热度 1| ||
如图是公司量产芯片i2c模块配置为slave模式(slave地址配置为8‘h6a)时一次传输利用示波器抓到的信号。start之后master写8’h6a,芯片回ack,master写8‘h11,芯片回ack,stop之后master发起restart,然后再次发送8‘h6b,此时芯片却回nack,按照设计此时硬件也是必须要回复ack的。那么问题到底出在哪里?是软件问题还是硬件问题?
补充说明:中断发生的条件为:
1、收到有效byte(地址或者数据)
2、检测到错误格式(byte数据没有接收完毕就收到start或stop)
3、有效byte后的stop
图中紫色信号表示中断,每次进中断了该信号就会翻转一次。
原因:I2C_CTL有个可写位BUS_R,写BUS_R会产生两个作用:释放hold住的SCL,复位内部的接收counter。收到byte后进入中断,这种情况下中断程序处理再慢也没有关系,因为此时电路设计会将SCL拉低hold住,master无法发送后续的数据,直到软件写了BUS_R释放SCL线才会开始接收数据。而收到stop进入中断,如果中断程序处理太慢了,后面的start和新数据已经在传输了,此时软件再去写BUS_R会复位内部的counter导致判断ack的时刻出错。
关键点就在于cpu响应中断的时间,在FPGA上抓到的波形显示,每次从发出I2C_IRQ到进入中断程序时间不一,一般都有50个HCLK(7.2M),STOP后的这个更长,接近100个HCLK,在经过了这段时间后,硬件已经接收了start并开始接收bit了。当硬件接收到start会将收到stop的标记位清零,而软件此时还在使用stop的标记位作判断,但此时查询到的状态已经不是stop了,在非stop的条件下对BUS_R有写操作,产生了如图所示的错误。