单片机 > 单片机程序设计 > 详情

如何编写51单片机超声波测距SR04_lcd1602显示程序

发布时间:2020-06-06 发布时间:
|

main.c     


  1. #include    

  2. #include   

  3. #include "lcd.h"  

  4.   

  5. unsigned char code ASCII[15] =    {'0','1','2','3','4','5','6','7','8','9','.','-','M'};  

  6.   

  7. static unsigned char DisNum = 0; //显示用指针                    

  8.        unsigned int  time=0;  

  9.        unsigned long S=0;  

  10.        bit      flag =0;  

  11.        unsigned char disbuff[4]    ={0,0,0,0};  

  12.   

  13. void Conut(void) ;  

  14. void  StartModule();                 //启动模块  

  15. void init_51(void);  

  16.   

  17. void  main(void)  

  18. {  

  19.     BELL = 0 ;  

  20.     Delay400Ms();  

  21.     LCMInit();  

  22.     init_51();    

  23.     while(1)  

  24.     {  

  25.          StartModule();  

  26.          while(!RX);        //当RX为零时等待  

  27.          TR0=1;             //开启计数  

  28.          while(RX);         //当RX为1计数并等待  

  29.          TR0=0;             //关闭计数  

  30.          Conut();           //计算  

  31.          if(S > 100){  

  32.             BELL = 1 ;   

  33.             Delay400Ms();  

  34.             BELL = 0 ;   

  35.             Delay400Ms();  

  36.          }  

  37.          delayms(80);       //80MS  

  38.     }  

  39. }  

  40.   

  41. void Conut(void)  

  42. {  

  43.      time=TH0*256+TL0;  

  44.      TH0=0;  

  45.      TL0=0;  

  46.       

  47.      S=(time*1.7)/100;     //算出来是CM  

  48.      if((S>=700)||flag==1) //超出测量范围显示“-”  

  49.      {     

  50.       flag=0;  

  51.       DisplayOneChar(0, 1, ASCII[11]);  

  52.       DisplayOneChar(1, 1, ASCII[10]);  //显示点  

  53.       DisplayOneChar(2, 1, ASCII[11]);  

  54.       DisplayOneChar(3, 1, ASCII[11]);  

  55.       DisplayOneChar(4, 1, ASCII[12]);  //显示M  

  56.      }  

  57.      else  

  58.      {  

  59.       disbuff[0]=S%1000/100;  

  60.       disbuff[1]=S%1000%100/10;  

  61.       disbuff[2]=S%1000%10 %10;  

  62.       DisplayOneChar(0, 1, ASCII[disbuff[0]]);  

  63.       DisplayOneChar(1, 1, ASCII[10]);  //显示点  

  64.       DisplayOneChar(2, 1, ASCII[disbuff[1]]);  

  65.       DisplayOneChar(3, 1, ASCII[disbuff[2]]);  

  66.       DisplayOneChar(4, 1, ASCII[12]);  //显示M  

  67.      }  

  68. }  

  69.   

  70. void zd0() interrupt 1       //T0中断用来计数器溢出,超过测距范围  

  71. {  

  72.     flag=1;                          //中断溢出标志  

  73. }  

  74. /********************************************************/  

  75. void  StartModule()                  //启动模块  

  76. {  

  77.       TX = 1;                                //启动一次模块  

  78.       _nop_();   

  79.       _nop_();   

  80.       _nop_();   

  81.       _nop_();   

  82.       _nop_();   

  83.       _nop_();   

  84.       _nop_();   

  85.       _nop_();   

  86.       _nop_();   

  87.       _nop_();   

  88.       _nop_();   

  89.       _nop_();   

  90.       _nop_();   

  91.       _nop_();   

  92.       _nop_();   

  93.       _nop_();   

  94.       _nop_();  

  95.       _nop_();   

  96.       _nop_();   

  97.       _nop_();   

  98.       _nop_();  

  99.       TX=0;  

  100. }  

  101.   

  102. void init_51(void)  

  103. {  

  104.     TMOD=0x01;         //设T0为方式1,GATE=1;  

  105.     TH0=0;  

  106.     TL0=0;            

  107.     ET0=1;             //允许T0中断  

  108.     EA=1;              //开启总中断   

  109.   

  110. }  

lcd.c



  1. #include"lcd.h"  

  2. //写数据  

  3. void WriteDataLCM(unsigned char WDLCM)   

  4. {  

  5.     ReadStatusLCM(); //检测忙  

  6.     LCM_Data = WDLCM;  

  7.     LCM_RS = 1;  

  8.     LCM_RW = 0;  

  9.     LCM_E = 0; //若晶振速度太高可以在这后加小的延时  

  10.     LCM_E = 0; //延时  

  11.     LCM_E = 1;  

  12. }  

  13.   

  14. //写指令  

  15. void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测  

  16. {  

  17.     if (BuysC) ReadStatusLCM(); //根据需要检测忙  

  18.     LCM_Data = WCLCM;  

  19.     LCM_RS = 0;  

  20.     LCM_RW = 0;   

  21.     LCM_E = 0;  

  22.     LCM_E = 0;  

  23.     LCM_E = 1;    

  24. }  

  25.   

  26. //读数据  

  27. unsigned char ReadDataLCM(void)  

  28. {  

  29.     LCM_RS = 1;   

  30.     LCM_RW = 1;  

  31.     LCM_E = 0;  

  32.     LCM_E = 0;  

  33.     LCM_E = 1;  

  34.     return(LCM_Data);  

  35. }  

  36.   

  37. //读状态  

  38. unsigned char ReadStatusLCM(void)  

  39. {  

  40.     LCM_Data = 0xFF;   

  41.     LCM_RS = 0;  

  42.     LCM_RW = 1;  

  43.     LCM_E = 0;  

  44.     LCM_E = 0;  

  45.     LCM_E = 1;  

  46.     while (LCM_Data & Busy); //检测忙信号  

  47.     return(LCM_Data);  

  48. }  

  49.   

  50. void LCMInit(void) //LCM初始化  

  51. {  

  52.     LCM_Data = 0;  

  53.     WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号  

  54.     Delay5Ms();   

  55.     WriteCommandLCM(0x38,0);  

  56.     Delay5Ms();   

  57.     WriteCommandLCM(0x38,0);  

  58.     Delay5Ms();   

  59.   

  60.     WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号  

  61.     WriteCommandLCM(0x08,1); //关闭显示  

  62.     WriteCommandLCM(0x01,1); //显示清屏  

  63.     WriteCommandLCM(0x06,1); // 显示光标移动设置  

  64.     WriteCommandLCM(0x0C,1); // 显示开及光标设置  

  65. }  

  66.   

  67. //按指定位置显示一个字符  

  68. void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)  

  69. {  

  70.     Y &= 0x1;  

  71.     X &= 0xF; //限制X不能大于15,Y不能大于1  

  72.     if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;  

  73.     X |= 0x80; //算出指令码  

  74.     WriteCommandLCM(X, 1); //发命令字  

  75.     WriteDataLCM(DData); //发数据  

  76. }  

  77.   

  78. //按指定位置显示一串字符  

  79. void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)  

  80. {  

  81.     unsigned char ListLength;  

  82.   

  83.   ListLength = 0;  

  84.     Y &= 0x1;  

  85.     X &= 0xF; //限制X不能大于15,Y不能大于1  

  86.     while (DData[ListLength]>0x19) //若到达字串尾则退出  

  87.         {  

  88.             if (X <= 0xF) //X坐标应小于0xF  

  89.                 {  

  90.                     DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符  

  91.                     ListLength++;  

  92.                     X++;  

  93.                 }  

  94.         }  

  95. }  

  96.   

  97. //5ms延时  

  98. void Delay5Ms(void)  

  99. {  

  100.     unsigned int TempCyc = 5552;  

  101.     while(TempCyc--);  

  102. }  

  103.   

  104. //400ms延时  

  105. void Delay400Ms(void)  

  106. {  

  107.     unsigned char TempCycA = 5;  

  108.     unsigned int TempCycB;  

  109.     while(TempCycA--)  

  110.         {  

  111.             TempCycB=7269;  

  112.             while(TempCycB--);  

  113.         };  

  114. }  

lcd.h



  1. #ifndef __LCD_H_  

  2. #define __LCD_H_  

  3. /********************************** 

  4. 当使用的是4位数据传输的时候定义, 

  5. 使用8位取消这个定义 

  6. **********************************/  

  7. #define LCD1602_4PINS  

  8.   

  9. /********************************** 

  10. 包含头文件 

  11. **********************************/  

  12. #include  

  13. #ifndef uchar  

  14. #define uchar unsigned char  

  15. #endif  

  16.   

  17. #ifndef uint   

  18. #define uint unsigned int  

  19. #endif  

  20.   

  21. sbit  RX = P1^0 ;   

  22. sbit  TX = P1^1 ;  

  23. sbit LCM_RW = P2^5 ;   

  24. sbit LCM_RS = P2^6 ;   

  25. sbit LCM_E = P2^7 ;   

  26. #define LCM_Data  P0  

  27.   

  28. #define Busy    0x80 //用于检测LCM状态字中的Busy标识  

  29. sbit  BELL = P2^1 ;   

  30.           

  31. void delayms(unsigned int ms);  

  32. void Delay400Ms(void);  

  33.   

  34. /*LCD1602初始化子程序*/  

  35. void LCMInit(void);  

  36. unsigned char ReadDataLCM(void);  

  37. //读状态  

  38. unsigned char ReadStatusLCM(void);  

  39. //5ms延时  

  40. void Delay5Ms(void);  

  41. //写数据  

  42. void WriteDataLCM(unsigned char WDLCM) ;  

  43. void WriteCommandLCM(unsigned char WCLCM,BuysC); //BuysC为0时忽略忙检测  

  44. //按指定位置显示一串字符  

  45. void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);  

  46. //按指定位置显示一个字符  

  47. void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);  

  48.              

  49.   

  50. #endif  

烧写到开发板上,现象如下:


没超出1m的情况下,不会报警。


超出1m后,蜂鸣器报警:


    





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM JTAG 调试原理