找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4155|回复: 4
收起左侧

关于超声波测距加LCD1602显示

[复制链接]
ID:339124 发表于 2018-7-13 16:45 | 显示全部楼层 |阅读模式
在LCD1602上只可以正确显示温度,其他都是初始化的值,硬件接在开发板上,东西型号都对的,求帮忙看看是否是程序问题,或者怎么写一段串口通信程序,用电脑串口看一下超声波是否有回传距离。
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char  //无符号字符型 宏定义        变量范围0~255
  4. #define uint  unsigned int         //无符号整型 宏定义        变量范围0~65535


  5. sbit c_send   = P1^5;                //超声波发射
  6. sbit c_recive = P3^2;                //超声波接收


  7. //这三个引脚参考资料
  8. sbit rs=P1^0;         //1602数据/命令选择引脚 H:数据              L:命令
  9. sbit rw=P1^1;         //1602读写引脚                 H:数据寄存器          L:指令寄存器
  10. sbit e =P2^5;         //1602使能引脚          下降沿触发
  11. uchar code table_num[]="0123456789abcdefg";
  12. sbit beep = P2^3;   //蜂鸣器IO口定义


  13. uint flag_300ms ;
  14. long distance;                //距离
  15. uint set_d = 100;                    //距离
  16. bit flag_csb_juli;        //超声波超出量程
  17. uint  flag_time0;     //用来保存定时器0的时候的
  18. uchar menu_1;        //菜单设计的变量


  19. uint code wendu_buchang1[46] = {                     //温度补偿表格
  20.                                                                 331,332,333,333,334,334,335,336,336,337,        // 0-9度
  21.                                                                 337,338,339,339,340,341,341,342,342,343,        //10-19度
  22.                                                                 343,344,345,345,346,346,347,348,348,349,        //20-29度
  23.                                                                 349,350,351,351,352,352,353,354,354,355,        //30-39度
  24.                                                                 355,356,357,357,358,358                         //40-45度
  25.                                                                 };


  26. sbit dq   = P2^4;        //18b20 IO口的定义
  27. uint temperature ;  //


  28. /***********************1ms延时函数*****************************/
  29. void delay_1ms(uint q)
  30. {
  31.         uint i,j;
  32.         for(i=0;i<q;i++)
  33.                 for(j=0;j<120;j++);
  34. }


  35. /********************************************************************
  36. * 名称 : delay_uint()
  37. * 功能 : 小延时。
  38. * 输入 : 无
  39. * 输出 : 无
  40. ***********************************************************************/
  41. void delay_uint(uint q)
  42. {
  43.         while(q--);
  44. }






  45. /********************************************************************
  46. * 名称 : write_com(uchar com)
  47. * 功能 : 1602命令函数
  48. * 输入 : 输入的命令值
  49. * 输出 : 无
  50. ***********************************************************************/
  51. void write_com(uchar com) //判断是否繁忙
  52. {
  53.         e=0;
  54.         rs=0;
  55.         rw=0;
  56.         P0=com;
  57.         delay_uint(25);
  58.         e=1;
  59.         delay_uint(100);
  60.         e=0;
  61. }


  62. /********************************************************************
  63. * 名称 : write_data(uchar dat)
  64. * 功能 : 1602写数据函数
  65. * 输入 : 需要写入1602的数据
  66. * 输出 : 无
  67. ***********************************************************************/
  68. void write_data(uchar dat)
  69. {
  70.         e=0;
  71.         rs=1;
  72.         rw=0;
  73.         P0=dat;
  74.         delay_uint(25);
  75.         e=1;
  76.         delay_uint(100);
  77.         e=0;        
  78. }


  79. /********************************************************************
  80. * 名称 : write_string(uchar hang,uchar add,uchar *p)
  81. * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
  82.                   write_string(1,5,"ab cd ef;")
  83. * 输入 : 行,列,需要输入1602的数据
  84. * 输出 : 无
  85. ***********************************************************************/
  86. void write_string(uchar hang,uchar add,uchar *p)
  87. {
  88.         if(hang==1)   
  89.                 write_com(0x80+add);
  90.         else
  91.                 write_com(0x80+0x40+add);
  92.                 while(1)
  93.                 {
  94.                         if(*p == '\0')  break;
  95.                         write_data(*p);
  96.                         p++;
  97.                 }        
  98. }


  99. /***********************lcd1602上显示两位十进制数************************/
  100. void write_sfm2(uchar hang,uchar add,uint date)
  101. {
  102.         if(hang==1)   
  103.                 write_com(0x80+add);
  104.         else
  105.                 write_com(0x80+0x40+add);
  106.         write_data(0x30+date/10%10);
  107.         write_data(0x30+date%10);      
  108. }


  109. /***********************lcd1602上显示超声波距离函数************************/
  110. void write_sfm3(uchar hang,uchar add,uint date)
  111. {
  112.         if(hang==1)   
  113.                 write_com(0x80+add);     //意思是指定地址在第1行的第add个位置
  114.         else
  115.                 write_com(0x80+0x40+add);//意思是指定地址在第2行(0x80+0x40 是第2行)的第add个位置
  116.         write_data(0x30+date/100%10);
  117.         write_data('.');
  118.         write_data(0x30+date/10%10);
  119.         write_data(0x30+date%10);        
  120. }




  121. /***********************lcd1602上显示特定的字符************************/
  122. void write_zifu(uchar hang,uchar add,uchar date)
  123. {
  124.         if(hang==1)   
  125.                 write_com(0x80+add);
  126.         else
  127.                 write_com(0x80+0x40+add);
  128.         write_data(date);        
  129. }






  130. /********************************************************************
  131. * 名称 : init_1602()
  132. * 功能 : 初始化1602液晶
  133. * 输入 : 无
  134. * 输出 : 无
  135. ***********************************************************************/
  136. void init_1602()      //1602初始化
  137. {
  138.         write_com(0x38);
  139.         write_com(0x0c);
  140.         write_com(0x06);
  141.         delay_uint(1000);
  142.         write_string(1,0,"juli:0.00m      ");
  143.         write_string(2,0," set:0.00m      ");
  144.         write_zifu(1,14,0xdf);  //显示度
  145.                 write_string(1,15,"C");        
  146. }




  147. /***********************18b20初始化函数*****************************/
  148. void init_18b20()
  149. {
  150.         bit q;
  151.         dq = 1;                                //把总线拿高
  152.         delay_uint(1);            //15us
  153.         dq = 0;                                //给复位脉冲
  154.         delay_uint(80);                //750us
  155.         dq = 1;                                //把总线拿高 等待
  156.         delay_uint(10);                //110us
  157.         q = dq;                                //读取18b20初始化信号
  158.         delay_uint(20);                //200us
  159.         dq = 1;                                //把总线拿高 释放总线
  160. }


  161. /*************写18b20内的数据***************/
  162. void write_18b20(uchar dat)
  163. {
  164.         uchar i;
  165.         for(i=0;i<8;i++)
  166.         {                                         //写数据是低位开始
  167.                 dq = 0;                         //把总线拿低写时间隙开始
  168.                 dq = dat & 0x01; //向18b20总线写数据了
  169.                 delay_uint(5);         // 60us
  170.                 dq = 1;                         //释放总线
  171.                 dat >>= 1;
  172.         }        
  173. }


  174. /*************读取18b20内的数据***************/
  175. uchar read_18b20()
  176. {
  177.         uchar i,value;
  178.         for(i=0;i<8;i++)
  179.         {
  180.                 dq = 0;                         //把总线拿低读时间隙开始
  181.                 value >>= 1;         //读数据是低位开始
  182.                 dq = 1;                         //释放总线
  183.                 if(dq == 1)                 //开始读写数据
  184.                         value |= 0x80;
  185.                 delay_uint(5);         //60us        读一个时间隙最少要保持60us的时间
  186.         }
  187.         return value;                 //返回数据
  188. }


  189. /*************读取温度的值 读出来的是小数***************/
  190. uint read_temp()
  191. {
  192.         uint value;
  193.         uchar low;                           //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
  194.         init_18b20();                   //初始化18b20
  195.         write_18b20(0xcc);           //跳过64位ROM
  196.         write_18b20(0x44);           //启动一次温度转换命令
  197.         delay_uint(50);                   //500us


  198.         init_18b20();                   //初始化18b20
  199.         
  200.         write_18b20(0xcc);           //跳过64位ROM
  201.         write_18b20(0xbe);           //发出读取暂存器命令
  202.         
  203.         EA = 0;
  204.         low = read_18b20();           //读温度低字节
  205.         value = read_18b20();  //读温度高字节
  206.         EA = 1;
  207.         value <<= 8;                   //把温度的高位左移8位
  208.         value |= low;                   //把读出的温度低位放到value的低八位中
  209.         value *= 0.0625;               //转换到温度值
  210.         return value;                   //返回读出的温度
  211. }


  212. /********************独立按键程序*****************/
  213. uchar key_can;         //按键值


  214. void key()         //独立按键程序
  215. {
  216.         static uchar temp,key_new;
  217.         key_can = 20;                                //按键值还原
  218.                 P3=0xfe;
  219.                 temp=P3;
  220.         temp=temp&0xf0;                                                                   //11110000松开时高电平1;按下时低电平0
  221.         if((P3 & 0xf0) != 0xf0)                //按键按下
  222.         {
  223.                 delay_1ms(10);                     //按键消抖动
  224.                 if((P3 & 0xf0) != 0xf0)
  225.                 {                                                //确认是按键按下
  226.                         
  227.                       switch(P3 & 0xf0)
  228.                         {
  229.                                 case 0x7e:  key_can = 3;  break;         //得到按键值 //1101 1110
  230.                                 case 0xbe:  key_can = 2;  break;         //得到按键值//        1011 0000
  231.                                 case 0xde:  key_can = 1;  break;         //得到按键值 //0111 0000
  232.                                     case 0xee:  key_can = 0;  break;
  233.                                                 }
  234.                 }
  235.                                 while(temp!=0xf0)
  236.          {
  237.            temp=P3;
  238.            temp=temp&0xf0;
  239.                 }
  240.                 }
  241. }
  242. /**************10us延时函数***************/
  243. void delay()
  244. {
  245.         _nop_();                            //执行一条_nop_()指令就是1us
  246.         _nop_();
  247.         _nop_();
  248.         _nop_();
  249.         _nop_();
  250.         _nop_();
  251.         _nop_();  
  252.         _nop_();
  253.         _nop_();
  254.         _nop_();  
  255.         _nop_();
  256. }




  257. /*********************超声波测距程序*****************************/
  258. void send_wave()
  259. {
  260.         c_send = 0;                           //10us的高电平触发
  261.         delay();
  262.         c_send = 1;         
  263.         TH0 = 0;                          //给定时器0清零
  264.         TL0 = 0;
  265.         TR0 = 0;                                  //关定时器0定时
  266.         while(!c_recive);                  //当c_recive为零时等待
  267.         while(c_recive)                      //当c_recive为1计数并等待
  268.         {
  269.                 flag_time0 = TH0 * 256 + TL0;
  270.                 if((flag_time0 > 40000))      //当超声波超过测量范围时,显示3个888
  271.                 {
  272.                         TR0 = 0;
  273.                         flag_csb_juli = 2;
  274.                         distance = 888;
  275.                         break ;               
  276.                 }
  277.                 else
  278.                 {
  279.                         flag_csb_juli = 1;        
  280.                 }
  281.         }
  282.         if(flag_csb_juli == 1)
  283.         {        
  284.                 TR0=0;                                                         //关定时器0定时
  285.                 distance =flag_time0;                         //读出定时器0的时间
  286.                 if(temperature <= 45)
  287.                         distance *= wendu_buchang1[temperature] / 2.0 * 0.0001;               // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
  288.                 else
  289.                         distance *= 358 / 2.0 * 0.0001;               // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
  290.                 if((distance > 500))                                 //距离 = 速度 * 时间
  291.                 {        
  292.                         distance = 888;                                 //如果大于5.0m就超出超声波的量程
  293.                 }
  294.         }  
  295. }




  296. /*********************定时器0、定时器1初始化******************/
  297. void time_init()         
  298. {
  299.         EA  = 1;                   //开总中断
  300.         TMOD = 0X11;          //定时器0、定时器1工作方式1
  301.         ET0 = 0;                  //关定时器0中断
  302.         TR0 = 1;                  //允许定时器0定时
  303.         ET1 = 1;                  //开定时器1中断
  304.         TR1 = 1;                  //允许定时器1定时        
  305. }


  306. /****************按键处理数码管显示函数***************/
  307. void key_with()
  308. {
  309.         if(key_can == 1)         //设置键
  310.         {
  311.                 menu_1 ++;
  312.                 if(menu_1 >= 2)
  313.                 {
  314.                         menu_1 = 0;
  315.                         init_1602() ;     //1602初始化
  316.                         write_sfm3(2,5,set_d);         //显示设置的距离
  317.                 }
  318.         }
  319.         if(menu_1 == 1)                        //设置距离报警
  320.         {
  321.                 if(key_can == 2)
  322.                 {
  323.                         set_d ++ ;                //按键按下未松开自动加三次        
  324.                         if(set_d > 400)
  325.                                 set_d = 400;
  326.                 }
  327.                 if(key_can == 3)
  328.                 {
  329.                         set_d -- ;                //按键按下未松开自动加三次        
  330.                         if(set_d <= 1)
  331.                                 set_d = 1;
  332.                 }
  333.                 write_sfm3(2,5,set_d);         //显示设置的距离
  334.                 write_com(0x80+0x40+6);  //将光标显示地址
  335.                 write_com(0x0f);         //显示光标并且闪烁
  336.         }        
  337. }  
  338. /****************报警函数***************/
  339. void clock_h_l()
  340. {
  341.         if(distance == set_d)
  342.         {
  343.                 beep = ~beep;           //蜂鸣器报警        
  344.         }
  345.         else
  346.         {
  347.                 beep = 1;                //取消报警
  348.         }        
  349. }


  350. /***************主函数*****************/
  351. void main()
  352. {
  353.         beep = 0;                 //开机蜂鸣器响一下
  354.         delay_1ms(150);
  355.         P0 = P1 = P2 = P3 = 0xff;  //单片机IO口初始化为1
  356.         time_init();          //定时器0、定时器1初始化
  357.         init_1602();      //1602初始化
  358.         write_sfm3(2,5,set_d);         //显示设置的距离
  359.         send_wave();        //测距离函数
  360.         while(1)
  361.         {
  362.                 flag_300ms ++;
  363.                 if(flag_300ms >= 300)
  364.                 {
  365.                         flag_300ms = 0;
  366.                         temperature = read_temp();        //先读出温度的值
  367.                         send_wave();        //测距离函数
  368.                         clock_h_l();    //报警函数
  369.                         if(menu_1 == 0)
  370.                         {
  371.                                 write_sfm3(1,5,distance);         //显示测定距离
  372.                                 write_sfm2(1,12,temperature);         //显示温度
  373.                         }
  374.                 }
  375.                 key();                                         //按键函数
  376.                 if(key_can < 10)
  377.                 {
  378.                         key_with();                         //按键处理函数
  379.                 }
  380.                 delay_1ms(1);
  381.         }
  382. }
复制代码




回复

使用道具 举报

ID:278079 发表于 2018-7-13 18:01 | 显示全部楼层
代码没怎么看。。distance是long类型,write_date是uint,还有是ucha,会不会跟这个有关?
回复

使用道具 举报

ID:339124 发表于 2018-7-20 13:11 | 显示全部楼层
a920366858 发表于 2018-7-13 18:01
代码没怎么看。。distance是long类型,write_date是uint,还有是ucha,会不会跟这个有关?

好的,谢谢回复,忙过这段时间试一试
回复

使用道具 举报

ID:339124 发表于 2018-9-23 20:37 | 显示全部楼层
a920366858 发表于 2018-7-13 18:01
代码没怎么看。。distance是long类型,write_date是uint,还有是ucha,会不会跟这个有关?

不是这个问题,我改了,还是显示不出来
回复

使用道具 举报

ID:475914 发表于 2019-4-5 09:50 | 显示全部楼层
请问你的代码问题解决了么?想学习一下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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