概述
这里将我写的STC12C5A60S2单片机控制湿度温度传感DHT11的程序共享一下,是为了让前辈给予斧正。
更新:
2014/06/29 09:01 在结构体DHT11_info中定义了DHT11_CRC,实际上此校验不属于CRC校验,定义名称不合适,
需要修改,这里只做声明,请自行修改
2014/05/31 提供修改方法,适用于不同型号的51单片机(文章最后)
2014/05/27 10:07(DHT11ReadByte(void)函数修改,修改内容已在DHT11.C中Modification部分讲述,为了便于理解修改细节,不涉及功能调试)
2014/04/26 18:04 (重新调试完成)
2014/04/26 17:50 (发现程序有问题,湿度整数部分超过100,重新调试)
2014/04/03 11:25
2014/03/31 15:17
(补充:以下代码只需要修改.h文件中含有 “选择” 字样的部分,就可以达到复用的效果)
对于串口调试部分,请参考《单片机程序协助调试方法(一)串口调试》点击进入
实验对象:
实验现象:
测试程序:
#include <reg52.h>
#include "common.h"
#include "uart.h"
#include "DHT11.h"
void main(void)
{
UB8 i=0;
DHT11_info dataCode ;
UartInit() ;
#if 0 //临时测试DHT11的存在与否
P1=0x00 ;//led
if(DHT11Init() <0) //未检测到DHT11
P1=0x01 ;
else //检测到DHT11
P1=0x02 ;
while(1);
#endif
while(1)
{
if(DHT11Init()==DHT11_EXISTENCT)
{
i=0; /*错误记录:忘记了给i清零,导致前几次测量数据正确,后面的数据都错误(一定要注意)*/
while((DHT11_DATA_BIT )&& (i < 250))
{
i++; //临时,具体见调试
/*经过试验,这里250足够大了*/
}
/*临时试验,真正试验时必须屏蔽,否则影响后面数据的读取*/
//UartSendString("ready to send data.rn") ;
DHT11ReadInfo(&dataCode) ;
UartSendValue("Humidity_H : ",dataCode.Humidity_H);
UartSendValue("Humidity_L : ",dataCode.Humidity_L);
UartSendValue("Temperature_H : ",dataCode.Temperature_H);
UartSendValue("Temperature_L : ",dataCode.Temperature_L);
UartSendValue("DHT11_CRC : " ,dataCode.DHT11_CRC);
UartSendString("rnrn") ;
}
else
{
UartSendString("No DHT11 existence.rn");
}
}
}
/*################DHT11.h start################*/
#ifndef __DHT11_H__
#define __DHT11_H__
#include "common.h"
#include "reg52.h"
sbit DHT11_DATA_BIT = P2^0 ;/*根据具体硬件选择*/
typedef struct {
UB8 Humidity_H ;
UB8 Humidity_L ;
UB8 Temperature_H ;
UB8 Temperature_L ;
UB8 DHT11_CRC;
}DHT11_info ;
#define DHT11_EXISTENCT 0 /*DHT11存在*/
#define DHT11_NOT_EXISTENCT -1 /*DHT11不存在*/
/*****************外部接口函数******************/
extern SB8 DHT11Init(void) ;
extern void DHT11ReadInfo(DHT11_info *temp) ;
/**********************************************/
#endif /*__DHT11_H__*/
/*################DHT11.h end################*/
/*################DHT11.C start################*/
/***************************************************************************
Module :DHT11.c
Purpose :Implementation of DHT11 module.
Version :0.01 2014/02/03 12:00(OK)
Complier:Keil 8051 C complier V9.01
MCU :STC12C5A60S2
Author :yangrui
QQ :279729201
Email :yangrui90s@163.com
Modification:
=================
2014/05/17 10:04
Reason:
1.将函数static UB8 DHT11ReadByte(void)内部的
if (DHT11_DATA_BIT)
{
datCode |= 0x01;
}
j=0 ;
while((DHT11_DATA_BIT) &&(j<250)) ;
{
j++ ;
}
修改为
if (DHT11_DATA_BIT)
{
datCode |= 0x01;
j=0 ;
while((DHT11_DATA_BIT) &&(j<250)) ;
{
j++ ;
}
}
因为只有当某一bit数据位高电平时,才需要等待电平拉低
(每一bit数据发送之前都是以低电平开始,所以这等待是必须的),
虽然第一种算法没有错误,但是方法二更好理解。
=================
=================
2014/04/03 11:01
Reason:
1.修改void DHT11ReadInfo(UB8 table[])的入参"UB8 table[]"形式
为DHT11_info *temp,这样的结构更加紧凑。
=================
=================
2014/03/31 10:48
Reason:
1.在DHT11ReadInfo(UB8 table[])中增加了延时部分,在没有延时的情况下。
发现main函数中有时竟然不发送数据,或者复位后发送一次数据,这是因为
DHT11在采集完数据之后会恢复到空闲状态,如果需要继续采集,需要一个启
动过程。在main函数中添加延时,正常。
但为了安全和方便,直接将延时加载采集数据的函数内部较好。
=================
***************************************************************************/
#include "DHT11.H"
#include <intrins.h>
/*外部接口函数在DHT11.H中声明*/
/*****************内部函数******************/
static void delay20msForDHT11(void) ;
static void delay10usForDHT11(void) ;
static UB8 DHT11ReadByte(void) ; //读取DHT11字节数据
/**********************************************/
/******************************************************
Function :delay20msForDHT11
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :由STC-ISP V6.67软件针对相应MCU生成,若MCU不同
最好也要修改此函数。
******************************************************/
static void delay20msForDHT11(void) //@11.0592MHZ
{
unsigned char i, j, k;
i = 1;
j = 216;
k = 35;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/******************************************************
Function :delay10usForDHT11
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :由STC-ISP V6.67软件针对相应MCU生成,若MCU不同
最好也要修改此函数。
******************************************************/
static void delay10usForDHT11(void)
{
unsigned char i;
_nop_();
i = 25;
while (--i);
}
/******************************************************
Function :DHT11Init
Input :N/A
Output :N/A
Return : 0(DHT1 existence)
-1(DHT11 not existenct)
Description :检测DHT11的存在与否
Note :1.本函数中,等待DHT11的低电平回应结束后才会跳出。
2.为了防止DHT11的未安装或接触不良导致的程序"卡死"
情况的发生,在等待电平转换的同时增加了时间限制,
并且这个时间设置的是较长的,经过试验,在正常连接
DHT11的情况下,还未等到"最后时间的到来",就已经
发生了电平转换,这在大工程中是非常必要的。
******************************************************/
SB8 DHT11Init(void)
{
SB8 existenceFlag ;
UB8 i=0 ;
DHT11_DATA_BIT = HIGH_LEVEL ;
_nop_() ;
_nop_() ;
DHT11_DATA_BIT = LOW_LEVEL ;
delay20msForDHT11() ;
DHT11_DATA_BIT = HIGH_LEVEL ;
delay10usForDHT11() ;
delay10usForDHT11() ;
delay10usForDHT11() ;
delay10usForDHT11() ;
delay10usForDHT11() ;
if( !DHT11_DATA_BIT)
{
existenceFlag = DHT11_EXISTENCT ;
}
else
{
existenceFlag = DHT11_NOT_EXISTENCT ;
}
while((!DHT11_DATA_BIT) && (i<250))
{
i++ ; //暂时,具体见调试
/*经过调试,这里250足够大了*/
}
return existenceFlag ;
}
/******************************************************
Function :DHT11ReadByte
Input :N/A
Output :N/A
Return :byte-data which is read from DHT11
Description :N/A
Note :为了防止DHT11的未安装或接触不良导致的程序"卡死"
情况的发生,在等待电平转换的同时增加了时间限制,
并且这个时间设置的是较长的,经过试验,在正常连接
DHT11的情况下,还未等到"最后时间的到来",就已经
发生了电平转换,这在大工程中是非常必要的。
修改:把if之后的j=0 ,while(){}部分修改到if内部
******************************************************/
static UB8 DHT11ReadByte(void)
{
UB8 j=0 ;
UB8 i, datCode;
for(i=0;i<8;i++)
{
datCode <<= 1;
/*每一bit数据都以50us低电平时隙开始,这里直接等待DHT11把数据线拉到高电平*/
j=0 ;
while( (! DHT11_DATA_BIT) && (j<250))
{
j++ ; //暂时,具体见调试
/*经过调试,这里250足够大了*/
}
delay10usForDHT11() ;
delay10usForDHT11() ;
delay10usForDHT11() ;
delay10usForDHT11() ;
if (DHT11_DATA_BIT)
{
datCode |= 0x01;
j=0 ;
while((DHT11_DATA_BIT) &&(j<250)) ;
{
j++ ; //暂时,具体见调试
/*经过调试,这里250足够大了*/
}
}
}
return datCode;
}
/******************************************************
Function :DHT11ReadInfo
Input :N/A
Output :DHT11_infor struct
Return :N/A
Description :读取DHT11采集到的数据
Note :注意增加延时的意义。见"Modification"的
"2014/03/31 10:48"部分。
******************************************************/
void DHT11ReadInfo(DHT11_info *temp)
{
temp->Humidity_H = DHT11ReadByte() ; //Humidity_H
temp->Humidity_L = DHT11ReadByte() ; //Humidity_L
temp->Temperature_H = DHT11ReadByte() ; //Temperature_H
temp->Temperature_L = DHT11ReadByte() ; //Temperature_L
temp->DHT11_CRC = DHT11ReadByte() ; //DHT11_CRC
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
delay20msForDHT11() ;
}
/*################DHT11.C end################*/
补充:common.h
#ifndef __COMMON_H__
#define __COMMON_H__
typedef unsigned char UB8 ;
typedef unsigned short int UW16 ;
typedef unsigned long UL32 ;
typedef char SB8;
typedef short int SW16 ;
typedef long SL32 ;
#define HIGH_LEVEL 1
#define LOW_LEVEL 0
#endif /*__COMMON_H__*/
后期:
1.针对不同的IO:
修改DHT11.h的
sbit DHT11_DATA_BIT = P2^0 ;/*根据具体硬件选择*/
即可!!
2.针对不同MCU修改:
修改DHT11.c中的static void delay20msForDHT11(void)和static void delay10usForDHT11(void),因为这里的延时函是利用STC-ISP软件自带的工具生成的,是针对STC12C5A60S2的,所以,若用于不同的51单片机,需要修改延时函数,过程截图:
3.对于串口打印:参考http://blog.csdn.net/yagnruinihao/article/details/22662145,这里需要使用11.0592MHZ晶振,直接拷贝uart.h和uart.c,加入工程直接编译即可,如果不同,只需稍作修改。
3.程序的拷贝:
最后
以上就是超级火龙果为你收集整理的单片机控制单总线协议湿度温度传感器DHT11之模块化编程(持续更新中)的全部内容,希望文章能够帮你解决单片机控制单总线协议湿度温度传感器DHT11之模块化编程(持续更新中)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复