简介
I2C 集成电路总线,一种串行通信总线,使用多主从架构
由飞利浦公司在20世纪80年代为了让主板和嵌入式系统以连接低速周边设备而开发
正确读法 “I平方C” 或者"I方C"
而"I二C"是错误读法
-
I2C硬件连接方式
- 在物理连接上十分简单,分别由SDA(串行数据线),SCL(串行时钟线)及上拉电阻组成
- 通信原理是通过控制SCL和SDA高低电平来产生I2C总线协议所需要的信号进行数据传输
- 在总线空闲状态时,SCL和SDA会上拉电阻拉高,保持着高电平
- 通过其物理连接方式,我们就可以知道I2C协议是串行,同步通讯协议
-
特征
-
I2C总线上的每一个设备都会对应这唯一的I2C地址
-
部分从设备可以·通过外围电路来改变I2C地址
-
主从设备之间就通过这个地址来确定与哪个器件进行通信
-
I2C总线上的主设备和从设备之间以字节(8位)为单位进行双向的数据传输
-
-
通讯速率
-
然而只支持标准模式的设备不能向上兼容,因为它们不能支持更高的传输速率
-
所以说不能在更高速率的I2C总线系统中存在
协议详解
-
I2C协议规定,总线上数据的传输必须有个起始信号作为开始条件,以一个结束信号作为传输的停止条件
-
起始和结束信号均是由主设备产生,这也意味着从设备不可以主动发起通信,所以的设备都是主设备发起的
-
主设备可以发起询问的指令,然后等待从设备的通信
-
当总线在空闲状态时,SCL和SDA都保持着高电平
-
当SCL为高电平而SDA由高到低的跳变,表示产生一个起始信号
-
当传输结束时,SCL为高而SDA由低到高的跳变,表示产生一个停止条件
-
在起始条件产生后,总线处于忙状态,由于本次数据传输的主从设备独占总线,其它的I2C器件无法访问总线
-
在停止信号产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态
-
数据传输以字节单位,主设备在SCL线上产生每个时钟脉冲的过程中将SDA线上传输一个数据位
-
当一个字节按照数据位由高到低的顺序传输完后,紧接着从设备将拉低SDA线
- 回传给主设备一个应答位,此时才被认为一个字节真正的被传输完成
-
当然,并不是所有的字节传输都必须有一个应答位
- 比如说从设备不能再接收主设备(发送的)数据时,从设备将不回传应答位
RP2040 I2C主要参数
函数讲解
-
machine.I2C(i2c_id,scl,sda,freq=400000)
- I2C对象构造函数,作用为初始化对应I2C通道和引脚.
- i2c_id:使用I2C通道,可为0或者1;
- scl:SCL引脚,应为Pin对象(I2C0默认为9,I2C1默认为7)
- sda:SDA引脚,应为Pin对象(I2C0默认为8,I2C1默认为6)
- freq:I2C时钟频率,默认为400Kb/S
-
I2C.scan()
- 扫描从设备函数,返回所有I2C总线上挂载从设备7位地址的列表。
-
I2C.readfrom(addr, nbytes, stop=True)
- readfrom函数其作用为通过I2C总线从设备读取数据并返回字节串。
- addr:从设备地址。
- nbytes:读取字符长度。
- stop:是否在接收完成数据后发送结束信号。
-
I2C.readfrom_into(addr, buf, stop=True)
- readfrom_into函数其作用为readfro函数的升级版,可以将读取数据指定存放在字符数组中。
- addr:从设备地址
- buf:字符数组,用于存放数据
- stop:是否在接收完成数据后发送结束信号
-
I2C.writeto(addr, buf, stop=True)
- writeto函数其作用为向从设备写入数据。
- addr:从设备地址
- buf:发送字符串
- stop:是否在接收完成数据后发送结束信号
内存操作
- I2C.readfrom_mem(addr, memaddr, nbytes, *, addrsize=8)
- readfrom_mem函数其作用为从设备的寄存器中读取数据。
- addr:从设备地址
- memaddr:寄存器地址
- nbytes:读取字节长度
- addrsize:寄存器地址长度
添加了寄存器操作的函数:
-
I2C.readfrom_mem_into(addr, memaddr, buf, *, addrsize=8)
- readfrom_mem_into函数其作用为从设备的寄存器中读取数据到指定字符数组。
- addr:从设备地址
- memaddr:寄存器地址
- buf:字符数组,用于存放数据
- addrsize:寄存器地址长度
-
I2C.writeto_mem(addr, memaddr, buf, *, addrsize=8)
- writeto_mem函数其作用为将数据写入从设备的寄存器
- addr:从设备地址
- memaddr:寄存器地址
- buf:发送字符串
- addrsize:寄存器地址长度
软件I2C
以下函数,MircoPython标注为只用于软件I2C
- I2C.start()
- start函数其作用为在I2C总线中发送开始信号(SCL保持高电平,SDA转为低电平)
- I2C.stop()
- start函数其作用为在I2C总线中发送终止信号(SCL保持高电平,SDA转为低电平)
- I2C.readinto(buf, nack=True,)
- readinto函数其作用为从I2C总线读取数据到指定的字符数组,读取长度为字符数组的长度。
- buf:存放数据的字符数组
- nack:在接受最后一个数据后,是否发送nack信号
- I2C.write(buf)
- write函数其作用为将buf字符数组的数据写入到I2C总线中。
- buf:需要发送的字符数组
例程地址
实操
- pico 1
- USB to Miscro USB 数据线 1
- Pico Eval Board 1
查看原理图,Pico 的GPIO6和GPIO7连接到LSF0204,这是一个双向电压电平转换器,它可以在不同工作电压的
器件中传递电平信号,防止器件损坏
然后通过LSF0204连接到ICM-20948,这是一个九轴传感器,分别有3轴加速度/陀螺仪/磁力计
可以用于检测运动姿势,方位和磁场
ICM20948相对重要的寄存器
![[Pasted image 20220923224853.png]]
- WHO_AM_I ,只读寄存器,寄存器地址为0X00,其中内容用于识别设备,如果其中值为0XEA则可以判读该设备为ICM_20948
- RED_ADD_ACCEL_XOUT_H,只读寄存器,寄存器地址为0X2D,存放X轴加速度读取值高8位
- 接下来几个连续地址的寄存器,都是用来存放加速度XYZ三轴读取数值,可以用于连续读取获取数值
- REG_BANK_SEL,可读可写寄存器,用于切换USER BANK
- 以上几个指令均位于USER BANK0下,切换USER BANK可切换对应不同的寄存器组
可以理解为USER BANK为页数,寄存器为行数
程序讲解
简单程序1:
from machine import I2C,Pin
i2c = I2C(id=1,scl=Pin(7),sda=Pin(6),freq=100_000) # 初始化I2C通道1,使用引脚,I2C频率为100KHZ
addr_list = i2c.scan() # 使用扫描函数,扫描I2C总线下所有的设备地址,并返回对应的列表
# 判断是否只有一个设备连接到了I2C总线
if len(addr_list) == 1:
who = i2c.readfrom_mem(addr_lst[0],0x00,1)
# Identify ICM20948
if who[0] == 0xEA :
print("Just a ICM20948 connected")
else :
print("Have a device connected but it is not ICM20948")
# Nothing connected
elif len(addr_list) == 0:
print("Nothing connected")
# More than one device is connected
else :
print("More than one device is connected")