写点什么

STM32F103ZE+SHT30 检测环境温度与湿度 (IIC 模拟时序)

作者:DS小龙哥
  • 2022 年 8 月 08 日
  • 本文字数:4946 字

    阅读完需:约 16 分钟

一、环境介绍

工程编译软件: keil5


温湿度传感器: SHT30


MCU : STM32F103ZET6


SHT30 是 I2C 接口的高精度温湿度传感器,应用范围较广,小米的温湿度检测智能设备也是采用 SHT30,相比 DHT11 而言,灵敏度都好一些。 当前程序采用模块化编程,iic 时序为一个模块(iic.c 和 iic.h),SHT30 为一个模块(sht30.c 和 sht30.h);IIC 时序采用模拟时序方式实现,IO 口都采用宏定义方式,方便快速移植到其他平台使用。


二、SHT30 介绍



特点:

\1. 湿度和温度传感器

\2. 完全校准、线性化和温度

\3. 补偿数字输出,宽电源电压范围,从 2.4 V 到 5.5 V

\4. I2C 接口,通信速度高达 1MHz 和两个用户可选地址\5. 典型精度 +- 2%相对湿度和+- 0.3°C

\6. 启动和测量时间非常快

\7. 微型 8 针 DFN 封装



三、设备运行效果

这是串口打印的数据:





四、设备代码

4.1 main.c

#include "stm32f10x.h"#include "led.h"#include "delay.h"#include "key.h"#include "usart.h"#include "iic.h"#include "sht3x.h"
int main(){ float Humidity; float Temperature; USART1_Init(115200); USART1_Printf("设备运行正常....\r\n"); IIC_Init(); Init_SHT30(); while(1) { //读取温湿度 SHT3x_ReadData(&Humidity,&Temperature); USART1_Printf("温度:%0.2f,湿度:%0.2f\r\n",Temperature,Humidity); delay_ms(1000); }}
复制代码


4.2 sht30.c

#include "sht3x.h"
const int16_t POLYNOMIAL = 0x131;
/**************************************************************** 函数名称: SHT30_reset* 说 明: SHT30复位* 参 数: 无* 返 回 值: 无***************************************************************/void SHT30_reset(void){ u8 r_s; IIC_Start(); //发送起始信号 IIC_WriteOneByteData(SHT30_AddrW); //写设备地址 r_s=IIC_GetACK();//获取应答 if(r_s)printf("Init_SHT30_error:1\r\n");
IIC_WriteOneByteData(0x30); //写数据 r_s=IIC_GetACK();//获取应答 if(r_s)printf("Init_SHT30_error:2\r\n"); IIC_WriteOneByteData(0xA2); //写数据 r_s=IIC_GetACK();//获取应答 if(r_s)printf("Init_SHT30_error:3\r\n"); IIC_Stop(); //停止信号
delay_ms(50); }

/**************************************************************** 函数名称: Init_SHT30* 说 明: 初始化SHT30,设置测量周期* 参 数: 无* 返 回 值: 无***************************************************************/void Init_SHT30(void){ u8 r_s; IIC_Start(); //发送起始信号 IIC_WriteOneByteData(SHT30_AddrW); //写设备地址 r_s=IIC_GetACK();//获取应答 if(r_s)printf("Init_SHT30_error:1\r\n");
IIC_WriteOneByteData(0x22); //写数据 r_s=IIC_GetACK();//获取应答 if(r_s)printf("Init_SHT30_error:2\r\n"); IIC_WriteOneByteData(0x36); //写数据 r_s=IIC_GetACK();//获取应答 if(r_s)printf("Init_SHT30_error:3\r\n"); IIC_Stop(); //停止信号 delay_ms(200);}

/**************************************************************** 函数名称: SHT3x_CheckCrc* 说 明: 检查数据正确性* 参 数: data:读取到的数据 nbrOfBytes:需要校验的数量 checksum:读取到的校对比验值* 返 回 值: 校验结果,0-成功 1-失败***************************************************************/u8 SHT3x_CheckCrc(char data[], char nbrOfBytes, char checksum){ char crc = 0xFF; char bit = 0; char byteCtr ; //calculates 8-Bit checksum with given polynomial for(byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr) { crc ^= (data[byteCtr]); for ( bit = 8; bit > 0; --bit) { if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL; else crc = (crc << 1); } } if(crc != checksum) return 1; else return 0; }
/**************************************************************** 函数名称: SHT3x_CalcTemperatureC* 说 明: 温度计算* 参 数: u16sT:读取到的温度原始数据* 返 回 值: 计算后的温度数据***************************************************************/float SHT3x_CalcTemperatureC(unsigned short u16sT){ float temperatureC = 0; // variable for result
u16sT &= ~0x0003; // clear bits [1..0] (status bits) //-- calculate temperature [℃] -- temperatureC = (175 * (float)u16sT / 65535 - 45); //T = -45 + 175 * rawValue / (2^16-1) return temperatureC; }
/**************************************************************** 函数名称: SHT3x_CalcRH* 说 明: 湿度计算* 参 数: u16sRH:读取到的湿度原始数据* 返 回 值: 计算后的湿度数据***************************************************************/float SHT3x_CalcRH(unsigned short u16sRH){ float humidityRH = 0; // variable for result u16sRH &= ~0x0003; // clear bits [1..0] (status bits) //-- calculate relative humidity [%RH] -- humidityRH = (100 * (float)u16sRH / 65535); // RH = rawValue / (2^16-1) * 10 return humidityRH; }

//读取温湿度数据void SHT3x_ReadData(float *Humidity,float *Temperature){ char data[3]; //data array for checksum verification u8 SHT3X_Data_Buffer[6]; //byte 0,1 is temperature byte 4,5 is humidity u8 r_s=0; u8 i; unsigned short tmp = 0; uint16_t dat; IIC_Start(); //发送起始信号 IIC_WriteOneByteData(SHT30_AddrW); //写设备地址 r_s=IIC_GetACK();//获取应答 if(r_s)printf("SHT3X_error:1\r\n");
IIC_WriteOneByteData(0xE0); //写数据 r_s=IIC_GetACK();//获取应答 if(r_s)printf("SHT3X_error:2\r\n"); IIC_WriteOneByteData(0x00); //写数据 r_s=IIC_GetACK();//获取应答 if(r_s)printf("SHT3X_error:3\r\n"); //IIC_Stop(); //停止信号 // DelayMs(30); //等待 //读取sht30传感器数据 IIC_Start(); //发送起始信号 IIC_WriteOneByteData(SHT30_AddrR); r_s=IIC_GetACK();//获取应答 if(r_s)printf("SHT3X_error:7\r\n"); for(i=0;i<6;i++) { SHT3X_Data_Buffer[i]=IIC_ReadOneByteData(); //接收数据 if(i==5) { IIC_SendACK(1); //发送非应答信号 break; } IIC_SendACK(0); //发送应答信号 } IIC_Stop(); //停止信号 // /* check tem */ data[0] = SHT3X_Data_Buffer[0]; data[1] = SHT3X_Data_Buffer[1]; data[2] = SHT3X_Data_Buffer[2];
tmp=SHT3x_CheckCrc(data, 2, data[2]); if( !tmp ) /* value is ture */ { dat = ((uint16_t)data[0] << 8) | data[1]; *Temperature = SHT3x_CalcTemperatureC( dat ); }
// /* check humidity */ data[0] = SHT3X_Data_Buffer[3]; data[1] = SHT3X_Data_Buffer[4]; data[2] = SHT3X_Data_Buffer[5];
tmp=SHT3x_CheckCrc(data, 2, data[2]); if( !tmp ) /* value is ture */ { dat = ((uint16_t)data[0] << 8) | data[1]; *Humidity = SHT3x_CalcRH( dat ); }}
复制代码


4.3 iic.c

#include "iic.h"
/*函数功能:IIC接口初始化硬件连接:SDA:PB7SCL:PB6*/void IIC_Init(void){ RCC->APB2ENR|=1<<3;//PB GPIOB->CRL&=0x00FFFFFF; GPIOB->CRL|=0x33000000; GPIOB->ODR|=0x3<<6;}
/*函数功能:IIC总线起始信号*/void IIC_Start(void){ IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SDA_OUT=1; //数据线拉高 IIC_SCL=1; //时钟线拉高 DelayUs(4); //电平保持时间 IIC_SDA_OUT=0; //数据线拉低 DelayUs(4); //电平保持时间 IIC_SCL=0; //时钟线拉低}

/*函数功能:IIC总线停止信号*/void IIC_Stop(void){ IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SDA_OUT=0; //数据线拉低 IIC_SCL=0; //时钟线拉低 DelayUs(4); //电平保持时间 IIC_SCL=1; //时钟线拉高 DelayUs(4); //电平保持时间 IIC_SDA_OUT=1; //数据线拉高}
/*函数功能:获取应答信号返 回 值:1表示失败,0表示成功*/u8 IIC_GetACK(void){ u8 cnt=0; IIC_SDA_INPUTMODE();//初始化SDA为输入模式 IIC_SDA_OUT=1; //数据线上拉 DelayUs(2); //电平保持时间 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 DelayUs(2); //电平保持时间,等待从机发送数据 IIC_SCL=1; //时钟线拉高,告诉从机,主机现在开始读取数据 while(IIC_SDA_IN) //等待从机应答信号 { cnt++; if(cnt>250)return 1; } IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 return 0;}
/*函数功能:主机向从机发送应答信号函数形参:0表示应答,1表示非应答*/void IIC_SendACK(u8 stat){ IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要发送数据 if(stat)IIC_SDA_OUT=1; //数据线拉高,发送非应答信号 else IIC_SDA_OUT=0; //数据线拉低,发送应答信号 DelayUs(2); //电平保持时间,等待时钟线稳定 IIC_SCL=1; //时钟线拉高,告诉从机,主机数据发送完毕 DelayUs(2); //电平保持时间,等待从机接收数据 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据}

/*函数功能:IIC发送1个字节数据函数形参:将要发送的数据*/void IIC_WriteOneByteData(u8 data){ u8 i; IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要发送数据 for(i=0;i<8;i++) { if(data&0x80)IIC_SDA_OUT=1; //数据线拉高,发送1 else IIC_SDA_OUT=0; //数据线拉低,发送0 IIC_SCL=1; //时钟线拉高,告诉从机,主机数据发送完毕 DelayUs(2); //电平保持时间,等待从机接收数据 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要发送数据 DelayUs(2); //电平保持时间,等待时钟线稳定 data<<=1; //先发高位 }}

/*函数功能:IIC接收1个字节数据返 回 值:收到的数据*/u8 IIC_ReadOneByteData(void){ u8 i,data; IIC_SDA_INPUTMODE();//初始化SDA为输入模式 for(i=0;i<8;i++) { IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 DelayUs(2); //电平保持时间,等待从机发送数据 IIC_SCL=1; //时钟线拉高,告诉从机,主机现在正在读取数据 data<<=1; if(IIC_SDA_IN)data|=0x01; DelayUs(2); //电平保持时间,等待时钟线稳定 } IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 (必须拉低,否则将会识别为停止信号) return data;}
复制代码


发布于: 刚刚阅读数: 3
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
STM32F103ZE+SHT30检测环境温度与湿度(IIC模拟时序)_8月月更_DS小龙哥_InfoQ写作社区