sj8zw8 发表于 2025-2-23 08:10

GD32E230与I2C传感器通信实现

通过 I2C 协议与温湿度传感器进行通信,是嵌入式系统中常见的操作。
GD32E230 作为一款基于 ARM Cortex-M0+ 的微控制器,具备丰富的外设支持,可以很方便地与 I2C 设备进行通信。
以下是实现与温湿度传感器通信的基本流程,包括配置 I2C 外设、读取数据、处理数据和使用中断优化性能的方式。


配置 I2C 外设
GD32E230 配备了 I2C 外设,首先需要配置 I2C 相关寄存器来启用通信。一般的配置步骤如下:

开启 I2C 时钟:首先需要确保 I2C 外设的时钟已开启。

c
rcu_periph_clock_enable(RCU_I2C0);
配置 I2C 引脚:为 I2C 通信配置适当的引脚,通常是 SCL 和 SDA。GPIO 配置如下:

c
gpio_init(GPIOB, GPIO_MODE_AF, GPIO_OSPEED_50MHZ, GPIO_PIN_6);// SCL
gpio_init(GPIOB, GPIO_MODE_AF, GPIO_OSPEED_50MHZ, GPIO_PIN_7);// SDA
I2C 参数配置:配置 I2C 工作模式、速率、地址等参数。以 100kHz 的标准模式为例:

c
i2c_deinit(I2C0);
i2c_master_mode(I2C0);
i2c_clock_config(I2C0, 100000);// 100kHz I2C 时钟
i2c_address_config(I2C0, 0x44, I2C_ADDR_7BIT);// 设备地址为 0x44
使能 I2C 外设:
c
i2c_enable(I2C0);
与传感器进行通信
接下来,我们需要通过 I2C 向温湿度传感器发送命令,并读取数据。以 SHT30 传感器为例,读取温湿度数据的流程如下:

发送命令:SHT30 传感器需要特定的命令才能开始测量。比如,发送测量命令。

c
uint8_t cmd[] = {0x2C, 0x06};// 启动测量命令
i2c_master_transmit(I2C0, 0x44, cmd, 2, I2C_SENDING_STOP);// 发送命令到地址为 0x44 的设备
读取数据:传感器返回的温湿度数据是 6 字节的格式,包括温度和湿度的原始数据。读取数据的过程如下:

c
uint8_t rx_data;
i2c_master_receive(I2C0, 0x44, rx_data, 6);
解析数据:解析传感器返回的数据,根据 SHT30 的文档,温度和湿度的原始数据可以通过公式转换为实际值。

c
uint16_t raw_temp = (rx_data << 8) | rx_data;
uint16_t raw_humidity = (rx_data << 8) | rx_data;
float temperature = -45 + 175 * ((float)raw_temp / 65535);
float humidity = 100 * ((float)raw_humidity / 65535);
使用中断优化性能
为了优化性能,尤其是在传感器数据采集过程中避免阻塞,可以利用 I2C 的中断机制来异步处理数据。

启用中断:在配置 I2C 时,可以使能 I2C 的中断功能,以便在数据传输完成时触发中断。

c
i2c_interrupt_enable(I2C0, I2C_INT_BUF | I2C_INT_EV | I2C_INT_ERR);
中断处理函数:在中断服务例程(ISR)中处理数据的接收。可以根据 I2C 中断状态来判断是否接收完成,或者是否出现错误。

c
void I2C0_EV_IRQHandler(void)
{
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE)) {
      uint8_t data = i2c_data_receive(I2C0);
      // 处理接收到的数据
    }
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) {
      // 数据发送完毕的处理
    }
}
通过中断的方式,可以在 I2C 数据传输过程中进行其他任务的处理,而不需要等待每次数据传输的完成。这种方式可以提高系统的响应速度和并发能力。

完整代码示例
c
#include "gd32e230.h"

#define SENSOR_ADDR 0x44// SHT30 地址

void i2c_init(void) {
    rcu_periph_clock_enable(RCPU_I2C0);
    gpio_init(GPIOB, GPIO_MODE_AF, GPIO_OSPEED_50MHZ, GPIO_PIN_6);// SCL
    gpio_init(GPIOB, GPIO_MODE_AF, GPIO_OSPEED_50MHZ, GPIO_PIN_7);// SDA
    i2c_deinit(I2C0);
    i2c_master_mode(I2C0);
    i2c_clock_config(I2C0, 100000);// 100kHz I2C 时钟
    i2c_address_config(I2C0, SENSOR_ADDR, I2C_ADDR_7BIT);
    i2c_enable(I2C0);
    i2c_interrupt_enable(I2C0, I2C_INT_BUF | I2C_INT_EV | I2C_INT_ERR);// 启用中断
}

void read_sensor(void) {
    uint8_t cmd[] = {0x2C, 0x06};// 启动测量
    i2c_master_transmit(I2C0, SENSOR_ADDR, cmd, 2, I2C_SENDING_STOP);

    uint8_t rx_data;
    i2c_master_receive(I2C0, SENSOR_ADDR, rx_data, 6);

    uint16_t raw_temp = (rx_data << 8) | rx_data;
    uint16_t raw_humidity = (rx_data << 8) | rx_data;
    float temperature = -45 + 175 * ((float)raw_temp / 65535);
    float humidity = 100 * ((float)raw_humidity / 65535);

    // 处理温湿度数据
}
结论
通过配置 I2C 外设和适当的中断机制,可以实现与 SHT30 或其他 I2C 温湿度传感器的高效通信。使用中断不仅能提高系统的响应能力,还能减少因等待数据传输完成而引起的处理时间浪费,适合高效的实时数据采集。

d1ng2x 发表于 2025-4-2 12:19

这I2C的话是硬件I2C,效果怎样

l1uyn9b 发表于 2025-4-2 13:26

之前说ST的油I2C的bug,GD的有没有啊?

g0d5xs 发表于 2025-4-2 14:23

I2C其实模拟I2C就行,主要是便于移植,比较方便

q1ngt12 发表于 2025-4-2 15:42

这个SHT30的地址一般是0x44?

p0gon9y 发表于 2025-4-2 16:53

话说I2C的速度这个可以设置为1M的速率吗

cen9ce 发表于 2025-4-2 19:55

原来配置I2C这么简单啊,用模拟I2C的话,感觉很难啊

lix1yr 发表于 2025-4-3 08:58

使能I2C的话,是不是就给I2C的端口,速率和地址配置好就行?

lamanius 发表于 2025-4-3 11:25

看这个例程还是比较通俗易懂的,很简单

suw12q 发表于 2025-4-3 14:06

如果想快的话,这个I2C应该是可以用DMA的吧

q1d0mnx 发表于 2025-4-9 18:07

100K的话对SHT30来说,够用不?
页: [1]
查看完整版本: GD32E230与I2C传感器通信实现