温湿度传感器DHT11:神舟IV

DHT11与DS18B20很像,都是单总线。不过DHT11操作简单多了,不用查询ROM,不需要操作流程,初始化之后有需要时候读取数据就可以了。

DHT11数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由5Byte40Bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先出。DHT11的数据格式为:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。其中校验和数据为前四个字节相加。

我们使用PE2作为DQ pin,宏定义操作与18B20一样

.h
1 //PE2作为DHT11的DQ pin
2 #define DHT11_OUT_High  GPIO_SetBits(GPIOE, GPIO_Pin_2) 
3 #define DHT11_OUT_Low   GPIO_ResetBits(GPIOE, GPIO_Pin_2)
4 #define    DHT11_DQ_IN      GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2)
DHT11_Init
 1 //初始化DHT11的IO口 DQ 同时检测DHT11的存在
 2 //返回1:不存在
 3 //返回0:存在         
 4 u8 DHT11_Init(void)
 5 {     
 6      GPIO_InitTypeDef  GPIO_InitStructure;
 7      
 8      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);     //使能PG端口时钟
 9     
10      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                 //PG11端口配置
11      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
12      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
13      GPIO_Init(GPIOE, &GPIO_InitStructure);                 //初始化IO口
14      GPIO_SetBits(GPIOE,GPIO_Pin_2);                         //PG11 输出高
15                 
16     DHT11_Rst();  //复位DHT11
17     return DHT11_Check();//等待DHT11的回应
18 } 
DHT11_Rst
1 //复位DHT11
2 void DHT11_Rst(void)       
3 {                 
4     DHT11_IO_OUT();     //SET OUTPUT
5     DHT11_OUT_Low;         //拉低DQ
6     delay_ms(20);        //拉低至少18ms
7     DHT11_OUT_High;     //DQ=1 
8     delay_us(30);         //主机拉高20~40us
9 }
DHT11_Check
 1 //等待DHT11的回应
 2 //返回1:未检测到DHT11的存在
 3 //返回0:存在
 4 u8 DHT11_Check(void)        
 5 {   
 6     u8 retry=0;
 7     DHT11_IO_IN();//SET INPUT     
 8     while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
 9     {
10         retry++;
11         delay_us(1);
12     };     
13     if(retry>=100)return 1;
14     else retry=0;
15     while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
16     {
17         retry++;
18         delay_us(1);
19     };
20     if(retry>=100)return 1;        
21     return 0;
22 }

以上为初始化所用到的函数
因为DHT11不需要发送指令,所以只是读取,很简单,没有了写操作

DHT11_Read_Data
 1 //从DHT11读取一次数据
 2 //temp:温度值(范围:0~50°)
 3 //humi:湿度值(范围:20%~90%)
 4 //返回值:0,正常;1,读取失败
 5 u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
 6 {        
 7      u8 buf[5];
 8     u8 i;
 9     DHT11_Rst();
10     if(DHT11_Check()==0)
11     {
12         for(i=0;i<5;i++)//读取40位数据
13         {
14             buf[i]=DHT11_Read_Byte();
15         }
16         if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
17         {
18             *humi=buf[0];
19             *temp=buf[2];
20         }
21     }else return 1;
22     return 0;        
23 }
DHT11_Read_Byte
 1 //从DHT11读取一个字节
 2 //返回值:读到的数据
 3 u8 DHT11_Read_Byte(void)    
 4 {        
 5     u8 i,dat;
 6     dat=0;
 7     for (i=0;i<8;i++) 
 8     {
 9            dat<<=1; 
10         dat|=DHT11_Read_Bit();
11     }                            
12     return dat;
13 }
DHT11_Read_Bit
 1 //从DHT11读取一个位
 2 //返回值:1/0
 3 u8 DHT11_Read_Bit(void)              
 4 {
 5      u8 retry=0;
 6     while(DHT11_DQ_IN&&retry<100)//等待变为低电平
 7     {
 8         retry++;
 9         delay_us(1);
10     }
11     retry=0;
12     while(!DHT11_DQ_IN&&retry<100)//等待变高电平
13     {
14         retry++;
15         delay_us(1);
16     }
17     delay_us(40);//等待40us
18     if(DHT11_DQ_IN)return 1;
19     else return 0;           
20 }

main函数中进行初始化

        /* 温湿度传感器DHT11初始化 */  
  if(DHT11_Init()) 
  {
          DHT11Init_Flag=0;
    printf("\r\n DHT11 Init Failed! \n\r");   
  }
  else  
  {
    DHT11Init_Flag=1;
    printf("\r\n DHT11 Init Success! \n\r");
  }

中断中显示:

显示数值
1     if(DHT11Init_Flag)     
2     {
3        DHT11_Read_Data(&temperature,&humidity);    //读取温湿度值
4        printf("\r\n 当前温度值:%d° 当前湿度值:%d\n\r",temperature,humidity);
5     }
6     else printf("\r\n 温湿度传感器DHT11初始化失败 \n\r");

实验中遇到一个问题:PE2端口并没有上拉电阻,而DQ pin需要上拉电阻,利用板子上IIC的接口,将PE2改为PB6,实验成功了。温度值很不准确。

原文地址:https://www.cnblogs.com/wwjdwy/p/3021841.html