树莓派资料
显示屏资料
系统下载
树莓派Pico
首页 动态 发帖 版块 我的
 退出
游客  
等级:
金币:
经验值:

I2C信号通讯协议 树莓派Pico RP2040【入门级教程】

  10615 
 0
 3
RASPI   RASPI 

Image


一:I2C通讯协议基础介绍

1. I2C信号基础介绍

I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,适用于短距离设备间的低速通信。广泛应用于各种单片机与传感器、EEPROM、LCD 模块等外围器件的短距离数据传输。其核心特点是仅需两根信号线即可实现双向通信,硬件成本低、布线简单,是单片机系统中最常用的通信接口之一。


I2C 通信仅依赖两根信号线,且需配合上拉电阻实现电平稳定,具体如下:

信号名称英文全称核心功能关键特性
SDASerial Data串行数据双向传输,用于发送 / 接收数据字节(8 位)
SCLSerial Clock串行时钟单向传输(由主设备生成),用于同步数据传输节奏

关键硬件细节:上拉电阻

SDA 和 SCL 均为开漏输出(Open-Drain) 结构,自身无法输出高电平,需通过外接上拉电阻(通常为 4.7kΩ~10kΩ,接 VCC)将电平拉至高电平。

当器件输出 “0” 时:引脚拉低,总线电平为低;

当器件输出 “1” 时:引脚高阻,总线电平由上拉电阻拉为高。

这种结构保证了多设备挂载时不会出现 “总线竞争”(即多个设备同时输出高低电平导致短路)。


2. I2C 信号的通信角色:主从模式

I2C 采用 “主从架构”,通信由主设备(如单片机) 发起和控制,从设备(如传感器) 仅被动响应,具体分工如下:


主从角色模式核心职责
主设备(Master)1.生成 SCL 时钟信号2.发起 “起始信号” 和 “停止信号"3.发送从设备地址(选择通信对象)4.控制数据传输方向(读 / 写)5.生成 “应答信号(ACK)” 或 “非应答信号(NACK)
从设备(Slave)1. 拥有唯一的 7 位或 10 位地址2. 检测总线地址是否与自身匹配3. 按主设备指令发送 / 接收数据4. 向主设备返回 ACK/NACK


注:I2C 总线支持多主设备(需避免冲突)和多从设备(最多 128 个 7 位地址从设备),但单片机系统中 99% 以上为 “单主多从” 场景。


3. I2C 信号的核心时序:5 个关键阶段

I2C 通信的完整过程由 “起始→地址→数据→应答→停止”5 个时序阶段组成,每个阶段的 SDA 和 SCL 电平变化严格定义,是协议正确性的核心。

1. 起始信号(Start Condition,S):通信开始的标志

时序定义:在 SCL 保持高电平期间,SDA 由高电平跳转为低电平(“高→低” 跳变)。

作用:告知总线上所有从设备 “通信即将开始”,从设备需准备接收后续地址信号。

波形示意图:


2. 从设备地址与读写控制:选择通信对象和方向

起始信号后,主设备会连续发送8 位数据,其中前 7 位为 “从设备地址”,第 8 位为 “读写控制位(R/W#)”:

第 8 位 = 0:表示主设备向从设备写数据(Write);

第 8 位 = 1:表示主设备从从设备读数据(Read)。


时序要求:

SCL 为高电平时,SDA 电平必须稳定(数据有效);

SCL 为低电平时,SDA 可跳变(准备下一位数据)。

示例:若从设备地址为 0x48(二进制1001000),主设备要向其写数据,则发送的 8 位为10010000(0x48 + 0);若要读数据,则发送10010001(0x48 + 1)。


3. 应答信号(ACK/NACK):数据接收确认

每传输 8 位数据(地址或数据字节)后,接收方需向发送方返回 1 位 “应答信号”,确认数据已接收:

ACK(应答):接收方在第 9 个 SCL 高电平期间,将 SDA 拉为低电平(表示 “已接收,可继续传输”);

NACK(非应答):接收方在第 9 个 SCL 高电平期间,将 SDA 保持高电平(表示 “未接收 / 接收完成”,主设备通常会终止通信)。


关键规则:

地址字节的应答方:从设备(确认地址匹配);

数据字节的应答方:

写操作时:从设备(确认数据接收);

读操作时:主设备(确认数据接收,若主设备无需更多数据,会返回 NACK)。

波形示意图(ACK):


4. 数据传输:8 位为单位的双向传输

地址和 ACK 确认后,进入数据传输阶段,每个数据单元为8 位(1 字节),传输方向由 “读写控制位” 决定:

写操作(主→从):主设备连续发送数据字节,每字节后等待从设备的 ACK;

读操作(从→主):从设备连续发送数据字节,每字节后等待主设备的 ACK/NACK(主设备要终止时发 NACK)。

时序要求:与地址传输一致 ——SCL 高电平时 SDA 稳定(数据有效),SCL 低电平时 SDA 跳变。

5. 停止信号(Stop Condition,P):通信结束的标志

时序定义:在 SCL 保持高电平期间,SDA 由低电平跳转为高电平(“低→高” 跳变)。

作用:告知总线上所有从设备 “本次通信结束”,从设备可进入空闲状态。

波形示意图:


4. I2C 信号的传输速率:三种常见模式

I2C 支持不同的传输速率,以适配不同的应用场景(速率越高,对布线和器件的要求越严格):


模式名称最大传输速率适用场景
标准模式(Standard-mode)100 kbps低速、长距离(如 1m 以上)、对稳定性要求高的场景
快速模式(Fast-mode)400 kbps中速、短距离(如 0.5m 内)温湿度传感器(SHT30)、OLED 
高速模式(Fast-mode Plus)1 Mbps高速、短距离(如 0.3m 以内)场景


注:部分高端器件支持 10Mbps 的 “超高速模式(High-speed mode)”,但单片机系统中极少使用。





5. 树莓派Pico开发板I2C引脚

在树莓派Pico开发板的引脚上有两个 I2C 控制器分别为(I2C0 和 I2C1)


其中代表I2C0的引脚如下:

SDA (数据): GPIO0 (默认) 或 GPIO4、GPIO8、GPIO12、GPIO16、GPIO20

SCL (时钟): GPIO1 (默认) 或 GPIO5、GPIO9、GPIO13、GPIO17、GPIO21


其中代表I2C1的引脚如下:

SDA (数据): GPIO2 (默认) 或 GPIO6、GPIO10、GPIO14、GPIO18、GPIO26

SCL (时钟): GPIO3 (默认) 或 GPIO7、GPIO11、GPIO15、GPIO19、GPIO27


二:树莓派Python使用I2C示例

1.初始化I2C引脚代码

使用 MicroPython 初始化 I2C 控制器:

from machine import Pin, I2C
import time

# 初始化I2C0,使用默认引脚
i2c0 = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000)

# 初始化I2C1,使用默认引脚
i2c1 = I2C(1, scl=Pin(3), sda=Pin(2), freq=400000)

print("I2C初始化完成")

2.扫描2C引脚代码

连接好 I2C的设备后,可以扫描总线上的设备地址:

from machine import Pin, I2C

# 初始化I2C
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000)

# 扫描I2C设备
devices = i2c.scan()

if devices:
    print("找到I2C设备:")
    for dev in devices:
        print(f"设备地址: 0x{dev:02x}")
else:
    print("未找到I2C设备")

3.I2C 数据发送与接收

以下是 I2C 主机发送数据到从设备和从从设备接收数据的示例:

from machine import Pin, I2C
import time

# 初始化I2C
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000)

# 假设我们有一个地址为0x48的I2C设备
DEVICE_ADDR = 0x48

def send_data(register, data):
    """向指定寄存器发送数据"""
    try:
        # 格式: i2c.writeto_mem(设备地址, 寄存器, 数据, 数据格式)
        i2c.writeto_mem(DEVICE_ADDR, register, bytes([data]), addrsize=8)
        print(f"已发送数据 0x{data:02x} 到寄存器 0x{register:02x}")
        return True
    except OSError as e:
        print(f"发送失败: {e}")
        return False

def receive_data(register, length):
    """从指定寄存器接收指定长度的数据"""
    try:
        # 读取数据
        data = i2c.readfrom_mem(DEVICE_ADDR, register, length, addrsize=8)
        print(f"从寄存器 0x{register:02x} 接收数据: {[hex(b) for b in data]}")
        return data
    except OSError as e:
        print(f"接收失败: {e}")
        return None

# 示例用法
if __name__ == "__main__":
    # 向寄存器0x00发送数据0xAA
    send_data(0x00, 0xAA)
    time.sleep(0.1)
    
    # 从寄存器0x01读取2字节数据
    receive_data(0x01, 2)


三:读取SHT30温湿度传感器I2C数据

SHT30是一款完全校准的线性化的温湿度数字传感器,增强了数字信号。采用I2C通讯,频率达1MHz。具有高可靠性及高稳定性,我们常见的SHT系列有三种型号:SHT30、SHT31、SHT35,其中比较便宜性价比较高的是 SHT30。在使用过程中需要用到 I2C 来通信。如果你没作更改过传感器,传感器的默认的从机地址是 0x44。它的供电是宽电压可输入2.15V-5.5V,可单次读取或周期性读取温度和湿度传感器数值,需要通过公式转换为摄氏度和相对湿度值。


四:引脚连接

接线如下图:分别将传感器的I2C引脚,SDA接GP0,SCL接GP1
Pico开发板SHT传感器
3.3vVCC
GNDGND
GP0SDA
GP1SCL

Image

五:Python源代码

SHT传感器Python源代码下载


1.下载源代码后,上传至树莓派Pico内,直接运行代码查看结果

Image



线性化的温湿度传感器测量到的环境温湿度数据是非常精准的!


六:传感器的其他资料

传感器详细参数产品手册CAD模型



关于更多SHT传感器详细参数可查看以下资料

https://sensirion.com/cn/products/catalog/SHT30-DIS-B

https://blog.csdn.net/weixin_44350337/article/details/141168150



标签:
作者签名: www.raspi.cc   楼主  2025-08-25 01:54:55
回复列表
Powered by RASPI _VERSION
© 2017-2025 树莓派极客版权
您的IP: 18.97.9.171 , 2025-11-12 20:12:11
Powered by RASPI _VERSION
© 2017-2025 树莓派极客版权