windman 发表于 2025-5-31 14:11:49

请教一个硬件I2C从机ACK应答信号的时序问题

<p>正常的I2C从机硬件中断的代码是这样的:</p>
<pre><code>void I2C_ISR_Handler() interrupt I2C_VECTOR
{
    //其它事件处理代码

    if (I2CSLST &amp; I2C_RXIF)// 0x20        处理RECV事件
    {
        I2CSLST &amp;= ~(I2C_RXIF | I2C_SLACKO);//SLACKO设置为0,应答ACK

      //接收数据处理代码
    }
}

</code></pre>
<p>我的问题是:这个SLACK0的应答ACK信号(拉低SDA),是(情况1)在I2CSLST被赋值的那一刻就被发送出去了,还是(情况2)要等到整个中断代码全部执行完毕,在中断返回语句 RETI 执行后才发送?</p>
<p>手册上只非常简单地讲了一句:“SLACKO:从机模式时,准备将要发送出去的 ACK 信号”,并没有说这个“将要”的任何时序问题。而ACK信号产生的时序问题,涉及到如果正确编写硬件I2C中断接收数据处理代码。所以万事不明找论坛,这里大佬荟萃、大神云集,希望能有老师给小弟答疑解惑,非常感谢。</p>

DebugLab 发表于 2025-6-1 01:19:51

一切时序以SCL为同步时钟,SCL由主机驱动,从机仅接收SCL,对SCL只读
ACK位,从机写,主机读
SCL前沿(下降沿)从机改变SDA电平(写SDA),时钟后沿(上升沿)主机锁存SDA电平(读SDA)
保证SCL前沿这个时间点之前SLACKO的状态正确即可




王昱顺 发表于 2025-6-1 10:11:07

进入接受中断的时候,其实是已经接受完了一整个数据,但是还没到ack(马上就到)
所以此时设置ack后是立刻发送
考虑到一般都是ack,所以可以初始化接受前设置一次即可


windman 发表于 2025-6-1 22:30:56

非常感谢两位版主的回复!
通过拜读两位大佬的赐教,是不是可以这样理解:对从机而言,SLACKO应答信号的产生,并没有固定的产生时机,也与从机I2C中断退出与否无关,只取决于主机的下一个SCL下降沿(由紧跟主机“写数据”指令的下一条主机“读ACK”指令产生 ?)什么时候到来。
若将上面的结论延伸开来,对于以数据帧为单位的I2C主从通讯来说,从机接收当前数据帧的正确与否判断(通过CRC效验正确与否来赋值I2CSLST的SLACKO位,以回应ACK还是NACK),必须在主机等待读ACK指令超时之前完成,这样才不会错过标准的I2C应答逻辑流程,而“人为”产生从机无应答(NACK)的逻辑错误。

不知道我这种理解和延伸推理是否正确,还请两位大佬不吝赐教,小弟这里先行谢过!
页: [1]
查看完整版本: 请教一个硬件I2C从机ACK应答信号的时序问题