温湿度传感器DHT11:神舟IV
DHT11与DS18B20很像,都是单总线。不过DHT11操作简单多了,不用查询ROM,不需要操作流程,初始化之后有需要时候读取数据就可以了。
DHT11数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由5Byte(40Bit)组成。数据分小数部分和整数部分,一次完整的数据传输为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,实验成功了。温度值很不准确。