找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+超声波测距模块数码管显示问题

[复制链接]
跳转到指定楼层
楼主
ID:381345 发表于 2018-8-3 21:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请问各位大佬,我想让超声波测出来的距离显示在数码管上,但是我这个程序只在开电的瞬间测出距离并显示在数码管上,然后数码管就一直显示那个数字,超声波也不工作了,请问怎么回事?代码如下。谢谢。。。

  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include <STDIO.H>

  4. /* 1m所需周期:1000mm/(1微秒的声波距离mm * 1周期的us时间) => 1000/(0.17*1.0851);
  5.    4m = 1000/(0.17*1.0851) * 4 = 21684   */
  6. #define uchar unsigned char
  7. #define iMAX_LEN 21684
  8. #define iMIN_LEN 109

  9. sbit trig = P3^0;
  10. sbit echo = P3^1;

  11. sbit ADDR0 = P1^0;
  12. sbit ADDR1 = P1^1;
  13. sbit ADDR2 = P1^2;
  14. sbit ADDR3 = P1^3;
  15. sbit ENLED = P1^4;

  16. /****************V数码管模块*****************************************************************************/
  17. unsigned char code LedChar[] = {  //数码管显示字符转换表
  18.                                0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  19.                                0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  20.                                };
  21. unsigned char LedBuff[6] = {  //数码管显示缓冲区,初值0xFF确保启动时都不亮
  22.                                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  23.                            },
  24.                           buf[6],
  25.                           i = 0,
  26.                           j;
  27. /*************** ^超声波模块*****************************************************************************/

  28. /****************V超声波模块*****************************************************************************/         
  29. unsigned long miDistance=0, //测距的距离值
  30.               distance = 0;
  31. uchar mcDistanceErr=0; //测距错误标记(0:正常 / 1:距离太近 /2:超量程)
  32. bit mbDelayOverFlg = 1;        //延迟程序的控制标记(默认为延迟结束否则无法进入refreshDistance()函数)
  33. uchar mbDelay10H, mbDelay10L; //测距的小单位时间延迟
  34.          
  35. /* 定时器函数,T1计数器使用3号中断
  36. *作用:用于延迟出发测距,每次测距完成后,需要延迟>60ms
  37. *因此当计数器溢出时,time=65.535ms,mbDelayCtlFlg=1    */
  38. void tim1_()interrupt 3
  39. {        
  40.         TR1 = 0; //T1关闭计数器
  41.         mbDelayOverFlg = 1; //设定延迟结束
  42. }
  43.          
  44. /*启动超声波测距模块,TX保持22us的高电平*/
  45. void StartModule()
  46. {
  47.     trig = 1; //控制端置1
  48.         _nop_();
  49.         _nop_();
  50.         _nop_();
  51.         _nop_();
  52.         _nop_();
  53.         _nop_();
  54.         _nop_();
  55.         _nop_();
  56.         _nop_();
  57.         _nop_();
  58.         _nop_();
  59.         _nop_();
  60.         _nop_();
  61.         _nop_();
  62.         _nop_();
  63.         _nop_();
  64.         _nop_();
  65.         _nop_();
  66.         _nop_();
  67.         _nop_();
  68.         _nop_();
  69.         trig = 0; //控制端置0,等待接收回波
  70. }
  71.          
  72. /*获取最近一次测得的距离
  73. *注意:每次成功测距,需要耗时100ms-150ms左右时间*/
  74. unsigned int getDistance(void)
  75. {
  76.         return miDistance;
  77. }
  78.          
  79. /*获取最近一次的测距状态
  80. *@return unsigned int 0:正常 / 1:(err)距离太近 /2:(err)超量程*/
  81. unsigned int getDistanceState(void)
  82. {
  83.         return mcDistanceErr;
  84. }
  85.          
  86. /*检查距离操作(将测得的距离保存在公共变量中)
  87. *备注:本函数调用完成后,需要通过getDistance()或getDistanceState()获得结果
  88. *注意:每次成功测距,需要耗时100ms-150ms左右时间
  89. *@return 0:完成测距操作 / 1:正在延迟等待下次测距的开始*/
  90. unsigned char refreshDistance(void)
  91. {
  92.         unsigned int i; //超量程检测变量
  93.         unsigned int iCycle; //计算总周期         
  94.         if (1 == mbDelayOverFlg)//判断是否在延迟期
  95.         {        
  96.                 i = iMAX_LEN; //置入最大量程
  97.                 StartModule(); //发送测距模块启动信号
  98.                 /*此语句的作用:
  99.                 *没有收到回波且在N(iMAX_LEN*N)米障碍物信号返回需要的时间前则等待
  100.                 *(无信号即时返回,防止死循环,阻碍其它程序的执行)*/
  101.                 while(!echo && i-->0);
  102.                 //判断处理结果
  103.                 if (i>0) //小于N米
  104.                 {
  105.                         TR1=1; //收到回波的上边沿(RX=1),打开计数器
  106.                         while(echo);//当回波RX=0时,测距结束
  107.                         TR1=0; //关闭定时器(需要一个时钟周期)
  108.                         iCycle = (TH1 * 256 + TL1) + 1; //计算总消耗的周期
  109.                         TH1=0;
  110.                         TL1=0;               
  111.                         if (iCycle <= iMIN_LEN)
  112.                         {
  113.                                 mcDistanceErr = 1;//距离太近
  114.                                 /*距离超近:重启延迟时间 >10ms,保证上一个声波回波已经消失
  115.                             *T0计数器重装值mbDelay10H, mbDelay10L,在
  116.                                 *InitUltrasonicDistance()初始化函数中生成*/
  117.                                 miDistance = 2;
  118.                                 mbDelayOverFlg = 0; //复位延迟标志
  119.                                 TH1 = mbDelay10H; //重装计数器高8位
  120.                                 TL1 = mbDelay10L; //重装计数器低8位
  121.                                 TR1 = 1; //启动延迟计数器
  122.                         }
  123.                         else
  124.                         {
  125.                                 //(iCycle * 1.0851 * 0.17 / 10) => iCycle * 0.01844670
  126.                                 miDistance = (unsigned int)(iCycle * 184467 / 10000000);//(单位cm)
  127.                                 mcDistanceErr = 0;//测距正常值
  128.                                 /*一次测距完成需要延迟>60ms的时间,保证上一个声波回波已经消失
  129.                                 * 这儿使用16位计数器的整个空间,> 65.535ms        */
  130.                                 mbDelayOverFlg = 0; //复位延迟标志
  131.                                 TH1 = 0; //T0,高位归0复位
  132.                                 TL1 = 0; //T0,低位归0复位
  133.                                 TR1 = 1;//打开T0延迟计数器(此时不测距,所以不影响测距的计算)
  134.                         }
  135.                 }
  136.                 else
  137.                 {
  138.                     mcDistanceErr = 2; //超量程
  139.                         miDistance = 400;
  140.                 }         
  141.                 return 0; //完成测距操作
  142.         }
  143.         else //正在延迟等待下次测距的开始
  144.         return 1;
  145. }
  146. /*************** ^超声波模块*****************************************************************************/

  147. //************数码管显示
  148. void display(unsigned long sec)
  149. {
  150.     buf[0] = sec%10;
  151.     buf[1] = sec/10%10;
  152.     buf[2] = sec/100%10;
  153.     //从最高为开始,遇到0不显示,遇到非0退出循环
  154.     for (j=2; j>=1; j--)
  155.     {
  156.          if (buf[j] == 0)
  157.          LedBuff[j] = 0xFF;
  158.          else
  159.          break;
  160.     }
  161.     //将剩余的有效数字位如实转换
  162.     for ( ; j>=0; j--)  //for()起始未对j操作,j即保持上个循环结束时的值
  163.     {
  164.          LedBuff[j] = LedChar[buf[j]];
  165.     }
  166. }

  167. void main(void)
  168. {
  169.         unsigned int delay_10ms;

  170.         ADDR3 = 1;
  171.         ENLED = 0;

  172.     TMOD |= 0x01;         
  173.         TH0  = 0xFC;  //为T0赋初值0xFC67,定时1ms
  174.     TL0  = 0x67;
  175.     ET0  = 1;     //使能T0中断
  176.     TR0  = 1;     //启动T0

  177.     TMOD |= 0x10;
  178.         TH1=0; //高位置0
  179.         TL1=0; //低位置0
  180.         TR1=0; //开始前先关闭计数器
  181.         ET1=1; //允许T0中断

  182.     EA = 1;

  183.         delay_10ms = (unsigned int)(65536-110592/12); //10ms的延迟提前计算
  184.         mbDelay10H = delay_10ms >> 8; //高8位值
  185.         mbDelay10L = delay_10ms &0x0F; //低8位值

  186.         while(1)
  187.         {
  188.                 //当调用测距函数后,返回为0,表示测距成功,否则测距函数正在延迟中
  189.                 if (0 == refreshDistance())
  190.                 {
  191.                         //当取值有效时,如果与前次值没变化,则不作更新
  192.                         if (0 == getDistanceState() && (distance != getDistance()))
  193.                         {
  194.                                 distance = getDistance();
  195.                                 display(distance);
  196.                         }
  197.                 }
  198.         }
  199. }

  200. /* 定时器0中断服务函数 */
  201. void InterruptTimer0() interrupt 1
  202. {
  203.         TH0 = 0xFC;  //重新加载初值
  204.     TL0 = 0x67;
  205.     P0 = 0xFF;   //显示消隐
  206.     switch (i)
  207.     {
  208.         case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
  209.         case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
  210.         case 2: ADDR2=0; ADDR1=1; ADDR0=0; i=0; P0=LedBuff[2]; break;
  211.         default: break;
  212.     }
  213. }
复制代码


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

使用道具 举报

沙发
ID:123289 发表于 2018-8-5 10:19 | 只看该作者
你把程序整理成逻辑框图就明白了、
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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