I2C — 双板主机轮询通信 I2C_TwoBoard_CommunicationMaster_Polling
固件库: PY32F403_Firmware V1.4.5
芯片: PY32F403(Cortex-M4)
源文件:PY32F403-STK/Example/I2C/I2C_TwoBoard_CommunicationMaster_Polling/Src/main.c
核心外设: I2C1(主机,100K,轮询)
1. 功能简介(大白话)
拿 两块 PY32F403-STK,一块当 主机(Master),一块当 从机(Slave)。主机按下用户键后,先通过 I2C 给从机发 15 个字节(1,2,...,15),发完再把从机回发的 15 个字节收回来。最后主机比较「发出去的是不是等于收回来的」:相等则点亮 LED,不相等就 LED 闪烁报错。
和 SPI 例程不同,I2C 是半双工——这里是「先发后收」两步完成,而不是同时收发。
2. 硬件准备
| 物品 | 数量 | 说明 |
|---|---|---|
| PY32F403-STK 开发板 | 2 | 主机烧 Master_Polling,从机烧 Slave_IT(或对应 Slave 例程) |
| USB 线 | 2 | 供电 + 下载 |
| 上拉电阻 4.7kΩ | 2 | SCL、SDA 各一(开发板通常已带上拉) |
接线(两根线交叉对应,务必共地):
|
|
STK 板上的 I2C1 引脚(PB6/PB7)一般已板载上拉电阻;若自己搭电路务必外接 4.7kΩ 上拉到 VCC。
操作步骤:
- 主机烧
I2C_TwoBoard_CommunicationMaster_Polling,从机烧I2C_TwoBoard_CommunicationSlave_IT; - 先复位从机,再复位主机;
- 按主机用户键启动通信;
- 主从 LED 由灭变常亮 = 成功;任一 LED 闪烁 = 失败。
3. 完整代码(带中文注释)
|
|
附:MSP 里的引脚配置(HAL_I2C_Init 自动调用)
|
|
4. 代码分段讲解
4.1 为什么 SCL/SDA 必须是「开漏 + 上拉」?
I2C 是多设备共用一条线的总线,任何一个器件都可能拉低它。若用推挽输出,两个器件一个拉高一个拉低就会短路。开漏保证「谁想拉低谁拉低,平时靠上拉电阻维持高电平」,多个器件不会互相打架——这是 I2C 能「一总线挂多设备」的物理基础。所以引脚模式务必是 GPIO_MODE_AF_OD。
4.2 先发后收:半双工的体现
代码里 HAL_I2C_Master_Transmit(发)和 HAL_I2C_Master_Receive(收)是两次独立调用。I2C 总线同一时刻只能单向传,所以主机要先写完、回到 READY,再启动读。每步都检查 HAL_I2C_GetState == READY 确保上一步彻底结束。
4.3 地址 0xA0 是什么?
本 demo 里主机 OwnAddress1 和对外寻址都用了 0xA0。这是示例自定义的地址,主从必须一致才能通信。实际接真实芯片(如 EEPROM AT24C02)时,要换成该芯片手册规定的地址(通常 7 位如 0x50),并注意 HAL 接口传的是 7 位地址。
4.4 时钟拉伸(Clock Stretching)
NoStretchMode = DISABLE 表示允许从机在忙时把 SCL 拉低「拖住」主机,等自己准备好再放开。很多传感器(如 SHT30)靠这招告诉主机「稍等」。保留默认允许即可。
4.5 速率怎么改?
直接改 I2C_SPEEDCLOCK:100000(标准)、400000(快速)。注意提高速率要保证上拉电阻合适、总线不长,否则波形失真。
5. 实验现象
- 正确接线、先跑从机再按主机按键后:
- 主机 LED 常亮 = 收发校验成功;
- 任一板 LED 闪烁 = 通信失败(检查接线、共地、地址、上拉)。
6. 常见问题
| 现象 | 原因 | 解决 |
|---|---|---|
| LED 一直闪(失败) | 没上拉 / 没共地 / 线接反 | 加 4.7k 上拉、接好 GND、SCL-SCL/SDA-SDA |
| 完全无响应、卡在发送 | 从机没先启动 | 先复位从机,再复位/按键启动主机 |
| 偶发通信错误 | 上拉太弱 / 速率过高 / 总线长 | 减小上拉电阻、降到 100K、缩短走线 |
| 接真实 EEPROM 不响应 | 地址不对(7 位 vs 8 位) | 用器件手册的 7 位地址;写后延时再读 |
| 读到全 0xFF | 从机没回数据 / 上拉缺失 | 查上拉与从机程序是否匹配 |
| 想提速 | 改 I2C_SPEEDCLOCK | 400K 需更优的上拉与时序 |
7. 小结
- I2C 是两线、半双工、多主从总线,靠地址选设备,靠开漏+上拉实现多设备共线;
- 例程用 I2C1(APB1=8MHz)100K,主机轮询「先发 15 字节、再收 15 字节」;
- 引脚必须 开漏 + 上拉(PB6/PB7,AF1),否则总线拉不高;
- 主从地址、速率必须一致,且从机要先于主机就绪;
- 校验方法是「发出去的 == 收回来的」逐字节比较。
8. 拓展应用(学了能做什么项目)
- 参数存储:参考
I2C_xxx_DMA_MEM,用 AT24Cxx 保存配置、校准值,断电不丢; - 环境传感器:挂 SHT30(温湿度)、BMP280(气压)、MPU6050(姿态),做气象站;
- 实时时钟:接 DS3231 做带断电走时的电子钟;
- OLED 显示:SSD1306(I2C 版)小屏,做菜单/状态显示;
- IO 扩展:PCF8574 扩展按键/LED,省 MCU 引脚;
- 非阻塞进阶:把轮询换成
I2C_xxx_IT/I2C_xxx_DMA,主循环不卡等,适合复杂项目。
返回:I2C 总线总览