1
前言
上期我们介绍了一个STM32毕设的器件选型,其中有温湿度传感器,我推荐了SHT30。
在CSDN上一搜温度传感器,冒出来的就是DHT11,大部分朋友在选型时也会选DHT11,是一个实打实的已经 “烂大街”
的传感器。听一些HR说看到简历上写着DHT11,就知道是什么水准了。
DHT11采用单总线通讯协议即one-wire,数据以位为单位传输,每个数据位持续 50 微秒。高电平持续 26-28 微秒表示一个逻辑 "1",高电平持续
70 微秒表示一个逻辑 "0"。在学习51单片机的时候使用的非常多。
而SHT30采用的是标准I2C通讯协议,是多数低速传感器都会采用的通讯协议,相较于DHT11有着更复杂的技术栈和在STM32等更为简单的实现,具有更高的精度和稳定性。
本期我们介绍如何分别利用STM32和ESP32实现DHT11。代码均会打包上传到交流群(主页有群号)中。
1
STM32
关于SHT30,其实操作起来比较简单,它的器件地址是0x44,我们只需要对其写入命令,读取数据,查阅数据手册后将相关的命令使用宏定义实现。
// SHT30 I2C地址 (ADDR引脚接GND时为0x44)#define SHT30_ADDR 0x44 // 7位地址:0x44 (ADDR引脚接GND时)
// SHT30命令列表#define SHT30_SOFT_RESET 0x30A2 // 软复位#define SHT30_HIGH_ENABLED 0x2C06 // 周期测量,高重复性#define SHT30_READ_STATUS 0xF32D // 读状态寄存器#define SHT30_CLEAR_STATUS 0x3041 // 清除状态寄存器#define SHT30_STOP_MEASURE 0x3093 // 停止周期测量#define SHT30_SINGLE_HIGH 0x2400 // 单次测量,高重复性
之后利用硬件I2C实现命令发送。
static uint8_t SHT30_Send_Cmd(uint16_t cmd){ uint8_t cmd_buffer[2]; cmd_buffer[0] = cmd >> 8; // 高字节 cmd_buffer[1] = cmd & 0xFF; // 低字节 return HAL_I2C_Master_Transmit(&hi2c1, (SHT30_ADDR << 1), cmd_buffer, 2, 0xFF);}
它的读取函数也很简单,我们在读取前需要发送单次测量命令,之后直接读取寄存器的值。
// 读取温湿度数据uint8_t SHT30_Read_Temp_Hum(float *temperature, float *humidity){ uint8_t buffer[6]; uint16_t temp_raw, hum_raw; // 发送单次测量命令 if(SHT30_Send_Cmd(SHT30_SINGLE_HIGH) != HAL_OK) return HAL_ERROR; // 等待测量完成 HAL_Delay(15); // 读取6个字节数据,注意这里要用读地址(末位为1) if(HAL_I2C_Master_Receive(&hi2c1, (SHT30_ADDR << 1) | 0x01, buffer, 6, 0xFF) != HAL_OK) return HAL_ERROR; // 温度数据转换 temp_raw = ((uint16_t)buffer[0] << 8) | buffer[1]; *temperature = -45 + 175 * ((float)temp_raw / 65535); // 湿度数据转换 hum_raw = ((uint16_t)buffer[3] << 8) | buffer[4]; *humidity = 100 * ((float)hum_raw / 65535); return HAL_OK;}
第 1,2个字节表示温度数据,第3,4个字节表示湿度数据 。
利用公式:温度 = -45 + (175 * (温度数据 / 65536))
湿度同样如此,我们就可以获取温湿度数据了。
在此基础上,利用 ** 结构体深度封装 ** 一下。
typedef struct { float temperature; // 温度值 float humidity; // 湿度值} SHT30_Data_t;
// SHT30设备结构体typedef struct { I2C_HandleTypeDef* hi2c; // I2C句柄 uint8_t dev_addr; // 设备地址 SHT30_Data_t data; // 测量数据 uint8_t init_flag; // 初始化标志} SHT30_HandleTypeDef;
之后就可以在我们的主函数使用了。
if(SHT30_Init(&hsht30, &hi2c1) != HAL_OK) { Error_Handler(); } while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(SHT30_ReadData(&hsht30) == HAL_OK) { float temp = SHT30_GetTemperature(&hsht30); float humi = SHT30_GetHumidity(&hsht30); } HAL_Delay(1000); }
** 静置状态 **
利用手指改变温湿度
2
ESP32
ESP32上开发相对简单,在Arduino中下载相对应的库。
// 初始化I2C通信,指定ESP32的SDA和SCL引脚 Wire.begin(SDA_PIN, SCL_PIN); // 初始化SHT31D传感器,默认地址0x44 sht31d.begin(0x44); SHT31D result = sht31d.readTempAndHumidity(SHT3XD_REPEATABILITY_HIGH, SHT3XD_MODE_POLLING, 50); // 打印温度数据 Serial.print("温度 (°C): "); Serial.println(result.t); Serial.println(""); // 打印湿度数据 Serial.print("湿度 (%RH): "); Serial.println(result.rh);
之后依据库API打印数据即可。
之后我们可以测试一下,利用ESP32将温湿度数据每隔半小时上传到MQTT服务器,在云服务器部署相应网页。
大家也可以访问这个网站试试看(这个是手机网页登录的):https://pic.qr2c.cn/mqtt/mobile.html
电脑端:
www.shizaitailan.cn/mqtt/visual.html