I2c突发模式和提前停止

⚠️
大家好. .谢谢你来到论坛。令人兴奋的消息!我们现在正在转移到新的论坛平台,它将提供更好的功能,包含在主对话网站中。所有岗位和账户都已迁移。我们现在只接受新论坛的流量-请在上面发布任何新帖子//www.wsdof.com/support.我们将在未来几天修复bug /优化搜索和标记。
4个职位/ 0个新
最后发表
marcodg
离线
最后看到:2年11个月前
加入:2015-01-14 17:58
I2c突发模式和提前停止

你好,

我试着用i2c从加速计读取30个字节。大多数情况下它是有效的,但有时,主程序(DA14580)会发出一个STOP,把随后的数据弄乱。我在用i2c eeprom模块的代码来进行脉冲读取。

有什么明显的东西需要我注意吗?

谢谢,
马可

设备:
PM_Dialog
在线
最后看到:1分14秒前
工作人员
加入:2018-02-08 11:03
嗨marcodg,

嗨marcodg,

你的描述很通用,所以你能否提供更多的信息,为什么你的代码意外停止工作,以便指导你?您是否尝试在调试模式下运行代码并热连接调试器?你能解释一下你的代码是在哪里崩溃的吗?是NMI处理器还是WDOG攻击了?或者你的代码在你试图从加速计读取字节时在其他地方崩溃了?

谢谢,PM_Dialog

marcodg
离线
最后看到:2年11个月前
加入:2015-01-14 17:58
问题似乎在于

问题似乎在于读取数据的原子性。在i2c_eeprom.c中,我看到如下内容


//------------------------------------------------------------------------------------------
/ /关键部分
GLOBAL_INT_DISABLE ();
//获取接收到的数据
For (j = 0;j <大小;j + +)
{
WAIT_FOR_RECEIVED_BYTE ();//等待收到的数据
**p =(0xFF & GetWord16(I2C_DATA_CMD_REG));//获取接收的字节
(* p) + +;

//临界区结束
GLOBAL_INT_RESTORE ();
//------------------------------------------------------------------------------------------

我有读取加速度计的代码。问题是,我必须将地址和所有读命令的写入放入同一个临界区,才能让它工作。是这样的:


//------------------------------------------------------------------------------------------
/ /关键部分
GLOBAL_INT_DISABLE ();
i2c_send_address(地址);
For (j = 0;j <大小;j + +)
{
WAIT_WHILE_I2C_FIFO_IS_FULL ();//如果Tx FIFO已满,则等待
SEND_I2C_COMMAND (0 x0100);//设置读访问次数

//获取接收到的数据
For (j = 0;j <大小;j + +)
{
WAIT_FOR_RECEIVED_BYTE ();//等待收到的数据
**p =(0xFF & GetWord16(I2C_DATA_CMD_REG));//获取接收的字节
(* p) + +;

//临界区结束
GLOBAL_INT_RESTORE ();
//------------------------------------------------------------------------------------------

我不确定为什么关键部分是必要的,因为似乎一旦i2c状态机运行,它就会自己运行,而不受程序的干预。但是,很明显,如果我不这样做,就会偶尔产生一个错误的STOP,弄乱数据传输。也许这只是我们使用的加速度计(MMA845IQ)的问题。拥有如此大的临界区还会导致其他问题。

PM_Dialog
在线
最后看到:1分14秒前
工作人员
加入:2018-02-08 11:03
嗨marcodg,

嗨marcodg,

当数据的实际接收发生时,我们禁用/恢复中断。这是一种保护的类型,以确保没有中断将发生时,你把数据放入FIFO。请注意,当FIFO为空且没有其他数据时,您将获得一个STOP。因此,如果你不保护这个接收过程和中断是造成的,你将停止把数据放入FIFO, FIFO将是空的,你将得到一个停止。关键部分是当你把数据放入FIFO,而不是当FIFO推入数据。因此,在接收数据时,请不要删除禁用/恢复中断。

谢谢,PM_Dialog