具有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填充了任何数据。
我尝试了一些不同的方法,但仍然存在。我可以在我的Ocilloscope上看到,设备正在回复2个字节的数据,因此我很高兴基本通信正常工作。

任何投入都非常感谢!

代码:

//关键部分
GLOBAL_INT_DISABLE ();

i2c_send_address(地址);

send_i2c_command(0x0100);//将R / W位设置为1(读取访问)
//关键部分结束
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个月3周前
工作人员
加入:2015-06-08 11:34
嗨Boydy1989,

嗨Boydy1989,

您只有一次调用send_i2c_command(0x100),这意味着58x的I2C模块只能访问一只读取的总线,因此您实际上只读一次,您就不会为您期望获得的第二个数据提供时钟,奴隶需要来自主站的时钟,以便将数据发送出来。例如,允许作为示例在SDK中的外围示例中的read_data_single()函数一次一次读取32字节的数据,因此该功能将发送想要通信的设备的地址和读取指示,然后它将开始使用读取命令0x100填充TX FIFO(0x100是一个凹陷的命令,该命令只会在总线上生成时钟),就像设备想要读取的字节一样多的读命令(32个字节也是FIFO。),然后可以从接收FIFO读取所有32个字节。

谢谢mt_dialog.

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

你好

感谢您的答复。

我现在正在努力努力,呼叫Send_i2c_command只会导致设备发送I2C设备地址(通过收到ACK)。

我无法发送任何数据。

代码片段:
SEND_I2C_COMMAND (0 x1e);

连接在PDF上的逻辑输出。

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

MT_dialog
离线
最后看到:3个月3周前
工作人员
加入:2015-06-08 11: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的驱动程序上基于我的代码。

init代码:(从SDK复制)

void i2c_init(uint16_t dev_address,uint8_t speed,uint8_t地址_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);//从站被禁用
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,0x1);//启用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个月3周前
工作人员
加入:2015-06-08 11:34
嗨Boydy1989,

嗨Boydy1989,

如果主机(585)在从从设备中获取ACK,则在每次尝试中为在总线上写入内容时,主模块将继续发送地址并等待ACK,每个SEND_I2C_COMMAND()将结果定义的目标地址以主机与从站通信。如果主设备没有从从机获得ACK,那么您不会看到您指示设备发送的字节。如果你没有得到一个ACK,那么附加的从设备有问题。关于检查是否已接收到外部设备的ACK,I2C_EEPROM.C中有一个名为i2c_wait_until_eeprom_ready()的函数,该函数将发送一个虚拟字节0x08,并检查i2c_tx_abrt_source_reg的abrt_7b_addr_noack位置,如果没有来自从站的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使用开式收集器驱动器。对对话框的一个澄清是I2C硬件结构的阐明。

再次感谢您的帮助,我希望这些信息有助于使用DA14585或DA14586设备使用I2C设备!

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(0x0100);//将R / W位设置为1(读取访问)
send_i2c_command(0x0100);//将R / W位设置为1(读取访问)
而(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 ();//等到没有主活动
* data =((byte2 << 8)| byte1);
返回i2c_no_error;
}

MT_dialog
离线
最后看到:3个月3周前
工作人员
加入:2015-06-08 11: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里
谢谢你的支持,

谢谢您的支持,所有评论都在船上服用!