STM32模拟IIC时序解析与SHT30温湿度数据采集实战

发布时间:2026/6/17 10:01:29

STM32模拟IIC时序解析与SHT30温湿度数据采集实战 1. STM32模拟IIC通信基础在嵌入式开发中IICInter-Integrated Circuit是一种常用的串行通信协议。当STM32的硬件IIC外设不可用或存在资源冲突时通过GPIO模拟IIC时序就成为必备技能。模拟IIC的核心在于用软件精确控制SCL时钟线和SDA数据线的电平变化模拟出标准IIC协议的时序。IIC协议有几个关键特征它采用主从架构只需要两根线SCL和SDA就能实现多设备通信支持多主机和从机每个设备都有唯一的7位地址。在模拟实现时我们需要特别注意四个基本时序起始条件Start Condition、停止条件Stop Condition、数据有效性Data Valid和应答ACK/NACK。模拟IIC相比硬件IIC最大的优势是灵活性强。你可以自由选择任意GPIO引脚作为SCL和SDA不受硬件外设引脚限制。我在实际项目中就遇到过硬件IIC引脚被其他功能占用的情况这时模拟IIC就成了救命稻草。不过要注意模拟IIC会占用更多CPU资源在高速通信场景下可能不如硬件IIC稳定。2. SHT30温湿度传感器解析SHT30是Sensirion公司推出的一款高精度数字温湿度传感器相比常见的DHT11/DHT22它具有更高的测量精度±1.5%RH湿度精度±0.2℃温度精度和更快的响应速度。传感器采用IIC接口默认地址是0x44也可配置为0x45工作电压范围2.4V-5.5V非常适合嵌入式应用。SHT30的测量模式分为单次测量和周期测量两种。单次测量模式下每次读取数据都需要发送测量命令周期测量模式下传感器会定期自动测量并缓存结果。在实际使用中我发现单次测量模式更适合低功耗应用因为传感器在非测量时段可以进入休眠状态。传感器输出的原始数据是16位数字量需要通过特定公式转换为实际温湿度值。温度转换公式为Temperature -45 175 × (tem/65535)湿度转换公式为Humidity 100 × (hum/65535)。这些转换在代码中需要特别注意数据类型处理避免精度丢失。3. 模拟IIC关键代码实现3.1 GPIO初始化与基本时序函数首先需要配置用于模拟IIC的GPIO引脚。以STM32F1系列为例我们选择PA5和PA6分别作为SCL和SDAvoid SHT30_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); SCL 1; SDA_OUT 1; }起始信号和停止信号是IIC通信的基础。起始信号在SCL高电平时SDA从高变低停止信号在SCL高电平时SDA从低变高void IIC_Start(void) { IIC_OUTPUT_MODE_SET(); SDA_OUT 1; SCL 1; delay_us(4); SDA_OUT 0; delay_us(4); SCL 0; } void IIC_Stop(void) { IIC_OUTPUT_MODE_SET(); SCL 0; SDA_OUT 0; delay_us(4); SCL 1; delay_us(4); SDA_OUT 1; delay_us(4); }3.2 数据收发与应答处理数据发送函数需要按位发送一个字节高位在前。每个bit在SCL低电平时准备数据在SCL高电平时保持稳定void IIC_SendByte(u8 byte) { u8 BitCnt; IIC_OUTPUT_MODE_SET(); SCL 0; for(BitCnt 0; BitCnt 8; BitCnt) { if(byte 0x80) SDA_OUT 1; else SDA_OUT 0; byte 1; delay_us(2); SCL 1; delay_us(2); SCL 0; delay_us(2); } }数据接收函数则需要将SDA配置为输入模式同样按位读取u8 IIC_RcvByte(void) { u8 retc 0; u8 BitCnt; IIC_INPUT_MODE_SET(); delay_us(1); for(BitCnt 0; BitCnt 8; BitCnt) { SCL 0; delay_us(2); SCL 1; retc retc 1; if(SDA_IN) retc | 1; delay_us(1); } SCL 0; return retc; }应答处理是IIC通信中容易出错的部分。主机在发送完每个字节后需要检测从机的ACK信号u8 IIC_wait_ACK(void) { u8 t 200; IIC_OUTPUT_MODE_SET(); SDA_OUT 1; delay_us(1); SCL 0; delay_us(1); IIC_INPUT_MODE_SET(); delay_us(1); while(SDA_IN) { t--; delay_us(1); if(t 0) { SCL 0; return 1; } delay_us(1); } delay_us(1); SCL 1; delay_us(1); SCL 0; delay_us(1); return 0; }4. SHT30数据采集完整流程4.1 传感器初始化与测量触发与SHT30通信的第一步是发送测量命令。对于高精度测量我们使用0x2C06命令时钟拉伸禁用高重复性测量IIC_Start(); IIC_SendByte(0x44 1 | write); // 写模式地址0x44 IIC_wait_ACK(); IIC_SendByte(0x2C); // 命令高字节 IIC_wait_ACK(); IIC_SendByte(0x06); // 命令低字节 IIC_wait_ACK(); IIC_Stop();发送命令后需要等待测量完成。SHT30的典型测量时间为15ms实际使用中建议等待至少50ms以确保测量完成。4.2 数据读取与处理测量完成后可以读取6字节的数据温度高字节、温度低字节、温度CRC、湿度高字节、湿度低字节、湿度CRCIIC_Start(); IIC_SendByte(0x44 1 | read); // 读模式 if(IIC_wait_ACK() 0) { buff[0] IIC_RcvByte(); // 温度高字节 IIC_ACK(); buff[1] IIC_RcvByte(); // 温度低字节 IIC_ACK(); buff[2] IIC_RcvByte(); // 温度CRC可忽略 IIC_ACK(); buff[3] IIC_RcvByte(); // 湿度高字节 IIC_ACK(); buff[4] IIC_RcvByte(); // 湿度低字节 IIC_ACK(); buff[5] IIC_RcvByte(); // 湿度CRC可忽略 IIC_NACK(); IIC_Stop(); }4.3 数据转换与输出将原始数据转换为实际温湿度值tem ((buff[0] 8) | buff[1]); // 组合温度数据 hum ((buff[3] 8) | buff[4]); // 组合湿度数据 Temperature (175.0 * (float)tem / 65535.0 - 45.0); Humidity (100.0 * (float)hum / 65535.0); if((Temperature -20) (Temperature 125) (Humidity 0) (Humidity 100)) { sprintf(humiture_buff1, %6.2f*C %6.2f%%, Temperature, Humidity); } printf(温湿度%s\n, humiture_buff1);5. 调试技巧与常见问题在实际项目中调试模拟IIC时逻辑分析仪是不可或缺的工具。它可以直观显示SCL和SDA的时序关系帮助发现时序问题。我曾遇到过一个棘手的问题传感器偶尔会无响应。通过逻辑分析仪发现是起始信号中SCL高电平时间不足导致的。常见问题及解决方案传感器无响应检查IIC地址是否正确SHT30默认0x44确认上拉电阻已连接通常4.7kΩ检查电源电压是否稳定。数据校验失败确保时序严格符合规范特别是SCL高电平期间SDA必须稳定适当调整延时时间不同MCU时钟频率可能需要不同的延时。测量值异常检查数据转换公式是否正确确认读取的数据字节顺序无误避免在传感器测量期间频繁查询。对于需要更换GPIO引脚的情况除了修改引脚定义外还需要注意STM32的端口配置寄存器操作。例如对于GPIOA的Pin5和Pin6CRL寄存器的配置如下#define IIC_INPUT_MODE_SET() {GPIOA-CRL 0XF0FFFFFF; GPIOA-CRL | 8 24;} #define IIC_OUTPUT_MODE_SET() {GPIOA-CRL 0XF0FFFFFF; GPIOA-CRL | 3 24;}这段代码中0XF0FFFFFF清零了Pin6对应的配置位bit24~27然后通过或运算设置新的模式。8表示输入模式上拉/下拉3表示输出模式最大速度50MHz。模拟IIC的稳定性很大程度上取决于时序控制的精确性。不同STM32系列的最佳延时参数可能不同需要根据主频调整。在我的经验中F1系列在72MHz主频下关键延时通常在1-5μs之间。建议通过实验找到最优值并在代码中做好注释以便后续调整。

相关新闻