STM32 温湿度传感器DHT11

1.参数
工作电压范围:3.3V-5.5V
工作电流 :平均0.5mA
输出:单总线数字信号
测量范围:湿度20-90%RH,温度0~50℃
精度 :湿度±5%,温度±2℃
分辨率 :湿度1%,温度1℃

在这里插入图片描述
2.性能特点
DHT11数字湿温度传感器采用单总线数据格式。单个数据引脚端口完成输入输出双向传输。其数据包由5Byte(40Bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先出。

DHT11的数据格式为:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。

其中校验和数据为前四个字节相加。
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。
3.时序逻辑
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。例如,某次从DHT11读到的数据如图所示:
在这里插入图片描述
由以上数据就可得到湿度和温度的值,计算方法:
湿度= byte4 . byte3=45.0 (%RH)
温度= byte2 . byte1=28.0 ( ℃)
校验= byte4+ byte3+ byte2+ byte1=73(校验正确)

4.数据发送流程
在这里插入图片描述
首先主机发送开始信号,即:拉低数据线,保持t1(至少18ms)时间,然后拉高数据线t2(20-40us)时间,然后读取DHT11的响应,正常的话,DHT11会拉低数据线,保持t3(40~50us)时间,作为响应信号,然后DHT11拉高数据线,保持t4(40-50us)时间后,开始输出数据。

DHT11输出数字‘0’的时序如图
在这里插入图片描述
DHT11输出数字‘1’的时序如图
在这里插入图片描述
5.代码讲解

//IO方向设置
#define DHT11_IO_IN()  {GPIOB->MODER&=~(3<<(12*2));GPIOB->MODER|=0<<(12*2);}	//PB12输入模式
#define DHT11_IO_OUT() {GPIOB->MODER&=~(3<<(12*2));GPIOB->MODER|=1<<(12*2);} 	//PB12输出模式
 
IO操作函数					
#define	DHT11_DQ_OUT(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET):  \
                                         HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET)) //数据端口PB12
#define	DHT11_DQ_IN     HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) //数据端口	PB12

代码解析:复位
在这里插入图片描述

//复位DHT11
void DHT11_Rst(void)	   
{                 
    DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_DQ_OUT=0; 	//拉低DQ
    delay_ms(20);    	//拉低至少18ms
    DHT11_DQ_OUT=1; 	//DQ=1 
    delay_us(30);     	//主机拉高20~40us
}

等待回应
在这里插入图片描述

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void) 	   
{   
   u8 retry=0;
  DHT11_IO_IN();//SET INPUT	 
   while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
  {
    retry++;   delay_us(1);
  };	 
  if(retry>=100)return 1;
  else retry=0;
   while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
  {
       retry++;  delay_us(1);
  };
  if(retry>=100)return 1;	    
  return 0;
}

读数据一个bit
在这里插入图片描述

//从DHT11读取一个位   返回值:1/0
u8 DHT11_Read_Bit(void) 			 
{
      u8 retry=0;
      while(DHT11_DQ_IN&&retry<100)//等待变为低电平
      {
             retry++;   
             delay_us(1);
       }
      retry=0;
      while(!DHT11_DQ_IN&&retry<100)//等待变高电平
       {
              retry++;	
              delay_us(1);
         }
         delay_us(40);//等待40us
         if(DHT11_DQ_IN)return 1;
         else return 0;		   
}
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
   for (i=0;i<8;i++) 
  {
      dat<<=1; 
     dat|=DHT11_Read_Bit();
    }				    
    return dat;
}

解析温度和湿度值

//从DHT11读取一次数据
//temp:温度值(范围:0~50°)     humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
    u8 buf[5];
   u8 i;
    DHT11_Rst();
   if(DHT11_Check()==0)
   {
          for(i=0;i<5;i++)//读取40位数据
    {
          buf[i]=DHT11_Read_Byte();
   }
    if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
   {
        *humi=buf[0];
       *temp=buf[2];
   }
 }else return 1;
  return 0;	    
}
<think>好的,我现在需要处理用户关于STM32DHT11温湿度传感器的驱动代码和教程的查询。首先,我要回忆一下DHT11的基本工作原理和通信协议。DHT11是单总线通信的,使用一根数据线进行数据传输,需要严格的时序控制。STM32的GPIO配置需要设置为推挽输出和浮空输入模式,同时要处理延时和中断的问题。 用户提到参考引用[1]中的内容,提到了PA11引脚的使用。所以,在示例代码中需要确保使用的GPIO端口是正确的,并且初始化配置符合单总线协议的要求。接下来,我需要考虑如何编写初始化函数、发送开始信号、读取数据位的函数。 可能需要注意的地方包括:时序的精确控制,比如开始信号的低电平时间、等待DHT11响应的高电平时间,以及数据位读取时的延时。STM32的微秒级延时通常使用SysTick定时器或者直接使用循环来实现,但需要根据系统时钟频率进行调整。 另外,数据校验也是关键,用户需要确保读取的40位数据(湿度整数、湿度小数、温度整数、温度小数、校验和)正确,校验和是前四个字节的和,需要验证是否正确。 用户可能需要教程的步骤,比如硬件连接、GPIO配置、时序控制、数据解析等部分。在代码示例中,应该包括初始化、启动信号、读取数据位、校验数据,并将结果通过串口输出。同时,需要提醒用户注意电源稳定性和信号线长度的问题,避免通信失败。 最后,生成相关问题时,要考虑用户可能进一步的需求,比如如何优化驱动、如何处理通信错误、如何与显示屏连接等。确保问题覆盖常见的应用场景和潜在问题,帮助用户深入学习和解决问题。</think>### STM32驱动DHT11温湿度传感器教程 #### 一、硬件连接 DHT11采用单总线协议,接线需注意: - **VCC**:3.3V-5.5V电源(建议STM32开发板3.3V) - **DATA**:PA11(需配置GPIO模式) - **GND**:共地连接[^1] #### 二、GPIO配置 配置PA11为推挽输出(发送启动信号)和浮空输入(接收数据): ```c // GPIO初始化函数 void DHT11_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 默认输出模式 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_SetBits(GPIOA, GPIO_Pin_11); // 初始高电平 } ``` #### 三、核心驱动代码 ```c // 启动信号发送 void DHT11_Start(void) { GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_ResetBits(GPIOA, GPIO_Pin_11); // 拉低18ms Delay_ms(20); GPIO_SetBits(GPIOA, GPIO_Pin_11); Delay_us(30); // 主机拉高20-40us } // 数据位读取 uint8_t DHT11_ReadBit(void) { while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)); // 等待低电平 Delay_us(40); // 判断26-28us后电平 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)) return 1; else return 0; } // 完整数据读取 uint8_t DHT11_ReadData(uint8_t *temp, uint8_t *humi) { uint8_t data[5] = {0}; DHT11_Start(); // 切换输入模式 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStruct); // 校验响应信号 if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)) { Delay_us(80); if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)) { // 读取40位数据 for(int i=0; i<40; i++) { data[i/8] <<= 1; data[i/8] |= DHT11_ReadBit(); } // 校验数据 if(data[4] == (data[0]+data[1]+data[2]+data[3])) { *humi = data[0]; *temp = data[2]; return 1; } } } return 0; } ``` #### 四、应用示例 ```c int main(void) { USART_Init(); // 初始化串口 DHT11_GPIO_Init(); uint8_t temperature, humidity; while(1) { if(DHT11_ReadData(&temperature, &humidity)) { printf("温度:%d℃ 湿度:%d%%\r\n", temperature, humidity); } else { printf("数据读取失败\r\n"); } Delay_ms(2000); // 2秒更新一次 } } ``` #### 五、注意事项 1. **时序精度**:微秒级延时误差需小于5us 2. **电源干扰**:建议DATA线加5K上拉电阻 3. **采样间隔**:DHT11需≥1秒的采集间隔
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值