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

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

软件层面的问题

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

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

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

附带代码:


# 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 的信号发出后,从机并没有做出 ACK 操作 DATA 线的应答,那此时的问题会是什么呢?

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

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

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

补 2020年9月9日

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

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

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

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

  1. PHP读取sphinx 搜索返回结果完整实战实例

    PHP读取sphinx 搜索返回结果完整实战实例 网上搜索N久都没有一个正在读取返回sphinx结果的实例,都是到了matches那里就直接var_dump或者print_r了,没有读取到字段的例子, ...

  2. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...

  3. Linux 设备驱动之字符设备

    参考转载博客:http://blog.chinaunix.net/uid-26833883-id-4369060.html https://www.cnblogs.com/xiaojiang1025/ ...

  4. [kernel]字符设备驱动、平台设备驱动、设备驱动模型、sysfs几者之间的比较和关联

    转自:http://www.2cto.com/kf/201510/444943.html Linux驱动开发经验总结,绝对干货! 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动 ...

  5. C# 实现自定义的USB设备与上位机进行通信(上位机部分)

    因为以前没用过USB,对USB也不了解,于是上网查了很多资料,不过网上的资料都是零零散散,不清不楚的,于是我自己总结了一下,下面几个链接是网上这么多零散资料里,我觉得比较有参考意义的. USB设备连接 ...

  6. windows核心编程---第九章 同步设备IO与异步设备IO之同步IO

    同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请求后并不会挂起而是继续执行.IO完毕后会得到设备的通知.而IO完成端口就是实现这种通知的很 ...

  7. 深入浅出:Linux设备驱动之字符设备驱

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...

  8. 【转】深入浅出:Linux设备驱动之字符设备驱动

    深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...

  9. 蜕变成蝶~Linux设备驱动之watchdog设备驱动

    看门狗(watchdog )分硬件看门狗和软件看门狗.硬件看门狗是利用一个定时器 电路,其定时输出连接到电路的复位端,程序在一定时间范围内对定时器清零 (俗称 “喂狗”),如果程序出现故障,不在定时周 ...

随机推荐

  1. 前端Web APIS

    day01 - Web APIs 学习目标: 能够通过ID来获取元素能够通过标签名来获取元素能够通过class来获取元素能够通过选择器来获取元素能够获取body和html元素能够给元素注册事件能够修改 ...

  2. 使用Arcgis时,在sde空间库常用的相关函数

    一.Oracle库中配置好sde空间库常见的场景 1.在sde库中创建表:community 创建表:community 字段:id(INTEGER), shape(ST_GEOMETRY) 2.往s ...

  3. 23种设计模式 - 数据结构(Composite - iterator - Chain of Responsibility)

    其他设计模式 23种设计模式(C++) 每一种都有对应理解的相关代码示例 → Git原码 ⌨ 数据结构 Composite 动机(Motivation) 软件在某些情况下,客户代码过多依赖于对象容器复 ...

  4. js中map()、some()、every()、filter()的区别

    js的Array对象有map.some.every.filter几个方法都能对数组中的每个对象进行处理,但是他们之间的功能又各有差别,所以在记下. map():通过指定函数处理数组的每个元素,并返回处 ...

  5. css学习入门-第一个css程序

    1.css的优势: --内容与表现分离 --网页结构统一,可以实现复用 --样式丰富 2.css的3种导入方式 2.1行内样式 <h1 style="color: red"& ...

  6. Stack (30)(模拟栈,输出中间数用set)

    Stack is one of the most fundamental data structures, which is based on the principle of Last In Fir ...

  7. C++中的输入输出

    update&fixed: 经过实测,io解绑在各大oj以及本地评测软件上都劣于scanf 所以在大数据的情况下还是推荐尽量使用scanf! ! ! ! 众所周知,C++自带了各种输入方式 比 ...

  8. Java反射(一)

    什么是反射? 在程序的运行过程中,可以动态的创建对象. 反射的基石是什么? 字节码对象是反射的基石.字节码对象:Java类文件通过javac进行编译后生成的xxx.class文件,此文件由jvm加载至 ...

  9. 剑指 Offer 54. 二叉搜索树的第k大节点

    题目描述 给定一棵二叉搜索树,请找出其中第k大的节点. 示例1: 输入: root = [3,1,4,null,2], k = 1 3 / \ 1 4 \ 2 输出: 4 示例2: 输入: root ...

  10. 使用代码生成工具快速生成基于ABP框架的Vue+Element的前端界面

    世界上唯一不变的东西就是变化,我们通过总结变化的规律,以规律来应付变化,一切事情处理起来事半功倍.我们在开发后端服务代码,前端界面代码的时候,界面都是依照一定的规律进行变化的,我们通过抽取数据库信息, ...