具有2字节响应的I2C设备

⚠️
大家好. .谢谢你来到论坛。令人兴奋的消息!我们现在正在转移到新的论坛平台,它将提供更好的功能,包含在主对话网站中。所有岗位和账户都已迁移。我们现在只接受新论坛的流量-请在上面发布任何新帖子//www.wsdof.com/support。我们将在未来几天修复bug /优化搜索和标记。
9个帖子/ 0个新
最后发表
boydy1989
离线
最后看到:1年9个月前
加入:2017-10-18里
具有2字节响应的I2C设备

你好

我正在尝试接口到一个I2C传感器设备(https://docs-emea.rs-online.com/webdocs/142c/0900766b8142cdd9.pdf)

我已经成功地用另一个不同的传感器在14586上使用I2C设备。

这种新的传感器在发送PROM或ADC读请求时响应2或3字节的数据。

我已经基于I2C EEPROM示例编写了代码,并且无法让系统从应答中读取超过1个字节。

测试代码如下。我正在设置一个断点,并在调试器监视窗口中查看'byte1'和'byte2'。只有byte1填充了任何数据。
我尝试了一些不同的方法,但还是卡住了。我可以在我的示波器上看到设备正在回复2字节的数据,所以我很高兴基本的通信工作正常。

任何输入都非常感谢!

代码:

/ /关键部分
GLOBAL_INT_DISABLE ();

i2c_send_address(地址);

SEND_I2C_COMMAND (0 x0100);//设置R/W位为1 (read access)
//临界区结束
GLOBAL_INT_RESTORE ();
Uint16_t byte1 = 0;
Uint16_t byte2 = 0;

WAIT_FOR_RECEIVED_BYTE ();//等待收到的数据

byte1 = (GetWord16(I2C_DATA_CMD_REG) & 0xFF);//获取第一个接收的字节
byte2 = (GetWord16(I2C_DATA_CMD_REG) & 0xFF);//问题似乎就在这里……

WAIT_UNTIL_NO_MASTER_ACTIVITY ();//等待直到没有主活动

返回I2C_NO_ERROR;

设备:
MT_dialog
离线
最后看到:3个月1周前
工作人员
加入:2015-06-08 34
嗨boydy1989,

嗨boydy1989,

你调用SEND_I2C_COMMAND (0 x100)只有一个时间,这意味着58 x的I2C模块只能访问总线一读,所以实际上你只读一次,你不提供时钟你期望得到第二个数据,和奴隶需要时钟从主为了发送数据。例如,让我们以read_data_single()函数为例,在SDK的外围例子中,它一次读取32字节的数据,因此该函数将发送想要通信的设备的地址和读取指示,然后它将开始填充Tx FIFO读命令0 x100 (0 x100是一个虚拟的命令,只会生成时钟总线),尽可能多的读命令字节设备想读也是FIFO)(32字节,那么所有的32个字节可以读取接收FIFO。

由于MT_dialog

boydy1989
离线
最后看到:1年9个月前
加入:2017-10-18里
你好

你好

谢谢你的回复。

不过,我现在有点纠结,对SEND_I2C_COMMAND的任何调用都只会导致设备发送I2C设备地址(接收到一个ACK)。

我不能发送任何数据。

代码片段:
SEND_I2C_COMMAND (0 x1e);

逻辑输出附在PDF上。

我确信有一些简单的东西我错过了,所有的帮助非常感激。

MT_dialog
离线
最后看到:3个月1周前
工作人员
加入:2015-06-08 34
嗨boydy1989,

嗨boydy1989,

您一直使用的目标地址是0xEE吗?如果在设备发出停止条件之前不发送一个字节,I2C模块将继续发送它想要通信的设备的地址。在代码片段中,您只提供了一个SEND_I2C_COMMAND(0x1E),如果您已经正确地初始化了I2C模块,并且您只是使用SEND_I2C_COMMAND(0x1E)通过总线发出字节,那么我无法从中得出任何结论;然后你应该能够看到通过总线的字节,只要外部设备ack的数据由58x发送。如果你不想使用I2C SDK中的驱动程序,你可以使用它们作为参考来创建你自己的驱动程序。

由于MT_dialog

boydy1989
离线
最后看到:1年9个月前
加入:2017-10-18里

我的代码基于SDK中的驱动程序。

初始化代码:(从SDK中复制)

i2c_init(uint16_t dev_address, uint8_t speed, uint8_t address_mode, uint8_t address_size)
{
SetBits16 (CLK_PER_REG I2C_ENABLE 1);//使能I2C时钟
SetWord16 (I2C_ENABLE_REG 0 x0);//关闭I2C控制器
SetWord16(I2C_CON_REG, I2C_MASTER_MODE | I2C_SLAVE_DISABLE | I2C_RESTART_EN);// Slave被禁用
SetBits16 (I2C_CON_REG, I2C_SPEED,速度);/ /设置速度
# ifdef I2C_SS_FREQ_TRIM
SetWord16 (I2C_SS_SCL_HCNT_REG I2C_SS_SCL_HCNT_VAL);//设置SCL时钟高周期计数为标准速度
SetWord16 (I2C_SS_SCL_LCNT_REG I2C_SS_SCL_LCNT_VAL);//设置SCL时钟低周期计数为标准速度
# endif / / I2C_SS_FREQ_TRIM
# ifdef I2C_FS_FREQ_TRIM
SetWord16 (I2C_FS_SCL_HCNT_REG I2C_FS_SCL_HCNT_VAL);//设置SCL时钟高周期计数为快速
SetWord16 (I2C_FS_SCL_LCNT_REG I2C_FS_SCL_LCNT_VAL);//设置SCL时钟低周期计数为快速
# endif / / I2C_HS_FREQ_TRIM
SetBits16 (I2C_CON_REG I2C_10BITADDR_MASTER address_mode);//设置寻址模式
SetWord16(I2C_TAR_REG, dev_address & 0x3FF);//设置从设备地址
SetWord16 (I2C_ENABLE_REG 0 x1);//开启I2C控制器
WAIT_UNTIL_NO_MASTER_ACTIVITY ();//等待I2C主FSM变为IDLE状态
i2c_dev_address = dev_address;
WAIT_UNTIL_NO_MASTER_ACTIVITY ();//等待没有主活动
}

我已经为设备使用了正确的地址,就好像我改变了地址,我就不再在我的逻辑分析器上看到Ack。

我是否错误地发出字节?我希望只调用SEND_I2C_COMMAND(),并看到总线上的开始、地址、字节和停止。我只知道起点,地址,终点。

我已经连续放置了几个SEND_I2C_COMMAND(),但是仍然没有看到任何数据。

有没有办法确认586号收到Ack ?或者,有什么东西会阻止它接收Ack?

再次感谢!

MT_dialog
离线
最后看到:3个月1周前
工作人员
加入:2015-06-08 34
嗨boydy1989,

嗨boydy1989,

如果主(585)不会ACK从奴隶设备在每一个尝试,你写一些在公共汽车上主模块将继续发送地址,等待ACK,每个SEND_I2C_COMMAND()将导致试图定义的目标地址的主人与奴隶。如果主服务器没有从从服务器获得ACK,那么你将看不到你指示设备发送的字节。如果你没有得到一个ACK,那么附属的从设备有问题。关于检查如果ACK从外部设备已经收到,有一个函数i2c_eeprom.c叫i2c_wait_until_eeprom_ready()函数会发送一个虚拟字节(和检查ABRT_7B_ADDR_NOACK I2C_TX_ABRT_SOURCE_REG的如果没有ACK的奴隶将被设置为1,也就是说这个装置还没有破解这个地址。

由于MT_dialog

boydy1989
离线
最后看到:1年9个月前
加入:2017-10-18里
你好

你好

我现在有了一些进展,正在正确接收数据。谢谢你的帮助。

出于完整性的考虑,希望它能帮助别人在未来我将我的代码提取一个解释——我发现I2C控制器的微处理器的文档不是很清楚,不过我想我现在了解它。

下面的代码将在I2C总线上传输以下序列:
Addr_wr | reg_addr | addr_re | CLK | CLK

我必须替换WAIT_FOR_RECEIVED_BYTE()宏与while(GetWord16(I2C_RXFLR_REG) != 2);

我发现试图从FIFO读取数据会立即导致一个字节丢失。也许这和管道有关,我不确定。

我发现添加一个WAIT_FOR_RECEIVED_BYTE();SEND_I2C_COMMAND之间(0 x0100);调用产生足够的等待时间,使I2C控制器在总线上生成一个STOP条件。

另一个观察,我已经是一个相当强大的拉起/高14586年国家推动内部端口配置为I2C——我使用的设备已经相当薄弱的司机为其“低”,我不得不增加外部拉电阻器价值约47 k,只允许设备把总线低ACK。我注意到,即使没有上拉电阻,端口配置为没有上拉,当未驱动时,总线上仍然有一个高状态。这与我以前使用过的其他微处理器不同,后者对I2C使用开式收集器驱动器。Dialog对I2C硬件的结构作了一些澄清。

再次感谢您的帮助,我希望此信息能够帮助使用I2C设备的DA14585或DA14586设备的其他人!

I2c_error_code i2c_read_int16(uint32_t address, uint16_t *data)
{
Uint8_t byte1 = 0;
Uint8_t byte2 = 0;
/ /关键部分
GLOBAL_INT_DISABLE ();

i2c_send_address(地址);

SEND_I2C_COMMAND (0 x0100);//设置R/W位为1 (read access)
SEND_I2C_COMMAND (0 x0100);//设置R/W位为1 (read access)
而(GetWord16 (I2C_RXFLR_REG) ! = 2);//等待收到的数据

byte1 = 0xFF & GetWord16(I2C_DATA_CMD_REG);//接收字节
byte2 = 0xFF & GetWord16(I2C_DATA_CMD_REG);//接收字节

GLOBAL_INT_RESTORE ();
WAIT_UNTIL_I2C_FIFO_IS_EMPTY ();//等待Tx FIFO为空
WAIT_UNTIL_NO_MASTER_ACTIVITY ();//等待直到没有主活动
*数据= ((byte2 << 8) | byte1);
返回I2C_NO_ERROR;
}

MT_dialog
离线
最后看到:3个月1周前
工作人员
加入:2015-06-08 34
嗨boydy1989,

嗨boydy1989,

用于eeprom的驱动程序是相当完整和测试的,所以应该基于该驱动程序的结构,并使用它作为参考,根据您的观察。

  • 如果WAIT_FOR_RECEIVED_BYTE,我看不出改变的原因,宏是用来停止代码,等待设备从FIFO接收数据。
  • 直接从FIFO读取有字节丢失,不记得了。
  • 关于停止条件,一旦FIFO是空的,设备将自动发出一个停止条件,所以为了不看到一个停止条件,你将不得不保持你的FIFO满,这就是为什么大量的驱动程序执行读取32个字节(这是显示数据表的80页的第一段14.2.1启动和停止代允许传输FIFO空导致I2C控制器产生一个停止条件I2C总线)。
  • 关于你的最后观察,你是对的,如果你已经配置了I2C引脚的功能,那么内部的引体向上将自动激活,即使你没有明确配置它们(这是从数据表21页,映射的Px引脚自动配置一个上拉电阻(25kΩ)到由寄存器Px_PADPWR_CTRL_REG配置的电源。

由于MT_dialog

boydy1989
离线
最后看到:1年9个月前
加入:2017-10-18里
谢谢你的支持,

谢谢你的支持,所有的意见都被采纳了!