ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

STM32 驱动 SHT35 温湿度传感器:从 I²C 通信到 CRC 校验的完整实战

STM32 驱动 SHT35 温湿度传感器:从 I²C 通信到 CRC 校验的完整实战

文章目录

  • 一、SHT35 简介
  • 二、引脚功能
  • 三、驱动与数据说明
    • 驱动说明
    • 数据说明
      • CRC校验
  • 四、程序
    • STM32
  • 五、测试

一、SHT35 简介

SHT35 是一款高精度数字式温湿度传感器,采用 I²C 通信接口,可测量环境温度和相对湿度,温度测量范围为 −40~125℃,湿度测量范围为 0~100%RH,具有测量精度高、功耗低、体积小和稳定性好等特点。通过单片机发送测量命令并读取传感器数据,广泛应用于环境监测、智能家居及工业温湿度检测等领域

二、引脚功能

引脚功能
VCC电源正 3.3-5V
GND参考地
SDA数据线
SCL时钟线

三、驱动与数据说明

驱动说明

传感器上电后需等待小段时间,发送写命令 0x2400,等待 20ms 测量完成;
后读取 6 字节温湿度数据,再进行CRC检验



数据说明

温湿度数据计算

CRC校验

CRC计算代码如下:

staticuint8_tSHT35_CRC8(constuint8_t*data,uint8_tlen){uint8_tcrc=0xFF;uint8_ti,j;for(i=0;i<len;i++){crc^=data[i];for(j=0;j<8;j++){if(crc&0x80){crc=(uint8_t)((crc<<1)^0x31);}else{crc=(uint8_t)(crc<<1);}}}returncrc;}

四、程序

STM32

SHT35 .C

#include"sht35.h"#include"delay.h"#defineSHT35_ADDR0x44#defineI2C_TIMEOUT100000Ustaticuint8_tI2C1_WaitEvent(uint32_tevent){uint32_ttimeout=I2C_TIMEOUT;while(!I2C_CheckEvent(I2C1,event)){if(--timeout==0)return0;}return1;}staticuint8_tI2C1_WaitFlag(uint32_tflag,FlagStatus status){uint32_ttimeout=I2C_TIMEOUT;while(I2C_GetFlagStatus(I2C1,flag)!=status){if(--timeout==0)return0;}return1;}staticvoidI2C1_Stop(void){I2C_GenerateSTOP(I2C1,ENABLE);I2C_AcknowledgeConfig(I2C1,ENABLE);}staticvoidI2C1_Init(void){GPIO_InitTypeDef gpio;I2C_InitTypeDef i2c;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);/* PB6 = SCL,PB7 = SDA */gpio.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;gpio.GPIO_Speed=GPIO_Speed_50MHz;gpio.GPIO_Mode=GPIO_Mode_AF_OD;GPIO_Init(GPIOB,&gpio);I2C_DeInit(I2C1);I2C_StructInit(&i2c);i2c.I2C_Mode=I2C_Mode_I2C;i2c.I2C_DutyCycle=I2C_DutyCycle_2;i2c.I2C_OwnAddress1=0;i2c.I2C_Ack=I2C_Ack_Enable;i2c.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;i2c.I2C_ClockSpeed=100000;I2C_Init(I2C1,&i2c);I2C_Cmd(I2C1,ENABLE);}voidSHT35_Init(void){I2C1_Init();}staticuint8_tSHT35_WriteCommand(uint16_tcmd){if(!I2C1_WaitFlag(I2C_FLAG_BUSY,RESET))return0;I2C_GenerateSTART(I2C1,ENABLE);if(!I2C1_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))gotoerror;I2C_Send7bitAddress(I2C1,SHT35_ADDR<<1,I2C_Direction_Transmitter);if(!I2C1_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))gotoerror;I2C_SendData(I2C1,(uint8_t)(cmd>>8));if(!I2C1_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED))gotoerror;I2C_SendData(I2C1,(uint8_t)cmd);if(!I2C1_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED))gotoerror;I2C1_Stop();return1;error:I2C1_Stop();return0;}staticuint8_tSHT35_ReadBytes(uint8_t*data){uint8_ti;if(!I2C1_WaitFlag(I2C_FLAG_BUSY,RESET))return0;I2C_AcknowledgeConfig(I2C1,ENABLE);I2C_GenerateSTART(I2C1,ENABLE);if(!I2C1_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))gotoerror;I2C_Send7bitAddress(I2C1,SHT35_ADDR<<1,I2C_Direction_Receiver);if(!I2C1_WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))gotoerror;for(i=0;i<3;i++){if(!I2C1_WaitFlag(I2C_FLAG_RXNE,SET))gotoerror;data[i]=I2C_ReceiveData(I2C1);}if(!I2C1_WaitFlag(I2C_FLAG_BTF,SET))gotoerror;I2C_AcknowledgeConfig(I2C1,DISABLE);data[3]=I2C_ReceiveData(I2C1);if(!I2C1_WaitFlag(I2C_FLAG_BTF,SET))gotoerror;I2C_GenerateSTOP(I2C1,ENABLE);data[4]=I2C_ReceiveData(I2C1);data[5]=I2C_ReceiveData(I2C1);I2C_AcknowledgeConfig(I2C1,ENABLE);return1;error:I2C1_Stop();return0;}staticuint8_tSHT35_CRC8(constuint8_t*data,uint8_tlen){uint8_tcrc=0xFF;uint8_ti,j;for(i=0;i<len;i++){crc^=data[i];for(j=0;j<8;j++){if(crc&0x80){crc=(uint8_t)((crc<<1)^0x31);}else{crc=(uint8_t)(crc<<1);}}}returncrc;}uint8_tSHT35_ReadData(float*temperature,float*humidity){uint8_tdata[6];uint16_trawT,rawRH;if(temperature==0||humidity==0)return0;if(!SHT35_WriteCommand(0x2400))return0;Delay_ms(20);if(!SHT35_ReadBytes(data))return0;if(SHT35_CRC8(&data[0],2)!=data[2])return0;if(SHT35_CRC8(&data[3],2)!=data[5])return0;rawT=((uint16_t)data[0]<<8)|data[1];rawRH=((uint16_t)data[3]<<8)|data[4];*temperature=-45.0f+175.0f*(float)rawT/65535.0f;*humidity=100.0f*(float)rawRH/65535.0f;if(*humidity<0.0f)*humidity=0.0f;if(*humidity>100.0f)*humidity=100.0f;return1;}

main.C

#include"stm32f10x.h"#include<stdio.h>#include<Delay.h>#include"sht35.h"#include<stdint.h>voidUSART1_Init(void){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA,&GPIO_InitStructure);USART_InitStructure.USART_BaudRate=115200;USART_InitStructure.USART_WordLength=USART_WordLength_8b;USART_InitStructure.USART_StopBits=USART_StopBits_1;USART_InitStructure.USART_Parity=USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;USART_Init(USART1,&USART_InitStructure);USART_Cmd(USART1,ENABLE);}intfputc(intch,FILE*f){USART_SendData(USART1,(uint8_t)ch);while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);returnch;}intmain(void){floattemperature=0.0f;floathumidity=0.0f;int32_tt100;uint32_th100;SystemInit();USART1_Init();SHT35_Init();Delay_ms(500);while(1){if(SHT35_ReadData(&temperature,&humidity)){t100=(int32_t)(temperature*100.0f);h100=(uint32_t)(humidity*100.0f);if(t100<0){printf("Temperature: -%ld.%02ld C, ",(long)(-t100/100),(long)(-t100%100));}else{printf("Temperature: %ld.%02ld C, ",(long)(t100/100),(long)(t100%100));}printf("Humidity: %lu.%02lu %%RH\r\n",(unsignedlong)(h100/100),(unsignedlong)(h100%100));}else{printf("Error!\r\n");}Delay_ms(1000);}}

五、测试

---------------------------------------------------接线--------------------------------------------------

  • UART:
  • PA9 -> TX
  • PA10 -> RX
  • IIC:
  • PB6 -> SCL
  • PB7 -> SDA

开发板串口输出如下:

以上内容个人理解,如有不正欢迎指正,需要资料及工程可留言邮箱

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进