找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2663|回复: 2
收起左侧

基于51单片机多路超声波显示源程序

[复制链接]
ID:699194 发表于 2020-4-29 00:35 | 显示全部楼层 |阅读模式
本人测试成功,程序绝对可用的

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. #define uchar unsigned char        // 以后unsigned char就可以用uchar代替
  4. #define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

  5. sfr ISP_DATA  = 0xe2;                        // 数据寄存器
  6. sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
  7. sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
  8. sfr ISP_CMD   = 0xe5;                        // 命令寄存器
  9. sfr ISP_TRIG  = 0xe6;                        // 命令触发寄存器
  10. sfr ISP_CONTR = 0xe7;                        // 命令寄存器

  11. sbit LcdRs_P   = P2^7;                // 1602液晶的RS管脚      
  12. sbit LcdRw_P   = P2^6;                // 1602液晶的RW管脚
  13. sbit LcdEn_P   = P2^5;                // 1602液晶的EN管脚
  14. sbit Trig1_P   = P2^3;                // 超声波模块1的Trig管脚
  15. sbit Echo1_P   = P2^4;                // 超声波模块1的Echo管脚
  16. sbit Trig2_P   = P1^5;                // 超声波模块2的Trig管脚
  17. sbit Echo2_P   = P1^6;                // 超声波模块2的Echo管脚
  18. sbit KeySet_P  = P1^0;                // 设置按键的管脚
  19. sbit KeyDown_P = P1^1;                // 减按键的管脚
  20. sbit KeyUp_P   = P1^2;                // 加按键的管脚
  21. sbit Buzzer_P  = P2^0;                // 蜂鸣器的管脚
  22. sbit Led1_P    = P2^2;                // 传感器1报警灯
  23. sbit Led2_P    = P3^3;                // 传感器2报警灯

  24. uint gAlarm;                                                        // 报警距离变量



  25. /*********************************************************/
  26. // 单片机内部EEPROM不使能
  27. /*********************************************************/
  28. void ISP_Disable()
  29. {
  30.         ISP_CONTR = 0;
  31.         ISP_ADDRH = 0;
  32.         ISP_ADDRL = 0;
  33. }


  34. /*********************************************************/
  35. // 从单片机内部EEPROM读一个字节,从0x2000地址开始
  36. /*********************************************************/
  37. unsigned char EEPROM_Read(unsigned int add)
  38. {
  39.         ISP_DATA  = 0x00;
  40.         ISP_CONTR = 0x83;
  41.         ISP_CMD   = 0x01;
  42.         ISP_ADDRH = (unsigned char)(add>>8);
  43.         ISP_ADDRL = (unsigned char)(add&0xff);
  44.         // 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
  45.         ISP_TRIG  = 0x46;          
  46.         ISP_TRIG  = 0xB9;
  47.         _nop_();
  48.         ISP_Disable();
  49.         return (ISP_DATA);
  50. }


  51. /*********************************************************/
  52. // 往单片机内部EEPROM写一个字节,从0x2000地址开始
  53. /*********************************************************/
  54. void EEPROM_Write(unsigned int add,unsigned char ch)
  55. {
  56.         ISP_CONTR = 0x83;
  57.         ISP_CMD   = 0x02;
  58.         ISP_ADDRH = (unsigned char)(add>>8);
  59.         ISP_ADDRL = (unsigned char)(add&0xff);
  60.         ISP_DATA  = ch;
  61.         ISP_TRIG  = 0x46;
  62.         ISP_TRIG  = 0xB9;
  63.         _nop_();
  64.         ISP_Disable();
  65. }


  66. /*********************************************************/
  67. // 擦除单片机内部EEPROM的一个扇区
  68. // 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
  69. /*********************************************************/
  70. void Sector_Erase(unsigned int add)          
  71. {
  72.         ISP_CONTR = 0x83;
  73.         ISP_CMD   = 0x03;
  74.         ISP_ADDRH = (unsigned char)(add>>8);
  75.         ISP_ADDRL = (unsigned char)(add&0xff);
  76.         ISP_TRIG  = 0x46;
  77.         ISP_TRIG  = 0xB9;
  78.         _nop_();
  79.         ISP_Disable();
  80. }



  81. /*********************************************************/
  82. // 毫秒级的延时函数,time是要延时的毫秒数
  83. /*********************************************************/
  84. void DelayMs(uint time)
  85. {
  86.         uint i,j;
  87.         for(i=0;i<time;i++)
  88.                 for(j=0;j<112;j++);
  89. }


  90. /*********************************************************/
  91. // 1602液晶写命令函数,cmd就是要写入的命令
  92. /*********************************************************/
  93. void LcdWriteCmd(uchar cmd)
  94. {
  95.         LcdRs_P = 0;
  96.         LcdRw_P = 0;
  97.         LcdEn_P = 0;
  98.         P0=cmd;
  99.         DelayMs(2);
  100.         LcdEn_P = 1;   
  101.         DelayMs(2);
  102.         LcdEn_P = 0;       
  103. }


  104. /*********************************************************/
  105. // 1602液晶写数据函数,dat就是要写入的数据
  106. /*********************************************************/
  107. void LcdWriteData(uchar dat)
  108. {
  109.         LcdRs_P = 1;
  110.         LcdRw_P = 0;
  111.         LcdEn_P = 0;
  112.         P0=dat;
  113.         DelayMs(2);
  114.         LcdEn_P = 1;   
  115.         DelayMs(2);
  116.         LcdEn_P = 0;
  117. }


  118. /*********************************************************/
  119. // 液晶光标定位函数
  120. /*********************************************************/
  121. void LcdGotoXY(uchar line,uchar column)
  122. {
  123.         // 第一行
  124.         if(line==0)        
  125.                 LcdWriteCmd(0x80+column);
  126.         // 第二行
  127.         if(line==1)        
  128.                 LcdWriteCmd(0x80+0x40+column);
  129. }



  130. /*********************************************************/
  131. // 液晶输出字符串函数
  132. /*********************************************************/
  133. void LcdPrintStr(uchar *str)
  134. {
  135.         while(*str!='\0')
  136.                         LcdWriteData(*str++);
  137. }


  138. /*********************************************************/
  139. // 液晶输出数字
  140. /*********************************************************/
  141. void LcdPrintNum(uint num)
  142. {
  143.         LcdWriteData(num/100+0x30);                                // 百位
  144.         LcdWriteData(num%100/10+0x30);                // 十位
  145.         LcdWriteData(num%10+0x30);                                // 个位
  146. }


  147. /*********************************************************/
  148. // 1602液晶功能初始化
  149. /*********************************************************/
  150. void LcdInit()
  151. {
  152.         LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
  153.         LcdWriteCmd(0x0C);        // 开显示,不显示光标
  154.         LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
  155.         LcdWriteCmd(0x01);        // 清屏
  156. }



  157. /*********************************************************/
  158. // 1602液晶显示内容初始化
  159. /*********************************************************/
  160. void LcdShowInit()
  161. {
  162.         LcdGotoXY(0,0);                                                                    // 定位到第0行第0列
  163.         LcdPrintStr("  dist1=   cm   ");        // 第0行显示“  dist1=   cm   ”
  164.         LcdGotoXY(1,0);                                                                    // 定位到第1行第0列
  165.         LcdPrintStr("  dist2=   cm   ");        // 第1行显示“  dist2=   cm   ”
  166. }


  167. /*********************************************************/
  168. // 计算传感器1测量到的距离
  169. /*********************************************************/
  170. uint GetDistance1(void)
  171. {
  172.         uint ss;                                        // 用于记录测得的距离

  173.         TH0=0;
  174.         TL0=0;

  175.         Trig1_P=1;                                // 给超声波模块1一个开始脉冲
  176.         DelayMs(1);
  177.         Trig1_P=0;

  178.         while(!Echo1_P);        // 等待超声波模块1的返回脉冲
  179.         TR0=1;                                                // 启动定时器,开始计时
  180.         while(Echo1_P);                // 等待超声波模块1的返回脉冲结束
  181.         TR0=0;                                                // 停止定时器,停止计时

  182.         ss=((TH0*256+TL0)*0.034)/2;                // 距离cm=(时间us * 速度cm/us)/2
  183.         return ss;
  184. }


  185. /*********************************************************/
  186. // 计算传感器2测量到的距离
  187. /*********************************************************/
  188. uint GetDistance2(void)
  189. {
  190.         uint ss;                                        // 用于记录测得的距离

  191.         TH0=0;
  192.         TL0=0;

  193.         Trig2_P=1;                                // 给超声波模块2一个开始脉冲
  194.         DelayMs(1);
  195.         Trig2_P=0;

  196.         while(!Echo2_P);        // 等待超声波模块2的返回脉冲
  197.         TR0=1;                                                // 启动定时器,开始计时
  198.         while(Echo2_P);                // 等待超声波模块2的返回脉冲结束
  199.         TR0=0;                                                // 停止定时器,停止计时

  200.         ss=((TH0*256+TL0)*0.034)/2;                // 距离cm=(时间us * 速度cm/us)/2
  201.         return ss;
  202. }


  203. /*********************************************************/
  204. // 按键扫描
  205. /*********************************************************/
  206. void KeyScanf()
  207. {
  208.         if(KeySet_P==0)                                        // 判断是否有按键按下
  209.         {
  210.                 LcdGotoXY(0,0);                                                                    // 光标定位
  211.                 LcdPrintStr("   Alarm Set    ");        // 第0行显示“   Alarm Set    ”
  212.                 LcdGotoXY(1,0);                                                                                // 光标定位
  213.                 LcdPrintStr("  alarm=   cm   ");        // 第1行显示“  alarm=   cm   ”
  214.                 LcdGotoXY(1,8);                                                                                // 光标定位
  215.                 LcdPrintNum(gAlarm);                                                        // 显示当前的报警值

  216.                 DelayMs(10);                                                                                        // 消除按键按下的抖动
  217.                 while(!KeySet_P);                                                                        // 等待按键释放
  218.                 DelayMs(10);                                                                                        // 消除按键松开的抖动               

  219.                 while(1)
  220.                 {               
  221.                         /* 报警值减的处理 */
  222.                         if(KeyDown_P==0)                                       
  223.                         {
  224.                                 if(gAlarm>2)                                                // 报警值大于2才能减1
  225.                                         gAlarm--;                                                        // 报警值减1
  226.                                 LcdGotoXY(1,8);                                        // 光标定位
  227.                                 LcdPrintNum(gAlarm);                // 刷新修改后的报警值
  228.                                 DelayMs(300);                                                // 延时
  229.                         }

  230.                         /* 报警值加的处理 */
  231.                         if(KeyUp_P==0)                                       
  232.                         {
  233.                                 if(gAlarm<400)                                        // 报警值小于400才能加1
  234.                                         gAlarm++;                                                        // 报警值加1
  235.                                 LcdGotoXY(1,8);                                        // 光标定位
  236.                                 LcdPrintNum(gAlarm);                // 刷新修改后的报警值
  237.                                 DelayMs(300);                                                // 延时
  238.                         }
  239.                        
  240.                         /* 退出报警值设置 */
  241.                         if(KeySet_P==0)                                       
  242.                         {
  243.                                 break;                                                                        // 退出while循环
  244.                         }       
  245.                 }
  246.                
  247.                 LcdShowInit();                                                        // 液晶恢复测量到测量界面
  248.                 DelayMs(10);                                                          // 消除按键按下的抖动
  249.                 while(!KeySet_P);                                                // 等待按键释放
  250.                 DelayMs(10);                                                          // 消除按键松开的抖动               

  251.                 Sector_Erase(0x2000);                                // 保存报警距离
  252.                 EEPROM_Write(0x2000,gAlarm/100);
  253.                 EEPROM_Write(0x2001,gAlarm%100);               
  254.         }       
  255. }


  256. /*********************************************************/
  257. // 传感器1报警判断
  258. /*********************************************************/
  259. void AlarmJudge1(uint ss)
  260. {
  261.         if(ss<gAlarm)                // LED灯判断
  262.         {
  263.                 Led1_P=0;
  264.         }
  265.         else
  266.         {
  267.                 Led1_P=1;
  268.         }
  269.        
  270.         if((Led1_P==0)||(Led2_P==0))        // 蜂鸣器判断
  271.         {
  272.                 Buzzer_P=0;
  273.         }
  274.         else
  275.         {
  276.                 Buzzer_P=1;
  277.         }
  278. }


  279. /*********************************************************/
  280. // 传感器2报警判断
  281. /*********************************************************/
  282. void AlarmJudge2(uint ss)
  283. {
  284.         if(ss<gAlarm)                // LED灯判断
  285.         {
  286.                 Led2_P=0;
  287.         }
  288.         else
  289.         {
  290.                 Led2_P=1;
  291.         }
  292.        
  293.         if((Led1_P==0)||(Led2_P==0))        // 蜂鸣器判断
  294.         {
  295.                 Buzzer_P=0;
  296.         }
  297.         else
  298.         {
  299.                 Buzzer_P=1;
  300.         }
  301. }


  302. /*********************************************************/
  303. // 报警值初始化
  304. /*********************************************************/
  305. void AlarmInit()
  306. {
  307.         gAlarm=EEPROM_Read(0x2000)*100+EEPROM_Read(0x2001);                // 从EEPROM读取报警值

  308.         if((gAlarm==0)||(gAlarm>400))                        // 如果读取到的报警值异常(等于0或大于400则认为异常)
  309.         {
  310.                 gAlarm=25;                                                                                        // 重新赋值报警值为25
  311.         }
  312. }



  313. /*********************************************************/
  314. // 主函数
  315. /*********************************************************/
  316. void main()
  317. {
  318.         uchar i;                                                                        // 循环变量
  319.         uint dist;                                                                // 保存测量结果

  320.         LcdInit();                                                                // 液晶功能初始化
  321.         LcdShowInit();                                                // 液晶显示内容初始化
  322.         AlarmInit();                                                        // 报警值初始化
  323.        
  324.         TMOD = 0x01;                                                        // 选择定时器0,并且确定是工作方式1(为了超声波模块测量距离计时用的)

  325.         Trig1_P=0;                                                                // 初始化触发引脚为低电平
  326.         Trig2_P=0;

  327.         while(1)
  328.         {
  329.                 /*传感器1*/
  330.                 dist=GetDistance1();                // 读取超声波模块1测量到的距离
  331.                 LcdGotoXY(0,8);                            // 光标定位
  332.                 LcdPrintNum(dist);                        // 显示传感器1测量到的距离
  333.                 AlarmJudge1(dist);                        // 判断传感器1的测量距离是否需要报警
  334.                
  335.                 /*延时并扫描按键*/
  336.                 for(i=0;i<20;i++)
  337.                 {
  338.                         KeyScanf();
  339.                         DelayMs(10);
  340.                 }
  341.                
  342.                 /*传感器2*/
  343.                 dist=GetDistance2();                // 读取超声波模块2测量到的距离
  344.                 LcdGotoXY(1,8);                            // 光标定位
  345.                 LcdPrintNum(dist);                        // 显示传感器2测量到的距离
  346.                 AlarmJudge2(dist);                        // 判断传感器2的测量距离是否需要报警
  347.                
  348.                 /*延时并扫描按键*/
  349.                 for(i=0;i<20;i++)
  350.                 {
  351.                         KeyScanf();
  352.                         DelayMs(10);
  353.                 }
  354.         }
  355. }
复制代码

回复

使用道具 举报

ID:632112 发表于 2020-5-20 09:33 | 显示全部楼层
正在找呢,谢谢楼主
回复

使用道具 举报

ID:761098 发表于 2020-5-28 09:18 | 显示全部楼层
楼主 有没有测量的数据?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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