最近大学课程里的单片机实训选了题目为DHT11温湿度检测系统,在本论坛看了很多大佬的资料后,自己简单写了一下能够完成任务的程序,主要使用了STC89C52单片机、LCD1602显示屏以及DHT11模块。模块的详细略过,直接贴代码。 DHT11的DATA为P3^0; DHT11对数据的传输很严格,数据线的优劣影响数据传输的成功跟速度,所以数据DATA线要连接好,不要松动。 本代码搬运于https://blog.csdn.net/qq_40626497/article/details/103615232谢谢博主 这个主要按照DHT11的时序自己调出一个合适的时延就可以了。标准就参照以下 这里主要用蜂鸣器作报警。 这里没有使用闪烁,如果使用闪烁可以知道正在修改哪个值的报警值,读者可以自行加上,这里不作优化。目录
简要
 单片机P0为1602的传输端;
 RS,RW,EN自便
 晶振为11.0592Mhz。
 最后1602屏幕的显示应该是
 K为开警报,变成G为关警报。
 湿度下限为70,上限为95
 温度下限为25,上限为95
 上行       “Wise:00|D70|U95K”  
 下行      “Temp:00|D25|U95K”问题:
主函数
#include<intrins.h>     //延时函数 #include<string.h> #include"delay.h" #include"DHT11.h" #include"LED1602.h" #include"init_frist.h" #include"keyadd.h"  #include"K1_K4.h" #define Uint unsigned int  //预定义 #define Uchar unsigned char  Uchar buff_wise[]="Wise:00|D00|U00K";             //D=Down 下限    U=up 上限 Uchar buff_temp[]="Temp:00|D00|U00K";      Uchar RH=0,RL=0,TH=0,TL=0; Uchar data_byte; Uint A_OPEN=0,W0,W00=70,W11=99,T00=25,T11=99,d_wh=0,d_th=0,Y=0,t2=0; void CLOCK_DHT11() interrupt 1      //定时器配置函数。 {  //static修饰的变量在程序运行的时候分配一次内存,以后不再分配  static int count=0;  //重装初值,计数器再次从初值开始算50000次。  TH0 = (65536-5000)/256;     //高8位。16位定时器 00000000 00000000     TL0 = (65536-5000)%256;   //低8位。    count++; //每10ms加1次。  if(count == 50)  //到达50次就是250ms。     {   count = 0;   A_OPEN = ~A_OPEN;   } } void main()  //主程序。  {        init_frist();      } DHT11模块代码
#include<DHT11.h>  #include<delay.h>   //************************************检测模块*************************************  void DHT11RstAndCheck()   //这为DHT11的复位程序和响应程序。 {   DHT11 = 1;     delay22us();    //首先拉高一个高电平。   DHT11 = 0;     delay(25);    // 主机把总线拉低必须大于18ms,保证DHT11能检测到起始信号。 此为22us。    DHT11 = 1;       //发送开始信号结束后拉高电平延时20-40us     delay22us();           // 22us }   Uchar DHT11ReadByte(void) //读一字节数据 {  Uchar i,temp;    for(i=0;i<8;i++)          //接收8bit的数据    {    while(!DHT11 );         //等待50us的低电平开始信号结束    delay35us();              //开始信号结束之后延时26us-28us     temp=0;//时间为26us-28us表示接收的为数据'0'    if(DHT11 ==1)    temp=1; //如果26us-28us之后还为高电平则表示接收的数据为'1'      while(DHT11);//等待数据信号高电平'0'为26us-28us'1'为70us    data_byte<<=1;//接收的数据为高位在前右移   data_byte|=temp;    }     return data_byte;  } //读取一次数据(整数) 0-读取失败 1-读取成功 void DHT11ReadData() {     Uchar T_H,T_L,R_H,R_L,check,num_check;    DHT11RstAndCheck();//开始信号//    DHT11=1;   //主机设为输入判断从机DHT11响应信号    if(!DHT11)//判断从机是否有低电平响应信号//    {    while(!DHT11);//判断从机发出 80us 的低电平响应信号是否结束//   while(DHT11);//判断从机发出 80us 的高电平是否结束如结束则主机进入数据接收状态     R_H=DHT11ReadByte();//湿度高位      R_L=DHT11ReadByte();//湿度低位        T_H=DHT11ReadByte();//温度高位     T_L=DHT11ReadByte();//温度低位   check=DHT11ReadByte();//校验位   DHT11=0; //当最后一bit数据接完毕后从机拉低电平50us//    delay2();   DHT11=1;//总线由上拉电阻拉高进入空闲状态   num_check=R_H+R_L+T_H+T_L;   if(num_check==check)//判断读到的四个数据之和是否与校验位相同    {      RH=R_H;    //定义湿度高位      RL=R_L;         TH=T_H;    //定义温度高位     TL=T_L;      check=num_check; //判断    }    }  } lcd1602显示模块
#include<led1602.h>  #include<delay.h>   //************************************显示模块************************************* bit test_BF()    //检测忙信号 {  Uchar LCD_status;  P0=0xFF;      //全选  EN=0;  RS=0;  RW=1;  EN=1;  Delay1(1);  LCD_status=P0;  EN=0;  return (LCD_status&0x80)?1:0; }  /* 写命令*/  void write_CMD(Uchar cmd) {  while(test_BF());    //检测不忙时。  EN=0;  RS=0;  RW=0;  P0=cmd;         //P0口输出数据位  EN=1;   _nop_();   EN=0; }  /*写数据(一位一位的写)*/ void write_Data(Uchar data8)   //1bit,1bit地写字。 {  while(test_BF());  EN=0; RS=1; RW=0;  P0=data8;  EN=1; _nop_(); EN=0; } /*屏幕初始化*/ void init() {  write_CMD(0x38);Delay1(1);   //置功能  write_CMD(0x01);Delay1(1);   //清显示  write_CMD(0x06);Delay1(1);   //置输入  write_CMD(0x0C);Delay1(1);   //显示开/关控制 } /*写字符串*/          void write_Str(int r, int c, char *str)     //整个字符串全写出来 {  int i=0;   unsigned char Addressx[] = {0x80, 0xC0};  unsigned char StartAdd = (Addressx[r] | c);//按位或   write_CMD(StartAdd);    for(i = 0; i < 16; i++){   if(str[i]==0) break;   write_Data(str[i]);  }  // 如果不够16位,用空格填充  for(;i < 16; i++){   write_Data(' ');    } } 延时模块,
#include<delay.h>   //************************************延时模块************************************* void Delay1(Uint x)      //这主要用于LCD1602显示器的延时,不需要太精准。 {  Uchar O;  while(x--)   for(O=0; O<120; O++); } //************************************延时模块************************************* void delay(Uchar ms)        //这为使用debug调试的延时,主要用于DHT11传感器的延时,25个ms为22ms。 {    Uchar i;    while(ms--)                           for(i=0;i<100;i++);  }  void delay22us()      //这为使用debug调试的延时,主要用于DHT11传感器的延时,显示延时22us。 {    Uchar i;   for(i=0;i<1;i++){_nop_();_nop_(); } } void delay35us()      //这为使用debug调试的延时,主要用于DHT11传感器的延时,显示延时29us。 {    Uchar i;      for(i=0;i<2;i++){_nop_();_nop_();_nop_();} } void delay2()                 //这为使用debug调试的延时,主要用于DHT11传感器的延时,显示延时50us。 {    Uchar i;    for(i=0;i<4;i++)_nop_();  }   启动模块
#include<init_frist.h>  void init_frist()   //开机全局启动 {    init();  //显示屏       //定时器0,工作方式1,16位计数器  TMOD = 0x01; //(D7->D0)-->0000 0001    0000 0010 0x02   //定时10ms,初值65536-10000  TH0 = (65536-5000)/256; //高8位  0-255     50ms     TL0 = (65536-5000)%256;   //低8位   ET0 = 1; //允许定时器中断       TR0 = 1; //开启定时器,开始计数         EA = 1;  //打开全局中断  while(1)  {   K1_K4();   if(A_OPEN)   {          DHT11ReadData();       Buzzer_b(d_wh,W00,W11,d_th,T00,T11);     d_wh=RH;  //湿度     d_th=TH;   //温度        buff_wise[5] = d_wh/10+'0';    buff_wise[6] = d_wh%10+'0';    //湿度下限    buff_wise[9] = W00/10+'0';    buff_wise[10] = W00%10+'0';    //湿度上限    buff_wise[13] = W11/10+'0';    buff_wise[14] = W11%10+'0';     buff_temp[5] = d_th/10+'0';    buff_temp[6] = d_th%10+'0';    //温度下限    buff_temp[9] = T00/10+'0';    buff_temp[10] = T00%10+'0';    //温度上限    buff_temp[13] = T11/10+'0';    buff_temp[14] = T11%10+'0';     if(Y==0)      //警报开关标志位。    {    buff_wise[15] = 'K';   //开警报。    buff_temp[15] = 'K';     }    else    {    buff_wise[15] = 'G';     //关警报。    buff_temp[15] = 'G';    }    //显示     write_Str(0,0,buff_wise);      write_Str(1,0,buff_temp);    }     } }  蜂鸣器报警模块
#include<Buzzer.h> //蜂鸣器模块 void Buzzer_b(Uint now_w,Uint w_down,Uint w_up,Uint now_t,Uint t_down,Uint t_up) { Uchar i1;  if(Y==0)                 //如果警报标志位开启,Y=1,警报开启;Y=0,警报关闭。  {   if((now_w<w_down)||(now_w>w_up )||(now_t<t_down)||(now_t>t_up )) //如果温度wise湿度temp大于上限值,小于下限值,就会报警。   {        for(i1=0;i1<2;i1++)           //循环2次蜂鸣器响起。      {       BUZZER = 0;            //蜂鸣器响起。       delay(50);            //作一定时间的延时。       BUZZER = 1;            //蜂鸣器不响。      }   }  }  } 选位修改报警值
#include<K1_K4.h>   //选位置调节,一共四个位置 |wise_down下限|wise_up上限 void K1_K4()   //选位置调节,一共四个位置 |temp_down下限|temp_up上限 { if(KEY4==0)        //检测按键4是否被按下。          {    Delay1(20);     //延时。       if(KEY4==0)     //延时后如果按键4还是被按下,则执行程序          {     while(!KEY4);           t2++;          }   } switch(t2)   {     case 0:    W00=keyadd(W00); break;        //当t2为0时,修改湿度(wise)下限值。     case 1:    W11=keyadd(W11); break;        //当t2为1时,修改湿度(wise)上限值。     case 2:    T00=keyadd(T00); break;        //当t2为2时,修改温度(temp)下限值。     case 3:    T11=keyadd(T11); break;        //当t2为3时,修改温度(temp)上限值。     default: t2=0;          //当t2超过3,归零。   }    } 修改报警值
#include<keyadd.h>   Uchar keyadd(Uchar n) { if(KEY1 == 0)      //增加。      {    Delay1(20);        if(KEY1 == 0)          {while(!KEY1);                n++;          }   }          if(KEY2 == 0)         //减小。      {    Delay1(20);        if(KEY2 == 0)          {while(!KEY2);               n--;          }  } if(KEY3 == 0)       //警报开关修改标志位。      {    Delay1(20);        if(KEY3==0)          {while(!KEY3);               Y=~Y;      //标志位取反。          }  }    return n;       //返回修改值。 } 这是我的第一篇博客,在这里见了很多大佬,也学到点知识,对我的学习生活都有很大帮助,写的东西也是简单粗略,若有不足之处,望看官能够指出。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
 官方软件产品操作指南 (170)
官方软件产品操作指南 (170)