I2C Slave 中断回调未按预期进入 I2C_SLAVE_EVENT_STOP 问题
-
1. 问题背景
- 软件:ME05 SDK 1.3.1 I2C
- 硬件:ME05 EVB(FXOSC 8M)
- 背景描述:
- I2C 做从机的情况下,主机执行主机写(不带停止位)+主机读(带停止位),理论上 I2C Slave 中断回调中的 I2C_SLAVE_EVENT_STOP Case 只会在主机读完后进入,但实际上在主机写完的时候也进入了。

- 对 PTD4 的 IO 反转操作只在中断回调函 I2C_SLAVE_EVENT_STOP Case 里操作

2. 问题分析
- 根据 I2C 驱动可以确认 I2C_SLAVE_EVENT_STOP 有三种条件会进入:① 重复接收起始位; ② 收到到错误 ;③ 总线上有 stop bit。也确认客户 restart 指令属于 重复接收起使位(repeat start )
2.1 重复接收起始位
- I2C_DRV_SlaveIRQHandler 函数中 repeatStartDetect 就是对 重复接收起始位 情况的判断。当 repeatStartDetect 置 1,会执行 I2C_DRV_SlaveEndTransferHandler 函数,然后通过回调函数进入 I2C_SLAVE_EVENT_STOP Case


2.2 收到到错误
- I2C_DRV_SlaveIRQHandler 函数中会判断 BitError 和 FIFOError。当 I2C 从机出现错误的情况下会执行 I2C_DRV_SlaveEndTransferHandler 函数,然后通过回调函数进入 I2C_SLAVE_EVENT_STOP Case

2.3 总线上有 stop bit
- I2C_DRV_SlaveIRQHandler 函数中 stopDetect 就是对 总线上有 stop bit 情况的判断。当 stopDetect 置 1,会执行 I2C_DRV_SlaveEndTransferHandler 函数,然后通过回调函数进入 I2C_SLAVE_EVENT_STOP Case

3. 解决方案
3.1 Plan A
- 如果不需要使用 重复接收起始位 进 I2C_SLAVE_EVENT_STOP,并且 I2C 不是使用 DMA,并且使能了监听的情况下,可以直接把 I2C_DRV_SlaveIRQHandler 函数里 repeatStartDetect 的 I2C_DRV_SlaveEndTransferHandler 函数直接注释即可

- 关于 I2C 产生 error 也进入 I2C_SLAVE_EVENT_STOP,可以在回调函数 I2C_SLAVE_EVENT_STOP Case 里调用 I2C_DRV_SlaveGetTransferStatus 函数获取 i2c 状态,如果产生 error 函数的返回值是 STATUS_ERROR,因此可以通过返回值去判断是否发产生 error

- 注意事项:
- 此方案对 SDK I2C 驱动修改程度最小
- 此方案会导致主机发送主机写并且不发停止位情况下,无法获取主机写命令什么时候接收完成
3.2 Plan B
- 在 I2C_DRV_SlaveIRQHandler 函数里调用 I2C_DRV_SlaveEndTransferHandler 函数的位置加 log

- 然后在回调函数 I2C_SLAVE_EVENT_STOP case 里去判断对应的 log,然后做相应的处理

- 注意事项:
- 此方案对 SDK I2C 驱动修改程度较大
快速上手云途开发生态
发帖前请查看
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...