树莓派开发(五)

I2C调试

Posted by 婷 on January 12, 2025 本文总阅读量

简介

记录树莓派上baremetal调试I2C的一些点

协议

总览

  • I2C一个master可以接多个slave

  • I2C总线使用两条线在master跟slave之间传输数据,SCL串行时钟线,SDA串行数据线

  • SCL跟SDA需要接上拉电阻,一般是4.7K,总线空闲时SCL和SDA处于高电平

    image-20250107221847760

  • 标准模式100Kbits/s,快速模式400Kbit/s

image-20250107222222606

起始与结束

  • 当 SCL 线是高电平时 SDA 线从高电平向低电平切换,这个情况表示通讯的起始。
  • 当 SCL 是高电平时 SDA 线由低电平向高电平切换,表示通讯的停止。

image-20250107222523968

示波器抓到的开始信号跟停止信号如下

70597599427f4f9aa8483e64217e9fc

a8535f9ff34ea218d98fefda450f87d

数据传输

I2C 总线在数据传输的时候要保证在 SCL 高电平期间,SDA 上的数据稳定,因此 SDA 上 的数据变化只能在 SCL 低电平期间发生,所以数据的采集需要看I2C高电平的时候SDA线的状态

image-20250108230929960

ACK跟NACK

  • SDA线上,ACK信号(应答)是低电平,NACK信号(非应答)是高电平。这部分比较好理解,因为空闲的时候总线上的上拉电阻会让SDA线为高。
  • 对于SDA线,master跟slave都可以控制其为输入或者输出状态
  • ACK/NACK的发生在发送完SDA线上发送8bit的data或者是7bit addr + 1bit rw之后,也即是每次传输的时候的第9个bit
  • ACK产生的情况:数据接收端(master/slave)如果希望对方继续发送数据,则发送ACK信号
  • NACK产生的情况:数据接收端希望结束数据传输,则对对方发送NACK信号,发送端收到该信号后会生成stop信号,结束此次传输
  • 当然如果是一个不存在的地址,自然SDA线再第九个时钟的时候自然是拉高的

读写过程

基本一帧的传输格式如下,每传输一个字节的内容,都要等1bit的应答信号

Read的时候为高电平,Write的时候为低电平

image-20250111153200152

当然连续读,连续写的时候,不一定每次都要StartStop信号都要来一遍

image-20250111153805845

比如下面的波形图,先是发送器件地址,然后读了两个字节,返回结果分别是0x20xa9

2dbb81622c098e81f907f7e377bdfff

image-20250111162921257

Start信号也可以重复,一般比如说读跟写交错这种情况(个人认为)

image-20250111154105654

如图,这是参考的网上的图

image-20250111154705174

尖峰毛刺

这个貌似比较容易出现,是一种控制真空的状态

image-20250111155022420

本次波形情况是主设备向从设备写数据,在寻址结束确认应答后,从设备会拉低总线,在SCL切换到低电平时,立即释放SDA,主设备还没有反应过来,造成了“控制真空”,这时SDA被上拉电阻拉高,而如果下一步主设备将传输低电平数据位,就会造成这个尖峰毛刺,原理如下图所示。

image-20250111155121828

具体波形

baremetal代码中,实现了i2c_detect,其原理是向总线上所有地址都读一个字节,如下是从器件被扫描到的时候抓的波形

fffab8773e9c5a4c06df8729a203a29

SDA线上的变化如下

image-20250111213942801

其中读方向以及ACK放大,如下所示

image-20250111214117450

最后的NACK以及Stop信号放大如下所示

image-20250111214208047

而如下所示为扫描一个不存在的从机的波形

39e77f9091955af9ae50da35a1bd52c

没有0x63这个从机,第9个bit的时候SDA就是高电平,也即NACK

image-20250111214540756

编码

controller

使用I2C1

gpio

使用GPIO2GPIO3

image-20250111215300631

image-20250105184136829

寄存器

控制器寄存器比较简单

image-20250111220413095

其中关于Status寄存器的描述,手册还是挺有意思的

image-20250111221037712

总之就是RXFTXERXRTXW这四个跟中断的一些条件配合使用

image-20250111220547235

image-20250111220846857

RXDTXD则是比较简单,查询模式用

image-20250111220608235

控制器的代码主要参考这个链接

问题记录

在跑代码的时候,对一个局部数组进行初始化,触发了异常

image-20250111221911469

从汇编一条条的跟,出问题的指令是xzr ,[sp, #34]

image-20250105212626629

ARM64必须要保证栈指针是8字节对齐的,这里是把SP+34的地址清零,所以这里触发了一个异常,不过现在也没有解决这个问题。反而单独对数组中的元素进行操作确实正常的,不理解。

image-20250111231405169

参考链接

代办

  • 10bit寻址

  • SMBUS
  • 中断模式,DMA模式
  • 总线挂死恢复
  • 总线仲裁参考
  • gpio模拟