找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3212|回复: 3
打印 上一主题 下一主题
收起左侧

基于51单片机的LCD12864超声波测距+温湿度显示代码

[复制链接]
跳转到指定楼层
楼主
89c52rc单片机控制超声波测距和读取实时的温湿度情况,按键控制切换注释准确。
详情见文件

单片机源程序如下:
  1. #include <reg52.h>                         //51 的头文件
  2. #include <intrins.h>                       //超声波的固有函数头文件
  3. #define uchar unsigned char                //表示之后代码中的“uchar”全部代表“unsigned char”
  4. #define uint unsigned int                  //定义uint为无符号整型。
  5. #define LCD_databus P2                     //定义LCD的数据口为P2
  6. //全局变量定义
  7. unsigned int time;                       //声明无符号类型 time
  8. unsigned int S,s_false;                  //声明无符号类型  
  9. unsigned long num1;                      //声明无符号长整数
  10. bit flag;
  11. //12864液晶显示定义
  12. uchar code sj1[]={"<<超声波测距仪>>"};
  13. uchar code sj4[]={"当前距离:"};
  14. uchar code sj5[]={"错误 "};
  15. uchar dht_num=0; //用于while循环中计数,超时则跳出循环
  16. uchar code table[]={"温度:"};
  17. uchar code table1[]={"湿度:"};
  18. uchar code table2[]={"℃"};
  19. uchar dht_d1=0,dht_d2=0        ;        //依次为湿度整数部分和湿度小数部
  20. uchar dht_t1=0,dht_t2=0        ;  //依次为温度整数部分和温度小数部分
  21. uchar dht_j=0;              //和校验,可选择是否使用,具体参照数据手
  22. uchar i,t11,t12,d11,d12;
  23. uchar t21,t22,d21,d22;
  24. //超声波引脚定义                                                 
  25. sbit Trig =P1^0;          //定义引脚       
  26. sbit Echo =P1^1;
  27. //12864液晶引脚定义
  28. sbit RS=P0^7;          //命令数据
  29. sbit RW=P0^6;          //读写
  30. sbit EN =P0^5;
  31. sbit dht_dat=P1^2; //用哪个I/O口自选,注意不要用P2口
  32. //定义按键
  33. sbit key1 = P3^5;  
  34. sbit key2 = P3^4;
  35. /*****************ms延时函数*********************************/
  36. void delay(uint z)
  37. {
  38.         uint x,y;
  39.         for(x=z;x>0;x--)
  40.                 for(y=110;y>0;y--);
  41. }
  42. /*****************20us延时函数*********************************/
  43. void delay_20us()
  44. {
  45.         uchar a;
  46.         for(a=0;a<100;a++);
  47. }

  48. /*****************ms延时函数*********************************/
  49. void dh11delayms(uint xms)
  50. {
  51. uint i,j;
  52. for(i=xms;i>0;i--)
  53.         for(j=110;j>0;j--);
  54. }
  55. /*****************us延时函数*****************************/
  56. void delay_10us()
  57. {
  58.         _nop_();
  59.         _nop_();
  60.         _nop_();
  61.         _nop_();
  62.         _nop_();
  63.         _nop_();
  64. }

  65. /*写指令函数*/
  66. /*rs=l,rw=l,en=高脉冲,D0-D7=指令码。*/
  67. void write_cmd(uchar cmd)
  68. {
  69.         RS=0;
  70.         RW=0;
  71.         EN=0;
  72.         LCD_databus=cmd;
  73.         dh11delayms(5);
  74.         EN=1;
  75.         dh11delayms(5);
  76.         EN=0;
  77. }

  78. /***************************写显示数据************************/
  79. /*rs=h,rw=l,*/
  80. void write_dat(uchar date)
  81. {
  82. RS=1;
  83. RW=0;
  84. EN=0;
  85. LCD_databus=date;
  86. dh11delayms(5);
  87. EN=1;
  88. dh11delayms(5);
  89. EN=0;
  90. }

  91. /*****************初始化************************/
  92. void DH11init()
  93. {        
  94.         EN=0;
  95.         RW=0;
  96.      

  97.         write_cmd(0x30);                //基本指令操作
  98.         dh11delayms(5);
  99.         write_cmd(0x0c);                //显示开,关光标
  100.         dh11delayms(5);
  101.         write_cmd(0x06);
  102.         dh11delayms(2);
  103.         write_cmd(0x01);                //清除显示内容
  104.         dh11delayms(5);
  105.                                 
  106.                                                                                                         
  107. }
  108. void dht_init()
  109. {
  110.    dh11delayms(1000);          //DHT11上电前准备时间,大概1s
  111.    dht_dat=1;             //         //总线准备
  112. }
  113. uchar read_date()        //接收一个8位数据,先高位后低位
  114. {
  115.         uchar i,dat;
  116.         for(i=0;i<8;i++)   //也就是说程序是循环八次,把判断有“1”输出到dat中,然后输出一个八位的数据。
  117.         {
  118.                 dht_num=2;
  119.                 while((dht_dat==0)&&(dht_num++)); //dht_dat 数据线由DH11拉低准备发送数据
  120.                 delay_10us();
  121.                                 delay_10us();
  122.                 delay_10us();
  123.                                 delay_10us();
  124.                 dat=dat<<1;
  125.                 if(dht_dat==1)
  126.                 {
  127.                         dht_num=2;
  128.                         dat=dat|0x01;  //如果来自DQ的数据是高电平1,则把1放到dat的最低位
  129.                         while((dht_dat==1)&&(dht_num++));

  130.                 }
  131.         }
  132.         return dat;        
  133. }

  134. void get_temp()        //给DHT11一个开始信号,然后读取一次数据,共五个8位字节
  135. {
  136.         dht_dat=0;
  137.         dh11delayms(25);
  138.         dht_dat=1;        //单片机给起始脉冲信号

  139.         delay_10us();
  140.         delay_10us();
  141.         delay_10us();
  142.         delay_10us();
  143.         dht_dat=1;         //稍作延时,等待DHT11返回响应(响应为低电 平)
  144.         if(dht_dat==0)         //有响应才接收数据,否则不作处理
  145.         {
  146.                 dht_num=2;
  147.                 while((dht_dat==0)&&(dht_num++));
  148.                 dht_num=2;
  149.                 while((dht_dat==1)&&(dht_num++));
  150.                 dht_d1=read_date();
  151.                 dht_d2=read_date();
  152.                 dht_t1=read_date();
  153.                 dht_t2=read_date();
  154.                 dht_j=read_date(); //一次读出五个数据
  155.         }
  156.         dht_dat=1;        //释放总线
  157.         dh11delayms(10);

  158.         d11=dht_d1/10;
  159.         d12=dht_d1%10;
  160.         t11=dht_t1/10;
  161.         t12=dht_t1%10;
  162.                
  163.                 d21=dht_d2/10;
  164.         d22=dht_d2%10;
  165.         t21=dht_t2/10;
  166.         t22=dht_t2%10;
  167.                                    
  168. }

  169. //2864液晶写命令函数
  170. void xmn(unsigned char com)
  171. {
  172.         RS=0;
  173.         LCD_databus=com;
  174.         delay(5);
  175.         EN=1;
  176.         delay(5);
  177.         EN=0;
  178. }
  179. //2864液晶写数据函数
  180. void xsj(unsigned char zifu)
  181. {
  182.         RS=1;
  183.         LCD_databus=zifu;
  184.         delay(5);
  185.         EN=1;
  186.         delay(5);
  187.         EN=0;
  188. }
  189. //2864液晶显示函数1
  190. void xs1()
  191. {
  192.         uchar i;
  193.         xmn(0x80);
  194.         for(i=0;i<16;i++)
  195.         {
  196.                 xsj(sj1[i]);
  197.         }
  198.        
  199.        
  200.         xmn(0x88);
  201.         for(i=0;i<16;i++)
  202.         {
  203.                 xsj(sj4[i]);
  204.         }
  205. }
  206. //2864液晶显示函数2
  207. void xs2(uint t_emp)
  208. {
  209.         uchar qian,bai,shi,ge;
  210.         qian=t_emp/1000;
  211.         bai=(t_emp%1000)/100;
  212.         shi=(t_emp%100)/10;
  213.         ge=t_emp%10;

  214.         xmn(0x8d);
  215.         xsj(0x30+qian);
  216.         delay(1);
  217.         xsj(0x30+bai);
  218.         delay(1);
  219.         xsj(0x30+shi);
  220.         delay(1);
  221.         xsj(0x30+ge);
  222.         delay(1);
  223.         xsj('c');
  224.         delay(1);
  225.         xsj('m');
  226.         delay(100);
  227. }
  228. //超声波计数函数
  229. void T0_time() interrupt 1  //T0中断用来计数器溢出,超过测距范围
  230. {
  231.         flag=0;                  //中断溢出标志,失败
  232.         TH0=0;
  233.         TL0=0;
  234.         TR0=0;                   //关闭计数
  235. }
  236. //中断定时函数
  237. void T1_timer() interrupt 3 //中断
  238. {
  239.         TH1=(65536-50000)/256;
  240.         TL1=(65536-50000)%256;
  241.         num1++;
  242. }
  243. //超声波模块启动函数
  244. void StartModule()          //启动模块
  245. {
  246.         Trig=1;                 //启动一次模块
  247.         _nop_();_nop_();_nop_();_nop_();_nop_();
  248.         _nop_();_nop_();_nop_();_nop_();_nop_();
  249.         _nop_();_nop_();_nop_();_nop_();_nop_();
  250.         _nop_();_nop_();_nop_();_nop_();_nop_();
  251.         _nop_();
  252.         Trig=0;
  253. }
  254. //超声波测试距离计算函数
  255. void Count(void)
  256. {
  257.         uchar i;
  258.         time=TH0*256+TL0;
  259.         TH0=0;
  260.         TL0=0;
  261.         S=(time*1.7)/100;               //算出来是CM
  262.         if(((S<1)||(S>=600))||flag==0)  //超出测量范围显示“-”失败
  263.         {
  264.                
  265.                 s_false=1000;
  266.                 xmn(0x8d);
  267.                 for(i=0;i<6;i++)
  268.                 {
  269.                         xsj(sj5[i]);
  270.                 }
  271.                
  272.         }
  273.         else
  274.         {
  275.                 xs2(S);
  276.         }
  277. }
  278. //12864液晶初始化函数
  279. void init()
  280. {
  281.         delay(100);
  282.         xmn(0x30);
  283.         delay_20us();
  284.         xmn(0x30);
  285.         delay_20us();
  286.         xmn(0x0c);
  287.         delay_20us();
  288.         xmn(0x01);
  289.         delay_20us();
  290.         xmn(0x06);
  291.         delay_20us();
  292. }

  293. void WSD()
  294. {
  295.         dht_init();
  296.         DH11init();                                    
  297.    while(1)
  298.    {
  299.                 get_temp();
  300.                
  301.         
  302.                
  303.                
  304.                 write_cmd(0x80);
  305.                 for(i=0;i<6;i++)
  306.                 {
  307.                 write_dat(table[i]);
  308.                 }
  309.                 write_cmd(0x83);        
  310.                 write_dat(0x30+t11);
  311.                 write_dat(0x30+t12);
  312.                                 write_cmd(0x80+4);
  313.                                 write_dat('.');                                         
  314.                 write_dat(0x30+t21);
  315.                 write_cmd(0x85);                                
  316.                 write_dat(0x30+t22);                                                      
  317.                 write_cmd(0x86);
  318.         for(i=0;i<4;i++)
  319.         {
  320.          write_dat(table2[i]);                                 
  321.         }

  322.                 write_cmd(0x90);
  323.         for(i=0;i<6;i++)
  324.         {
  325.           write_dat(table1[i]);
  326.         }
  327.                 write_cmd(0x93);
  328.         write_dat(0x30+d11);
  329.                 write_dat(0x30+d12);
  330.                 write_cmd(0x94);
  331.                 write_dat('.');                                                
  332.                 write_dat(0x30+d21);
  333.                 write_cmd(0x95);
  334.                 write_dat(0x30+d22);
  335.                 write_cmd(0x96);
  336.         write_dat('%');                                                                                                                                                                                                           
  337.    }
  338. }



  339. void CSB()
  340. {


  341.         delay(500);    //启动等待,等LCM讲入工作状态
  342.         RW=0;
  343.         init();        //LCM初始化
  344.         delay(500);    //延时片刻(可不要)
  345.         while(1)
  346.         {
  347.                 TMOD=0x11; //设T0为方式1,GATE=1;
  348.                 TH0=0;
  349.                 TL0=0;
  350.                 ET0=1;     //允许T0中断
  351.                 ET1=1;
  352.                 TR1=1;
  353.                 EA=1;      //开启总中断

  354.                 xs1();

  355.                 Trig=0;
  356.                 Echo=0;
  357.                 while(1)
  358.                 {
  359.                         StartModule();
  360.                         flag=1;
  361.                         //while(!Echo);      //当echo为零时等待
  362.                         while((!Echo)&&flag);//当echo为零时等待,中断flag跳出等待
  363.                         TR0=1;               //开启计数
  364.                         while(Echo&&flag);   //当echo为1计数并等待
  365.                         TR0=0;               //关闭计数
  366.                         Count();             //计算
  367.                         delay(120);          //80MS
  368.                 }
  369.         }
  370. }


  371. void keyscan()  
  372. {  


  373. if(key1 == 0)  
  374.   {  

  375.     if(key1 == 0)  
  376.     {  
  377. CSB();
  378.     }   
  379.   }  
  380.   
  381.   if(key2 == 0)  
  382.   {  
  383.   
  384.     if(key2 == 0)  
  385. WSD();  
  386.   }  
  387. }
  388.   
  389. void main(void)
  390.        
  391. {
  392.         while(1)
  393.                
  394.         {
  395.        
  396.         keyscan();}
  397. }
复制代码

以上的代码51hei提供下载:
整合版本加按键.zip (61.35 KB, 下载次数: 128)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏6 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:883975 发表于 2021-5-3 19:13 | 只看该作者
超声波模块用的哪一个呢
回复

使用道具 举报

板凳
ID:833834 发表于 2021-8-9 10:31 | 只看该作者
风浪彼岸 发表于 2021-5-3 19:13
超声波模块用的哪一个呢

HC-SR04
回复

使用道具 举报

地板
ID:372579 发表于 2022-2-24 07:44 来自手机 | 只看该作者
这个可不可以用 Oled
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表