微雪树莓派PICO笔记——6. I2C(集成电路总线)

9 篇文章 12 订阅

简介

I2C 集成电路总线,一种串行通信总线,使用多主从架构
由飞利浦公司在20世纪80年代为了让主板和嵌入式系统以连接低速周边设备而开发

正确读法 “I平方C” 或者"I方C"
而"I二C"是错误读法

  • I2C硬件连接方式
    - ![[Pasted image 20220923220530.png]]

    • 在物理连接上十分简单,分别由SDA(串行数据线),SCL(串行时钟线)及上拉电阻组成
    • 通信原理是通过控制SCL和SDA高低电平来产生I2C总线协议所需要的信号进行数据传输
    • 在总线空闲状态时,SCL和SDA会上拉电阻拉高,保持着高电平
    • 通过其物理连接方式,我们就可以知道I2C协议是串行,同步通讯协议
  • 特征

    • I2C总线上的每一个设备都会对应这唯一的I2C地址

    • 部分从设备可以·通过外围电路来改变I2C地址![[Pasted image 20220923221234.png]]

    • 主从设备之间就通过这个地址来确定与哪个器件进行通信

    • I2C总线上的主设备和从设备之间以字节(8位)为单位进行双向的数据传输

  • 通讯速率

    • ![[Pasted image 20220923221536.png]]

    • 然而只支持标准模式的设备不能向上兼容,因为它们不能支持更高的传输速率

    • 所以说不能在更高速率的I2C总线系统中存在

协议详解

![[Pasted image 20220923222134.png]]

  • I2C协议规定,总线上数据的传输必须有个起始信号作为开始条件,以一个结束信号作为传输的停止条件

  • 起始和结束信号均是由主设备产生,这也意味着从设备不可以主动发起通信,所以的设备都是主设备发起的

  • 主设备可以发起询问的指令,然后等待从设备的通信

  • 当总线在空闲状态时,SCL和SDA都保持着高电平![[Pasted image 20220923222543.png]]

  • 当SCL为高电平而SDA由高到低的跳变,表示产生一个起始信号![[Pasted image 20220923222604.png]]

  • 当传输结束时,SCL为高而SDA由低到高的跳变,表示产生一个停止条件![[Pasted image 20220923222738.png]]

  • 在起始条件产生后,总线处于忙状态,由于本次数据传输的主从设备独占总线,其它的I2C器件无法访问总线![[Pasted image 20220923222927.png]]

  • 在停止信号产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态![[Pasted image 20220923223116.png]]

  • 数据传输以字节单位,主设备在SCL线上产生每个时钟脉冲的过程中将SDA线上传输一个数据位

  • 当一个字节按照数据位由高到低的顺序传输完后,紧接着从设备将拉低SDA线

    • 回传给主设备一个应答位,此时才被认为一个字节真正的被传输完成![[Pasted image 20220923223448.png]]
  • 当然,并不是所有的字节传输都必须有一个应答位

    • 比如说从设备不能再接收主设备(发送的)数据时,从设备将不回传应答位![[Pasted image 20220923223650.png]]

RP2040 I2C主要参数

![[Pasted image 20220923223758.png]]

函数讲解

  • 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:需要发送的字符数组

例程地址

MicroPython源码

实操

  • pico 1
  • USB to Miscro USB 数据线 1
  • Pico Eval Board 1

查看原理图,Pico 的GPIO6和GPIO7连接到LSF0204,这是一个双向电压电平转换器,它可以在不同工作电压的
器件中传递电平信号,防止器件损坏
![[Pasted image 20220923224601.png]]

然后通过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")
        

微雪PICO教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值