微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于Mega128的DHT11温湿度传感器

基于Mega128的DHT11温湿度传感器

时间:11-29 来源:互联网 点击:
DHT11和DS18B20一样,都是单总线芯片,同DHT10不同,它的四根引脚中有一条是空脚,与DS18B20相似,对时序的要求比较高,不同之处在于写程序的时候数据的采集必须间隔1s以上,不然采集会失败。

还有,DHT11的数据口最好要接一个上拉电阻,或者单片机内部上拉也可以。

DHT11的数据手册网上有,上面有时序操作的详细介绍。个人建议写这个程序的时候要一边写一边检测(比如写完复位子程序之后就在主函数中调用它一次,看它是否执行成功。。。),不然很可能到最后找不到错误出在哪里,本人就是一直写完然后不好使,最后又重写的!

闲话不说了,下面帮助大家分析一下DHT11的时序图(数据手册上有),因为DHT11对时序的要求很高,所以很可能写完程序不好使。本人建议:延时子函数最好自己用示波器检测一下,自己算出来的在10us下误差会很大的。

进入正题:下面我说的话可以参照下面的程序看。

数据手册前面的一些内容自己了解就可以了,先看数据手册上主机复位信号和DHT11相应信号那部分。

主机先控制总线,拉低至少18ms,然后再拉高20~40us,(这时如果硬件没有问题的话DHT11会有响应的)所以现在主机释放总线(把DDRXN 寄存器清零),等待DHT11的响应,如果成功DHT11会产生40~50us的低电平,和40~50us的高电平。这里可以由程序完成检测。

接下来在一次采集中,把总线一直交给DHT11,它会给主机传送一个40位的二进制数,前0~7位是湿度的整数部分,8~15位是湿度的小数部分;16~23位是温度的整数部分,24~31位是温度的小数部分;最后八位是校验位。这些数据要通过程序进行处理,转换成温湿度的实际值,并由显示部分显示出来。(本人用的是数码管,建议用1602显示会更方便一些)。

后面的处理部分我就不一一讲解了,我在程序中是有注释的,自己把程序加入到工程中看效果会好很多的,也可以用专门的阅读软件来看(source insignte),不然字体都一个颜色非常乱。

如果有不懂的地方或者程序有什么不足之处给我留言就好了,我会及时帮助大家解决的^_^!!!
程序代码的完整版本下载地址是:http://www.51hei.com/f/dht11.rar

================================================//这里是delay.h     /*************我开发板的晶振是16M的,具体的延时子函数要自己仔细写*************/#ifndef __DELAY_H#define __DELAY_Hvoid delay_us(unsigned int xus);void delay_ms(unsigned int xms);#endif================================================//这里是delay.c#include"delay.h"#include//延时微妙子函数void delay_us(unsigned int xus){unsigned int i,j;for(i=0;i#endif#ifndef __MACROS_H#include #endif#define DDR_1 DDRC|=BIT(PC0)#define DDR_0 DDRC&=~BIT(PC0)#define PORTC_1 PORTC|=BIT(PC0)#define PORTC_0 PORTC&=~BIT(PC0)#define DQ    (PINC&0x01)void caiji(void);long int dht(void);void init_dht11(void);//void ceshi(void);#endif================================================//这里是dht11.c#include"dht11.h"unsigned char dht_data[5],a,b;unsigned int s1,s0,t1,t0,sd,wd,wsd;void caiji(void){unsigned char i,j;//delay_ms(900);for(i=0;i<5;i++){dht_data[i]=0x00;  //数组清零for(j=0;j<8;j++){while(!DQ);    //判断是否为高电平//延时50us若为高电平则为一,否则为零delay_us(50);if(DQ){dht_data[i]|=BIT(7-j); //保存数据while(DQ);//低电平检测}}}}void init_dht11(void){DDR_1;  //设置主机输出PORTC_0;  //总线拉低至少18msdelay_ms(20);PORTC_1; //总线由主机拉高大约30usdelay_us(30);DDR_0; //主机设置为输入,检测从机信号while(DQ);}long int dht(void){init_dht11();if(!DQ){while(!DQ);while(DQ); //经以上两句后开始接收信号caiji();DDR_1;PORTC_1;//校验a=(dht_data[0]+dht_data[1]+dht_data[2]+dht_data[3]);if(a==dht_data[4]){s1=dht_data[0];s0=dht_data[1];t1=dht_data[2];t0=dht_data[3];}//s为湿度,t为温度sd=s1;sd<=8;sd|=s0;wd=t1;wd<=8;wd|=t0;wsd=sd<16;wsd|=wd;}  return wsd;}================================================//这里是xianshi.h#ifndef __XIANSHI_H#define __XIANSHI_H#ifndef __IOM128V_H#include#endif#define SCK_0 PORTB&=~(1>16;//下面为把温度和湿度换算成十进制并且四舍五入temp=(t>>8);temp_shi=temp/10;temp_ge=temp%10;SH=(s>>8);SH_shi=SH/10;SH_ge=SH%10;int_part=SH_shi*10+SH_ge;float_part=0;for(i=0;i<50;i++){digitron_show(int_part,float_part);}}void digitron_show(unsigned int int_part,unsigned int float_part){ PORTA=0x01;send_595(table[float_part/10]);send_595(0x00);delay_ms(5);PORTA=0x02;send_595(table[(int_part%10)+10]);send_595(0x00);delay_ms(5);PORTA=0x04;send_595(table[int_part/10]);send_595(0x00);delay_ms(5);}================================================//这里是MAIN.C#include#include#include"delay.h"#include"dht11.h"#include"xianshi.h"#pragma interrupt_handler Timer0_COMP:16 #define uchar unsigned charuchar k=0;void init(void);void main(){init();//初始化TCCR0=0X0F;DDRA=0XFF;TCCR0=0X0f;//CTC模式OCR0=145;//10msTIMSK=0X02;SEI();while(1);}//初始化子函数void init(void){DDRA=0XFF; DDRB=0XFF;}void Timer0_COMP(void){TCCR0=0X08;CLI();k++;if(k==255){k=0;show();}TCCR0=0X0f;//重置初值SEI();}程序到这里结束,希望大家多提宝贵意见哦!!!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top