近来对 amigo 开发期间的遇到 I2C 问题做一下总结。

我们发现有一些 I2C 设备搜索不到,主要原因是 DATA 的信号衰减,也可能是 I2C 的总线被拉住了。

软件层面的问题

例如在实现 Amigo 音频设备,录音与播放切换和重入功能实现,主要问题是 I2C 的传输超时问题。

如 amigo 的 ES8374 在通过 I2C 配置设备播放后,一条 4 设备的 I2C 变得很不稳定,排查后,发现通信失败后, SDA 脚失败后持续为低,理论上 I2C 驱动应该在判断接收数据失败后,恢复为 高, 但实际上没有,所以现在的解决方法是重新配置为 GPIO 后手动拉高,然后就可以重新继续工作了。

关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。-LMLPHP

这个问题是因为 I2C 从机端 K210 给出数据,从机应答了,并且拉低的数据线表示我知道了,要返回数据,但实际上并没有返回,而造成的结果就是,主机在等待从机的应答数据,从机也在等待主机的下一次读取请求,但谁也没办法继续运行了,理论上 K210 端在发现超时退出后应当恢复 I2C 总线的现场准备下一次的请求读取,但实际并没有进行这样预期的处理,所以临时的修复方案可以如下图。

关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。-LMLPHP

附带代码:


# read reg value
def _readReg(self, regAddr):
while True:
try:
self.i2c_bus.writeto(self.i2c_addr, bytes([regAddr]))
return (self.i2c_bus.readfrom(self.i2c_addr, 1))[0]
except OSError as e:
#print(e)
from fpioa_manager import fm
from Maix import GPIO
tmp = fm.fpioa.get_Pin_num(fm.fpioa.I2C1_SDA)
fm.register(tmp, fm.fpioa.GPIOHS15)
sda = GPIO(GPIO.GPIOHS15, GPIO.OUT)
sda.value(1)
fm.register(tmp, fm.fpioa.I2C1_SDA, force=True) # write value to reg
def _writeReg(self, regAddr, data):
while True:
try:
return self.i2c_bus.writeto_mem(self.i2c_addr, regAddr, data, mem_size=8)
except OSError as e:
#print(e)
from fpioa_manager import fm
from Maix import GPIO
tmp = fm.fpioa.get_Pin_num(fm.fpioa.I2C1_SDA)
fm.register(tmp, fm.fpioa.GPIOHS15)
sda = GPIO(GPIO.GPIOHS15, GPIO.OUT)
sda.value(1)
fm.register(tmp, fm.fpioa.I2C1_SDA, force=True)

需要注意的是,这个问题,应该迟早要在 BSP SDK 层面得到解决,内部的资源执行方式出了问题,考虑不周全。

硬件层面的问题

刚才我们说的是从软件的角度发现问题,而另一种情况是完全于软件无关的情况。

同一份代码,如下读取 RGB Sensor 的代码,在 ESP32 上可以正常工作,但在 K210 上则无法正常工作,操作逻辑保持一致,也不受到执行时序的影响,从逻辑分析上出现的结果如下图。

关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。-LMLPHP

可以看到后者 K210 的信号发出后,从机并没有做出 ACK 操作 DATA 线的应答,那此时的问题会是什么呢?

我们接一台示波器就可以发现了,主要原因是实际的信号有差异。

关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。-LMLPHP

关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。-LMLPHP

嗯,衰减的那个就是 K210 的(时好时坏),这种信号从机芯片不一定可以识别得到,实际输出的信号与 下方 ESP32 输出的信号对比一下就存在差距。

关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。-LMLPHP

剩下就自己想想有什么办法了,通常来说芯片 IO 上拉能力不够可能会有这种现象,但实际是不是这样呢?我们还是得检讨一下硬件线路和软件IO配置才能解决具体的问题了,这已经超过了我对本质问题的理解,等我之后能完美解决再做出解答吧。

注意,最近得到了解到 I2C 的总线上存在上拉电阻的差异,通常 I2C 都是开漏输出,所以需要一个外部的弱上拉电阻,那上拉电阻应该要多少呢,这里有一个参考 IIC为什么绝大多数时候都是带有上拉电阻呢? , 这件事早在 STM32 时期就存在这些现象了,大多数人不会用硬件的 I2C ,然后都用 软 I2C 的 GPIO 的推挽输出来解决问题了,但实际上只是不了解应该要如何配合那个硬 I2C 的上拉。

关于 K210 MaixPy 的 I2C 读取设备,搜索不到设备,通信失败的一些原因以及解决方案。-LMLPHP

如果使用 GPIO 上拉就可以将它恢复到最开始的状态。

下次再说说 SPI 存在的问题吧~。

05-21 15:29