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 温湿度传感器的高效通信。使用中断不仅能提高系统的响应能力,还能减少因等待数据传输完成而引起的处理时间浪费,适合高效的实时数据采集。
这I2C的话是硬件I2C,效果怎样 之前说ST的油I2C的bug,GD的有没有啊? I2C其实模拟I2C就行,主要是便于移植,比较方便 这个SHT30的地址一般是0x44? 话说I2C的速度这个可以设置为1M的速率吗 原来配置I2C这么简单啊,用模拟I2C的话,感觉很难啊 使能I2C的话,是不是就给I2C的端口,速率和地址配置好就行? 看这个例程还是比较通俗易懂的,很简单 如果想快的话,这个I2C应该是可以用DMA的吧 100K的话对SHT30来说,够用不?
页:
[1]