- 背景
计划做一个基于wifi的家庭温度湿度监控装置,于是网购一温度湿度传感器模块HTU21D,采用3.3v电源供电,I2C接口。之前在迷你四轴上用过MPU6050,也是I2C接口的。将传感器连接到STM32C8最小系统板上后,移植迷你四轴中的软件模拟I2C协议代码,编写了HTU21D驱动程序,开始测试。 - 回合1
先试着读取了一下HTU21D的用户寄存器user_register的默认值,居然读到的是0x00,其默认值应是0x01。上示波器看波形,发现给出I2C的起始信号S正常,紧跟着的设备地址0x80信号给出后,SDA线在第9个时钟周期为高电平,收不到ACK。
由于这个I2C代码是以前用过的,代码应该没问题,并且读用户寄存器仅调用了I2C_Start()和I2C_WriteByte(uint8_t Data)函数就收不到ACK了,不会是对HTU21D的操作不符合它本身的指令和数据顺序的原因。考虑到之前遇到过I2C设备本身有故障,折腾了很久才发现,怀疑这个HTU21D是坏的。于是联系卖家,卖家说不会坏,于是发给我一个测试程序,让我用他的程序试试。把卖家发的hex文件烧进片子,串口助手看收到的数据,能正确测量温度和湿度。看来HTU21D是好的。 - 回合2
用卖家的程序测试时,在示波器上看到SCL周期为20us,I2C的位速率为50kbps。而我的程序I2C速率接近250k,于是怀疑是不是HTU21D不支持这么高的位速率。仔细看了下芯片手册,最高可以支持到400kbs。可是为什么用卖家的程序就没问题呢?两个不同的程序,使用的电路是完全一样的,STM32最小系统板和HTU21D传感器直接通过四根20cm左右的杜邦线连接的,边沿时间应该是一样的。
又从网上找了几个别人写的I2C程序和HTU21D程序,有C51内核的,有STM32的,但是都不能用,从程序代码上看都没什么问题。再转过头来修改自己的I2C程序,加长了位延时,把I2C位速率降了下来,通过示波器看和卖家给的程序波形一样了,把示波器探头从板子上取下来,通过串口助手看HTU21D的hold master方式下的测量数据,没有读数。 - 回合4
怀疑是波形的边沿时间过长,超出了HTU21D允许的上升沿时间。用示波器看上升时间,对比了卖家给的程序和我自己的程序的波形的上升时间,都是比HTU21D的数据手册给出的最大允许上升时间400ns要长的,应该是示波器的性能问题。上升沿时间由I2C总线上的上拉电阻的值和总线上的电容Cb有关。那么减小上升时间的手段就有2种,一是减小上拉电阻,而是减小总线电容。显然通过缩短导线来降低分布电容更简单,于是不用杜邦线了,直接把HTU21D通过一个一头儿是针另一头儿是座子的接插件连接到最小系统板上,再接上示波器,波形正常,程序运行正常,可以测量温度和湿度了。至此已证实确实是上升时间过长导致的问题。可是为什么卖家给的程序可以使用杜邦线呢?决定继续折腾。 - 回合5
改回杜邦线连接,再下载卖家给的程序,接上示波器,从串口助手看数据,一起正常。再下载我的程序,奇怪的是居然也可以正常测数据了。那之前有为什么不行呢?自习想了想,和前面回合3中唯一的不同就是,现在接了示波器探头。于是把探头从板子上断开,果然立即就没数据了。再把卖家的程序烧进去,这下发现,如果不接示波器也是无法测量的。看来是示波器探头改变了总线的分布电容。百度了“示波器探头对分布电容的影响”,确实如我猜测的那样,度娘告诉我们示波器的探头不仅由于加载效应使得测量的信号有失真,还会对被测电路产生影响。不过一般都只说示波器探头在测量MHz级的信号时才考虑探头对信号的影响,对于这个不到300kbps的I2C电路的上升时间也会产生影响确是没料到的。而且,网上的资料的提法是接示波器探头会使上升时间变长,可是这次我的经历似乎是示波器探头使上升时间缩短了。经过尝试,发现即使不接示波器,仅仅用手拿着金属镊子去夹着SCL线,也可以起到同样的效果,HTU21D可以测量温度和湿度。 - 回合6
用那个双头接插件可以解决问题,可是不方便固定。把HTU21D模块上的I2C上拉电阻从4.7k改为1k也许也能解决问题,可是那个电阻是0603的,我只有0805的。那么还有什么办法呢?忽然想到作为SCL和SDA两根线的杜邦线是并在一起的,撕开之后会不会有用呢?马上撕开试试,果然可以。两根杜邦线并在一起,分布电容较大,可以用类似平板电容的计算公式解释,导线相当于两个平板电极,绝缘层是电介质,导线间距就是电极平面之间的距离,距离越近,电容越大。
I2C电路故障排除---边沿时间与杜邦线
最新推荐文章于 2024-09-25 00:15:05 发布