打印
[研电赛技术支持]

GD32 I2C应用深度剖析:从原理到实战项目

[复制链接]
22|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Puchou|  楼主 | 2025-2-13 15:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

40

帖子

0

粉丝