//IO定义 #define P_DataIN_DHT11 PB0_IN #define P_DataOUT_DHT11 PB0_OUT //宏定义 #define BSET_DHT11 P_DataOUT_DHT11 = 1 #define BCLR_DHT11 P_DataOUT_DHT11 = 0 //*************************************** // 模块功能:读取DHT11的数据 // 该模块为温湿度传感器 当主机给启动信号后 // 该模块会连续发出5个字节的数据 共耗时约4MS // 第一二个字节为湿度数据的整数与小数部分 // 第三四个字节为温度数据的整数与小数部分 // 第五个字节为校验码 它是前四个数据相加后的后8位的数值 // 程序带未传感器未连接检测 及读数据超时处理 //*************************************** //************************************* // 函数名称:VerificaDHT11Data // 函数功能:效验DHT11所读的数据是否正确 // 入口参数: // 出口参数:校验正确返回1 否则返回0 // 备注: //***************************************/ uint8 VerificaDHT11Data(uint8 *a) { uint8 i ; uint8 Tmp = 0 ; uint16 wTmp = 0 ; for(i=0;i<4;i++) { wTmp += a[i] ; } Tmp = (uint8)(wTmp & 0x00ff) ; //取低8位数据 if(Tmp == a[4]) { return 1 ; } else { return 0 ; } } //************************************* // 函数名称:ReadPinDHT11 // 函数功能:读管脚并滤波 // 入口参数: // 出口参数:返回管脚状态 Fcpu=16M时 耗时6US //***************************************/ uint8 ReadPinDHT11(void) { uint8 Tcon = 0 ; uint8 i ; for(i=0;i<5;i++) //读5次 { _asm("nop") ;//延时 _asm("nop") ; _asm("nop") ; _asm("nop") ; _asm("nop") ; if(P_DataIN_DHT11 == 1) { Tcon ++ ; } } if(Tcon >= 3) //读状态为1的次数大于3次 { return 1 ; } else { return 0 ; } } //=====读一字节数据====== uint8 ReadDHT11DataByte(uint8 InValue) { uint8 Data = 0 ; uint8 i = 0 ; uint8 ucTOver = 0 ; //等待超时时间 for(i=0;i<8;i++) { ucTOver = 30 ; //200U while(!ReadPinDHT11()&&(ucTOver--)) ; //等待高电平的到来 Nopt(VT_DLY40U) ; //延时40U Data <<= 1; ucTOver = 30 ; //200U if(ReadPinDHT11()&&(ucTOver--)) //判断IO是否还是被拉高的状态 { Data |= 0x01 ; //读最后一BIT数据时 不等待高电平 ucTOver = 30 ; //200U while(ReadPinDHT11()&&(ucTOver--)) ; //等待IO被外设拉低 } } return Data ; } //************************************* // 函数名称:ReadDH11Data // 函数功能:读取DHT // 入口参数: // 出口参数:返回读取的数据 // 当读取到数据时 返回1 未读取到数据返回0 //***************************************/ uint8 ReadDHT11Data(uint8 *a) { uint8 i ; uint8 ucTOver = 0 ; //等待超时时间 Nopt(VT_DLY40U) ; //延时40U if(ReadPinDHT11()) { Nopt(VT_DLY40U) ; //延时40U //从机一直没有回应 直接退出 if(ReadPinDHT11()) { return 0 ; } } //等待从机回应信号结束 ucTOver = 30 ; //200U while(!ReadPinDHT11()&&(ucTOver--)) ; //从机拉低时一直等待 ucTOver = 30 ; //200U while(ReadPinDHT11()&&(ucTOver--)) ; //从机拉高时一直等待 for(i=0;i<5;i++) //读5字节数据 { *a = ReadDHT11DataByte(i) ; a++ ; } return 1 ; } //************************************* // 函数名称:CmdDHT11Data // 函数功能:读DHT11的湿度 温度 // 入口参数:延时时间 // 出口参数:无 //***************************************/ void CmdDHT11Data(void) { static uint16 Tcyc = 0 ; static uint8 Tcon = 0 ; static uint8 TNum = 0 ; uint8 Tmp = 0 ; uint16 wTmp = 0 ; uint8 i ; Tcyc ++ ; if(Tcyc >= (VT_1S*VT_READDHT11)) //1s读取一次数据 { Tcyc = 0 ; F_ReadD11 = 1 ; Tcon = 0 ; } if(F_ReadD11) //准备启动从机 1S动作一次 { if(Tcon < 4) // 主机启动 拉低40ms { Tcon ++ ; BCLR_DHT11 ; } else { F_ReadD11 = 0 ; F_TestDH11 = 0 ; //读数据前清掉工作正常标志 for(i=0;i<5;i++) //清空数据缓存 { aDHT11Data[i] = 0 ; } BSET_DHT11 ; //主机拉高 等待从机回应 //从DHT11读数据 Tmp = ReadDHT11Data(aDHT11Data) ;// BSET_DHT11 ; //释放总线 if(Tmp != 0)//读数据有效 { if(VerificaDHT11Data(aDHT11Data)) { F_ReadD11OK = 1 ;//校验 成功 TNum = 0 ; } } else //传感器未连接出错 { TNum ++ ; if(TNum >= 4) { TNum = 0 ; F_ERRD11 = 1 ; } } } } } //************************************* // 函数名称:CountDHT11 // 函数功能:计算湿度 // 入口参数:延时时间 // 出口参数:无 //***************************************/ void CountHumidity(void) { uint8 Tmp ; static uint8 R_Save[3]; if(!F_ReadD11OK) return ; F_ReadD11OK = 0 ; //对数据进行滤波取中值处理 RMovData_Byte(R_Save,3); R_Save[0] = aDHT11Data[0] ; //保存结果 Humidity = Order_Byte(R_Save); //处理位数最大3位 F_TestDH11 = 1 ; //DHT11 工作正常 } //====================================================== //=======main======================================== //====================================================== void main(void) { while(1) { while(!F_10MS); // 主程序10MS跑一次 F_10MS = 0 ; CmdDHT11Data() ; //读DHT11数据 CountHumidity() ; // 计算湿度 } }