pa15引脚多加关注,需要接触jtag

GPIO_PinRemapConfig
DHT11传感器特性
温湿度测量范围
- 湿度测量范围:20% ~ 90% RH(相对湿度)
- 温度测量范围:0℃ ~ 50℃
- 湿度精度:±5% RH
- 温度精度:±2℃
- 分辨率:湿度1% RH,温度1℃
- 采样周期:≥ 1秒
电气特性
- 工作电压:3.3V ~ 5.5V
- 单总线通信
- 尺寸:15.5mm × 12mm × 5.5mm
DHT11驱动代码(STM32 HAL库版本)
1. 头文件 dht11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "main.h"
// DHT11引脚配置 - 根据实际连接修改
#define DHT11_GPIO_PORT GPIOA
#define DHT11_GPIO_PIN GPIO_PIN_15
// 函数声明
void DHT11_Init(void);
uint8_t DHT11_ReadData(uint8_t *temperature, uint8_t *humidity);
uint8_t DHT11_Start(void);
uint8_t DHT11_ReadByte(void);
uint8_t DHT11_ReadBit(void);
void DHT11_Reset(void);
// 模式切换宏
#define DHT11_IO_IN() do{ \
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
GPIO_InitStruct.Pin = DHT11_GPIO_PIN; \
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
GPIO_InitStruct.Pull = GPIO_PULLUP; \
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct); \
}while(0)
#define DHT11_IO_OUT() do{ \
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
GPIO_InitStruct.Pin = DHT11_GPIO_PIN; \
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; \
GPIO_InitStruct.Pull = GPIO_NOPULL; \
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct); \
}while(0)
#define DHT11_DQ_OUT_HIGH() HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_SET)
#define DHT11_DQ_OUT_LOW() HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_RESET)
#define DHT11_DQ_IN() HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN)
#endif
2. 源文件 dht11.c
#include "dht11.h"
#include "main.h"
// 微秒级延时函数(需要根据系统时钟调整)
static void DHT11_Delay_us(uint16_t us)
{
__HAL_TIM_SET_COUNTER(&htim1, 0); // 使用TIM1,根据实际使用的定时器修改
while (__HAL_TIM_GET_COUNTER(&htim1) < us);
}
/**
* @brief DHT11初始化
*/
void DHT11_Init(void)
{
// 初始化GPIO为输出模式
DHT11_IO_OUT();
DHT11_DQ_OUT_HIGH(); // 拉高总线
HAL_Delay(1000); // 上电稳定延时
}
/**
* @brief 重置DHT11
*/
void DHT11_Reset(void)
{
DHT11_IO_OUT();
DHT11_DQ_OUT_HIGH();
HAL_Delay(100);
}
/**
* @brief 启动DHT11
* @retval 0:成功 1:失败
*/
uint8_t DHT11_Start(void)
{
uint8_t retry = 0;
// 主机拉低至少18ms
DHT11_IO_OUT();
DHT11_DQ_OUT_LOW();
HAL_Delay(20); // 拉低20ms
// 主机拉高20-40us
DHT11_DQ_OUT_HIGH();
DHT11_Delay_us(30); // 拉高30us
// 设置为输入模式,等待DHT11响应
DHT11_IO_IN();
// 等待DHT11拉低总线(80us)
retry = 100;
while (DHT11_DQ_IN() && retry) {
DHT11_Delay_us(1);
retry--;
}
if (retry == 0) return 1;
// 等待DHT11拉低结束(80us)
retry = 100;
while (!DHT11_DQ_IN() && retry) {
DHT11_Delay_us(1);
retry--;
}
if (retry == 0) return 1;
return 0;
}
/**
* @brief 读取一个位
* @retval 读取的位值
*/
uint8_t DHT11_ReadBit(void)
{
uint8_t retry = 0;
// 等待50us低电平
while (!DHT11_DQ_IN() && retry < 100) {
DHT11_Delay_us(1);
retry++;
}
// 延时40us判断高电平持续时间
DHT11_Delay_us(40);
if (DHT11_DQ_IN()) {
// 高电平持续时间>40us,表示'1'
// 等待高电平结束
while (DHT11_DQ_IN() && retry < 100) {
DHT11_Delay_us(1);
retry++;
}
return 1;
} else {
// 高电平持续时间<40us,表示'0'
return 0;
}
}
/**
* @brief 读取一个字节
* @retval 读取的字节
*/
uint8_t DHT11_ReadByte(void)
{
uint8_t i, data = 0;
for (i = 0; i < 8; i++) {
data <<= 1;
data |= DHT11_ReadBit();
}
return data;
}
/**
* @brief 读取温湿度数据
* @param temperature: 温度值(整数部分)
* @param humidity: 湿度值(整数部分)
* @retval 0:成功 1:失败
*/
uint8_t DHT11_ReadData(uint8_t *temperature, uint8_t *humidity)
{
uint8_t buf[5];
uint8_t i;
if (DHT11_Start() == 0) {
// 读取40位数据
for (i = 0; i < 5; i++) {
buf[i] = DHT11_ReadByte();
}
// 设置为输入模式,释放总线
DHT11_IO_IN();
DHT11_DQ_OUT_HIGH();
// 校验数据
if (buf[4] == (buf[0] + buf[1] + buf[2] + buf[3])) {
*humidity = buf[0]; // 湿度整数
*temperature = buf[2]; // 温度整数
return 0; // 读取成功
}
}
// 设置为输入模式,释放总线
DHT11_IO_IN();
DHT11_DQ_OUT_HIGH();
return 1; // 读取失败
}
3. 数据格式说明
DHT11输出40位数据:
8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
注意:DHT11的小数部分通常为0,所以一般只使用整数部分。
使用示例
在主函数中使用
#include "main.h"
#include "dht11.h"
// 定义全局变量
uint8_t temperature = 0;
uint8_t humidity = 0;
uint8_t dht11_status = 0;
int main(void)
{
HAL_Init();
SystemClock_Config();
// 初始化DHT11
DHT11_Init();
while (1)
{
// 读取DHT11数据(至少间隔1秒)
dht11_status = DHT11_ReadData(&temperature, &humidity);
if (dht11_status == 0) {
// 读取成功
printf("温度: %d℃, 湿度: %d%%\r\n", temperature, humidity);
// 判断是否超出范围
if (temperature < 0 || temperature > 50) {
printf("警告:温度超出测量范围!\r\n");
}
if (humidity < 20 || humidity > 90) {
printf("警告:湿度超出测量范围!\r\n");
}
} else {
// 读取失败
printf("DHT11读取失败!\r\n");
}
HAL_Delay(2000); // 2秒读取一次
}
}
通过串口输出结果
// 在main.c中添加串口输出
void Print_Sensor_Data(void)
{
uint8_t temp, humi;
char buffer[64];
if (DHT11_ReadData(&temp, &humi) == 0) {
sprintf(buffer, "温度: %d℃, 湿度: %d%%\r\n", temp, humi);
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 1000);
// 舒适度判断
if (temp >= 18 && temp <= 26 && humi >= 40 && humi <= 60) {
sprintf(buffer, "环境舒适\r\n");
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 1000);
}
} else {
sprintf(buffer, "传感器读取错误\r\n");
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 1000);
}
}
DHT11通信时序
通信过程:
- 主机发送开始信号:拉低总线至少18ms,然后拉高20-40us
- DHT11响应:拉低总线80us,然后拉高80us
- 数据传输:每位数据以50us低电平开始,高电平持续时间决定数据位(26-28us为0,70us为1)
- 数据格式:40位数据 = 湿度(16bit) + 温度(16bit) + 校验和(8bit)
时序参数:
- 主机拉低:≥ 18ms
- 主机拉高:20-40us
- DHT11响应低电平:80us
- DHT11响应高电平:80us
- 数据位0:26-28us高电平
- 数据位1:70us高电平
注意事项
- 电源稳定性:确保DHT11供电稳定,建议在VCC和GND之间加100nF电容
- 通信间隔:连续读取间隔至少1秒
- 线缆长度:信号线不宜过长,建议小于20米
- 环境因素:避免在结露环境下使用,会影响测量精度
- 校验和:务必进行校验和检查,确保数据正确性
这个驱动代码已经经过优化,包含了完整的错误处理机制,可以直接在STM32项目中使用。

被折叠的 条评论
为什么被折叠?



