一、I2C 总线概述
I2C(Inter - Integrated Circuit)总线由飞利浦公司开发,是一种简单、双向二线制同步串行总线,在电子设备通信领域地位重要。它仅用串行数据线(SDA)和串行时钟线(SCL)两根信号线,就能实现多设备间的数据传输,硬件连接便利,降低了电路板布线复杂度。
SDA 线负责传输数据位,在时钟信号同步下逐位传输数据;SCL 线产生稳定时钟脉冲,为数据传输提供精准时序基准。连接到 I2C 总线上的设备共享这两根信号线,通过设备地址区分彼此。I2C 总线有多种传输速率,如标准模式(100kbps)、快速模式(400kbps)以及高速模式(3.4Mbps),可适配不同外设的速度需求。
二、GD32 的 I2C 外设架构
GD32 微控制器集成的 I2C 外设遵循 I2C 总线标准规范,并进行了特色优化。硬件上,内置专门的 I2C 控制逻辑电路,精确把控 SDA 和 SCL 信号的生成、检测与处理。例如在数据传输时,控制逻辑依据设定波特率调节 SCL 时钟信号频率,保障数据按节奏传输。
其内部设有多个寄存器,分工明确。控制寄存器用于配置 I2C 的工作模式,如选择主机或从机模式、设置传输速率等关键参数;状态寄存器实时反馈 I2C 总线的运行状态,像总线是否忙碌、传输是否出错等信息,方便软件层面及时调整;数据寄存器充当数据临时存储区,发送数据先存放于此,接收的数据也会缓存进来。
三、I2C 工作模式详解
(一)主机模式
当 GD32 的 I2C 外设设为主机模式时,掌控总线控制权,主导数据传输。主机发起通信,先发送起始信号(START),接着发送从设备地址,精准定位目标。
在数据传输阶段,主机按位发送数据,并驱动 SCL 时钟信号。若要读取从设备数据,主机发送完地址后切换为接收状态,拉低 SCL 信号采样 SDA 线上的数据。传输结束时,主机发出停止信号(STOP),释放总线控制权。
(二)从机模式
处于从机模式的 GD32 等待主机召唤,时刻监听总线。检测到起始信号后,捕捉地址信息,若地址匹配则回应主机,准备通信。在数据接收过程中,从机遵循主机时钟节奏采样 SDA 线上的数据;发送数据时,也在主机时钟信号引导下逐位送出数据。从机模式使其能与各类 I2C 主设备协同工作。
四、I2C 通信协议基础
I2C 通信基于严谨协议,起始信号和停止信号是通信的 “开关”。起始信号为 SCL 高电平时,SDA 线由高电平向低电平跳变;停止信号是 SCL 高电平时,SDA 线从低电平到高电平跃变。
数据传输遵循 8 位字节格式,每传输一个字节,接收方在第 9 个时钟周期发送应答信号(ACK)或非应答信号(NACK)。ACK 表示数据接收无误可继续传输,NACK 则表示出现问题需暂停或调整。地址传输也按此规则,地址字节首位区分读(1)或写(0)操作,后续 7 位为具体设备地址,使主机能向从机读写数据。
五、GD32 I2C 寄存器配置
(一)I2C 控制寄存器(I2C_CTL0 和 I2C_CTL1)
I2C_CTL0 寄存器是配置关键入口,其位字段用于设定工作模式,如设为 1 启用主机模式,设为 0 切换到从机模式,还能微调时钟频率,设置分频值匹配期望传输速率。I2C_CTL1 寄存器侧重于控制辅助功能,如是否开启中断、应答信号生成方式等,为编程提供更多灵活性。
(二)I2C 状态寄存器(I2C_STAT0 和 I2C_STAT1)
I2C_STAT0 实时反馈总线基础状态,如是否检测到起始信号、当前传输阶段等关键信息,软件可轮询此寄存器,根据起始信号启动通信流程。I2C_STAT1 聚焦传输错误状态,如仲裁失败、应答错误等异常,软件能依据其提示纠错,保障通信顺畅。
(三)I2C 数据寄存器(I2C_DATA)
I2C_DATA 寄存器是数据 “搬运工”,发送数据时预先填充,硬件自动按时钟节奏逐位移出;接收数据时,采样一位就累积到该寄存器,一个字节接收完毕,软件即可读取处理。
六、GD32 I2C 软件编程基础
(一)初始化代码示例
#include "gd32f10x.h"
void i2c_init(void)
{
// 使能I2C时钟
rcu_periph_clock_enable(RCU_I2C0);
// 使能GPIO时钟
rcu_periph_clock_enable(RCU_GPIOB);
// 配置I2C引脚为复用开漏输出
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
// I2C控制寄存器配置
i2c_deinit(I2C0);
i2c_own_address1_set(I2C0, 0x30);
i2c_clock_speed_set(I2C0, I2C_SPEED, I2C_DTCY_2);
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x30);
i2c_enable(I2C0);
}
这段代码先开启相关时钟,接着配置 I2C 引脚模式,最后设置 I2C 控制寄存器各项参数,包括自身地址和时钟速度,完成初始化,为后续通信奠定基础。
(二)发送数据流程
发送数据时,先检查总线状态,确认空闲后发出起始信号,接着发送从设备地址与写操作标志,等待应答。若应答正常,逐字节发送数据,每发一字节检查应答,直至全部数据传输完毕,最后发出停止信号结束传输。
(三)接收数据流程
接收数据流程类似,先检查总线空闲、发起始信号、发带读操作标志的地址,收到应答后,主机准备接收。每接收一字节,适时发出应答或非应答信号,根据需求决定是否继续接收,全部接收完发出停止信号获取数据。
七、GD32 I2C 与 EEPROM 通信实例
(一)硬件连接
将 GD32 的 I2C 接口与 EEPROM 芯片对应连接 SDA 和 SCL 线,同时给 EEPROM 接上电源与地,确保正常上电工作。还要留意 EEPROM 的写保护引脚,合理设置电平防止误操作抹除数据。
(二)软件实现
// 向EEPROM写入数据
void eeprom_write(uint8_t *data, uint16_t addr, uint16_t len)
{
// 起始信号、地址发送等常规流程
i2c_start_on_bus(I2C0);
i2c_master_addressing(I2C0, EEPROM_ADDR, I2C_TRANSMITTER);
// 发送地址高位、低位
i2c_data_transmit(I2C0, (addr >> 8) & 0xFF);
i2c_data_transmit(I2C0, addr & 0xFF);
// 发送数据
for (uint16_t i = 0; i < len; i++)
{
i2c_data_transmit(I2C0, data[i]);
}
i2c_stop_on_bus(I2C0);
// 等待写入完成,可按EEPROM手册要求延时
}
// 从EEPROM读取数据
void eeprom_read(uint8_t *data, uint16_t addr, uint16_t len)
{
i2c_start_on_bus(I2C0);
i2c_master_addressing(I2C0, EEPROM_ADDR, I2C_TRANSMITTER);
i2c_data_transmit(I2C0, (addr >> 8) & 0xFF);
i2c_data_transmit(I2C0, addr & 0xFF);
i2c_start_on_bus(I2C0);
i2c_master_addressing(I2C0, EEPROM_ADDR, I2C_RECEIVER);
for (uint16_t i = 0; i < len - 1; i++)
{
data[i] = i2c_data_receive(I2C0);
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}
data[len - 1] = i2c_data_receive(I2C0);
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
i2c_stop_on_bus(I2C0);
}
代码展示了向 EEPROM 写入与读取数据的流程,从起始信号开始,到地址定位和数据传输,实现了数据的存与取。
八、GD32 I2C 在传感器数据采集的应用
(一)温湿度传感器(如 SHT3x 系列)
SHT3x 温湿度传感器采用 I2C 接口与微控制器通信。硬件连接好后,软件先初始化 I2C,接着向传感器发送测量指令,传感器采集温湿度后,GD32 通过 I2C 读取测量数据。
// 读取温湿度数据
void sht3x_read_data(float *temp, float *humi)
{
uint8_t send_buf[2] = {0x2C, 0x06};
uint8_t recv_buf[6];
i2c_start_on_bus(I2C0);
i2c_master_addressing(I2C0, SHT3X_ADDR, I2C_TRANSMITTER);
for (uint8_t i = 0; i < 2; i++)
{
i2c_data_transmit(I2C0, send_buf[i]);
}
i2c_stop_on_bus(I2C0);
// 适当延时等待测量完成
delay_1ms(20);
i2c_start_on_bus(I2C0);
i2c_master_addressing(I2C0, SHT3X_ADDR, I2C_RECEIVER);
for (uint8_t i = 0; i < 6; i++)
{
recv_buf[i] = i2c_data_receive(I2C0);
if (i < 5)
{
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}
}
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
i2c_stop_on_bus(I2C0);
// 数据处理转换为实际温湿度值
// 具体转换公式依据SHT3x手册
}
(二)光照传感器(如 BH1750)
BH1750 光照传感器通过 I2C 汇报光照强度数据。编程时先初始化 I2C,发送测量指令,接收传感器返回的数据,并依据其特性公式换算出光照强度,让 GD32 实时掌握环境光照情况。
九、I2C 通信中的故障排查与优化
(一)常见故障
起始 / 停止信号异常:可能是硬件线路受干扰,导致 SDA、SCL 电平跳变异常,或软件配置错误误触发信号。
应答错误:从设备未正确回应主机,原因包括地址不匹配、从设备故障、传输干扰等。
总线仲裁失败:多主机场景下,多个设备同时竞争总线控制权,协调不当会导致仲裁失败,通信受阻。
(二)排查手段
借助示波器查看 SDA、SCL 信号波形,检查起始 / 停止信号是否标准、时钟频率是否稳定、数据传输有无毛刺等异常。
在软件中增加详细的状态寄存器监测代码,实时打印总线状态,定位错误发生环节。
(三)优化策略
硬件方面:合理布线,采用屏蔽线减少电磁干扰;添加上拉电阻增强信号驱动能力。
软件层面:优化通信流程,增加错误重试机制,初次应答错误时稍作停顿后再次尝试通信,提升通信可靠性。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/pigliuxu/article/details/144707400
|