我看那么多人问DHT11源码,这个校验不对,那个数据不对,干脆发出来了。与STM32 PB15对接,觉得好请打赏,节省你2天时间啊!
#include "dht11.h" #include "bsl.h" static void pin_config(int is_out) { int set=0; static int status=0; GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 ; GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; if(is_out){ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; }else{ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; } /* pb15=temperature sensor */ if( is_out && status!=1){ set = 1; status = 1; } else if(!is_out && status!=2){ status = 2; set = 1; } if(set) GPIO_Init(GPIOB, &GPIO_InitStructure); } static void write_pin(int is_high) { GPIO_WriteBit(GPIOB,GPIO_Pin_15,is_high?Bit_SET: Bit_RESET); } static uint8_t read_pin(void) { return (!!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)); } /* DHT11输出0、1信号的低电平时间相同,而高电平的时间不同,输出 * 0信号时高电平约26-28us,而当输出1信号时高电平约为70us。 */ static uint8_t dht_read_byte(void) { uint8_t i,temp=0; uint16_t tick,time_out; for(i=0;i<8;i++) { /* 等待变起始低电平50us */ SET_TICKUS(tick); //SET_TICKUS(time_out); while( read_pin() == 1){ //if(GET_DIFF_TICKUS(time_out) > 90) //return 0; } /* 等待变高电平出真正数据 */ SET_TICKUS(time_out); while( read_pin() == 0){ //if(GET_DIFF_TICKUS(time_out) > 60) //return 0; } delay_xus(40); /* 此时再判断高电平,仍然为高就是1.仍然为高的话,留给下一次等待判断变低(50us开始) */ temp <<= 1; if(read_pin() == 1){ temp |= 1; } } return temp; } /* * @temp:高字节为温度整数,低字节为小数。 * @shidu:高字节为湿度整数,低字节为小数。 */ int dht_read_data(uint16_t *temp,uint16_t *shidu) { uint16_t count,sum,temp_int,temp_dec,shi_int,shi_dec; if(temp==NULL || shidu==NULL) return -250; /* 主机设为输出模式 */ pin_config(1); /* 主机拉低,至少拉低18ms */ write_pin(0); delay_xms(20); /* 主机拉高 20-40us,dht检测变低后就开始送数据 */ write_pin(1); delay_xus(30); /* 主机设置为输入模式,此时dht11变低 */ pin_config(0); while(read_pin()== 1){} /* 等待拉低80us */ //if(read_pin()== 0) //{ SET_TICKUS(count); /* 等待DHT11拉高80us */ while(read_pin()== 0){ if(GET_DIFF_TICKUS(count) > 100) return -1; } /* 此时dht11开始拉高80us,然后拉低50us出数据了 */ /* 等待DHT11置高80us SET_TICKUS(count); while(read_pin()== 1){ if(GET_DIFF_TICKUS(count) > 100) return -2; }*/ /* DHT11以低电平应答主机,然后拉高总线准备输出。 * 数据格式:8bit湿度整数数据+8bit湿度小数数据(目前保留=0) * +8bit温度整数数据+8bit温度小数数据(目前保留=0) * +8bit校验和 */ shi_int = dht_read_byte(); shi_dec = dht_read_byte(); temp_int = dht_read_byte(); temp_dec = dht_read_byte(); sum = dht_read_byte(); /*读取结束,将主机设为输出模式*/ pin_config(1); write_pin(1); /*检查读取的数据是否正确*/ if(sum==(temp_int+temp_dec+shi_int+shi_dec)){ *temp = (temp_int<<8) | temp_dec; *shidu = (shi_int<<8) | shi_dec; return 0; } else return -3; //} //else //return -4; }
关键就是读字节那里,先|=1跟后|=1是差1倍的问题,还有各种各样的问题,大家要注意了!