找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC89C52单片机超声波测距与蓝牙 定时器的复用导致的问题吗?

[复制链接]
ID:1029098 发表于 2023-5-18 15:40 | 显示全部楼层 |阅读模式
我在设计过程中遇到了问题,超声波测距模块和蓝牙分别可以单独正常运行,但是把他们放在一起超声波就接收不到信号,不能完成测距,我个人认为是定时器的复用导致问题,但是由于了解不足,不知道如何解决这个问题,还请大神帮我看看。

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <1602.h>
  3. #include <intrins.h>
  4. #include <math.h>
  5. #include <stdlib.h>
  6. #include <string.h>

  7. #define VELOCITY_26C        3485       //26摄氏度时的声速,声速V= 331.5 + 0.607*温度;  
  8. #define uchar unsigned char
  9. #define uint unsigned int

  10. sbit INPUT  = P1^0;                //回声接收端口
  11. sbit OUTPUT = P1^1;                //超声触发端口
  12. sbit beep   = P2^3 ;                                 // 蜂鸣器
  13. sbit ds = P2^2;
  14. sbit RS = P3^5;   
  15. sbit LCDEN = P3^4;

  16. long int distance=0;             //距离变量
  17. long int thickness=0;

  18. char pass[3];       // 传递数据位
  19. uchar table[]="thk  : ";
  20. uchar table0[]="temp:  ";
  21. uchar count;

  22. extern void initLCD();
  23. extern void write_date(uchar date);
  24. extern void write_com(uchar com);
  25. extern void delay(uint x);

  26. //LCD1602
  27. void _nop_(void);

  28. void delayUs()
  29. {
  30.     _nop_();
  31. }

  32. void delayMs(uint a)
  33. {
  34.     uint i, j;
  35.     for(i = a; i > 0; i--)
  36.         for(j = 100; j > 0; j--);
  37. }

  38. void writeData(uchar dat)
  39. {
  40.     RS = 1;
  41.     P0 = dat;
  42.     LCDEN = 1;
  43.     delayUs();
  44.     LCDEN = 0;
  45.     delayMs(1);
  46. }

  47. void writeComm(uchar comm)
  48. {
  49.     RS = 0;   
  50.     P0 = comm;
  51.     LCDEN = 1;
  52.     delayUs();
  53.     LCDEN = 0;
  54.     delayMs(1);
  55. }

  56. void writeString(uchar * str, uchar length)
  57. {
  58.      uchar i;
  59.     for(i = 0; i < length; i++)
  60.     {
  61.          writeData(str[i]);
  62.      }
  63. }
  64. //HC-05
  65. void UART_Init()
  66. {
  67.     TMOD = 0x20;
  68.     TH1 = 0xfd;
  69.     TL1 = 0xfd;  // 波特率9600
  70.     SM0 = 0;
  71.     SM1 = 1;   // 串口工作方式1 10位异步
  72.     REN = 1;  // 串口允许接收
  73.     TR1 = 1;
  74.     EA = 1;
  75.     ES = 1;  // 启用串口中断
  76. }

  77. // 发送单个字符函数
  78. void UART_SendChar(char ch)
  79. {
  80.     SBUF = ch;
  81.     while (!TI);  // 等待发送完成
  82.     TI = 0;  // 清除发送中断标志
  83. }

  84. // 发送字符串函数
  85. void UART_SendString(char* str)
  86. {
  87.     while (*str != '\0')
  88.     {
  89.         UART_SendChar(*str);
  90.         str++;
  91.     }
  92. }

  93. //DS18B20
  94. void dsInit()
  95. {
  96.    
  97.     unsigned int i;  
  98.     ds = 0;
  99.     i = 100;  
  100.      while(i>0) i--;
  101.     ds = 1;   
  102.     i = 4;
  103.      while(i>0) i--;
  104. }

  105. void dsWait()
  106. {
  107.       unsigned int i;
  108.       while(ds);  
  109.       while(~ds);
  110.       i = 4;
  111.       while(i > 0) i--;
  112. }

  113. bit readBit()
  114. {
  115.     unsigned int i;
  116.     bit b;
  117.     ds = 0;
  118.     i++;   
  119.     ds = 1;
  120.    i++; i++;  
  121.     b = ds;
  122.     i = 8;
  123.     while(i>0) i--;
  124.     return b;
  125. }

  126. unsigned char readByte()
  127. {
  128.     unsigned int i;
  129.     unsigned char j, dat;
  130.    dat = 0;
  131.     for(i=0; i<8; i++)
  132.     {
  133.         j = readBit();
  134.       
  135.         dat = (j << 7) | (dat >> 1);
  136.     }
  137.     return dat;
  138. }

  139. void writeByte(unsigned char dat)
  140. {
  141.     unsigned int i;
  142.     unsigned char j;
  143.     bit b;
  144.     for(j = 0; j < 8; j++)
  145.     {
  146.         b = dat & 0x01;
  147.         dat >>= 1;
  148.    
  149.         if(b)   
  150.         {
  151.            ds = 0;          i++; i++;  
  152.             ds = 1;   
  153.             i = 8; while(i>0) i--;  
  154.         }
  155.         else  
  156.         {
  157.             ds = 0;
  158.           i = 8; while(i>0) i--;  
  159.             ds = 1;
  160.            i++; i++;
  161.         }
  162.    }
  163. }

  164. void sendChangeCmd()
  165. {
  166.     dsInit();   
  167.     dsWait();   
  168.     delayMs(1);   
  169.     writeByte(0xcc);
  170.     writeByte(0x44);
  171. }

  172. void sendReadCmd()
  173. {
  174.     dsInit();
  175.     dsWait();
  176.     delayMs(1);
  177.     writeByte(0xcc);
  178.     writeByte(0xbe);
  179. }

  180. int getTmpValue()
  181. {
  182.     unsigned int tmpvalue;
  183.     int value;
  184.     float t;
  185.     unsigned char low, high;
  186.     sendReadCmd();
  187.    
  188.     low = readByte();
  189.     high = readByte();
  190.    
  191.     tmpvalue = high;
  192.     tmpvalue <<= 8;
  193.     tmpvalue |= low;
  194.     value = tmpvalue;
  195.   
  196.     t = value * 0.0625;
  197.    
  198.     value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
  199.     return value;
  200. }

  201. void display_tmp(int v)
  202. {
  203.     unsigned char count;
  204.     unsigned char datas[] = {0, 0, 0, 0, 0};
  205.     unsigned int tmp = abs(v);
  206.     datas[0] = tmp / 10000;
  207.     datas[1] = tmp % 10000 / 1000;
  208.     datas[2] = tmp % 1000 / 100;
  209.     datas[3] = tmp % 100 / 10;
  210.     datas[4] = tmp % 10;
  211.     writeComm(0xc0+6);
  212.     if(v < 0)
  213.     {
  214.         writeString("- ", 2);
  215.    }
  216.     else
  217.     {
  218.        writeString("+ ", 2);
  219.     }
  220.     if(datas[0] != 0)
  221.     {
  222.         writeData('0'+datas[0]);
  223.     }
  224.     for(count = 1; count != 5; count++)
  225.     {
  226.         writeData('0'+datas[count]);
  227.         if(count == 2)
  228.         {
  229.             writeData('.');
  230.         }
  231.     }
  232. }

  233. //HC-SR04
  234. void delayt(uint x)
  235. {
  236.     uchar j;
  237.     while(x-- > 0)
  238.     {
  239.               for(j = 0;j < 125;j++)
  240.         {
  241.             ;
  242.         }
  243.     }
  244. }

  245. void Init_MCU(void)//初始化单片机函数
  246. {
  247.         TMOD = 0x01;
  248.          TL0 = 0x66;
  249.         TH0 = 0xfc;              //1ms
  250.   ET0 = 1;              //开定时器2
  251.         EA = 1;                      //总中断使能
  252. }

  253. void Init_Parameter(void)
  254. {
  255.          OUTPUT =1;
  256.          INPUT = 1;
  257.          count = 0;
  258.          distance = 0;
  259. }

  260. void display_char(uchar *point,uchar address)//显示字符串
  261. {
  262.         uchar i;
  263.         write_com(0x80 + address);
  264.         for(i = 0;i < 16; i++)
  265.         {
  266.                 write_date(*point);
  267.                 point++;
  268.         }
  269. }

  270. void display_dis(int number,uchar address)//显示距离
  271. {
  272.         uchar b,c,d,e;
  273.         b= (number / 1000);
  274.         c= (number / 100) % 10;
  275.         d = (number / 10) % 10;
  276.         e = number % 10;

  277.         write_com(0x80 + address);
  278.   write_date(b + 48);
  279.         write_date(c + 48);
  280.         write_date(d + 48);
  281.         write_date(46);           //小数点的ASCII
  282.         write_date(e + 48);
  283.   write_date(99);           //"c"的ASCII
  284.         write_date(109);          //"m"的ASCII
  285.         write_date(32);  write_date(32);  //空格的ASCII
  286. }

  287. void Trig_SuperSonic(void)//出发声波
  288. {
  289.          OUTPUT = 1;
  290.          delayt(1);
  291.          OUTPUT = 0;
  292. }

  293. void Measure_Distance(void)//计算距离函数
  294. {
  295.         uchar l;
  296.         uint h,y;
  297.         TR0 = 1;
  298.         while(INPUT)
  299.     {
  300.         ;
  301.     }        
  302.         TR0 = 0;
  303.         l = TL0;
  304.         h = TH0;
  305.         y = (h << 8) + l;//回声信号时间差
  306.         y = y - 0xfc66;//单位是us
  307.         distance = y + 1000 * count;//计算总时间
  308.         TL0 = 0x66;
  309.         TH0 = 0xfc;
  310.         delayt(30);
  311.         distance = VELOCITY_26C * distance / 20000;
  312.         thickness=210-distance;
  313.         
  314. }

  315. void main(void)
  316. {
  317.         
  318.         initLCD();
  319.         Init_MCU();
  320.         Init_Parameter();
  321.         sendChangeCmd();
  322. //        UART_Init();  // 波特率9600
  323.         
  324.   writeComm(0xc0);
  325.   writeString(table0, 8);
  326.         display_char(table,0x00);
  327.         beep=1;

  328.   while(1)
  329.     {
  330.                           ES=0;
  331.         delayMs(1000); //温度转换时间需要750ms以上
  332.         writeComm(0xc0);
  333.         display_tmp(getTmpValue());
  334.         sendChangeCmd();
  335.                         
  336.                           Trig_SuperSonic();         //触发超声波发射
  337.                     while(INPUT == 0)          //等待回声
  338.          {
  339.              ;
  340.          }
  341.                      Measure_Distance();        //计算脉宽并转换为距离
  342.                                  display_dis(thickness,0x07);    //显示厚度
  343.                                  
  344. //                                 if(thickness>=100)
  345. //                                 {
  346. //                                         ES=1;TR0=0;
  347. //                                         UART_SendString("The thickness exceeds the warning value!");
  348. //                                         ES=0;
  349. //                                         beep=0;
  350. //                            }
  351.               Init_Parameter();          // 参数重新初始化
  352.                     delayt(100);
  353.     }

  354. }

  355. void timer0 (void) interrupt 1   //T0中断处理函数
  356. {
  357.         TF0 = 0;
  358.         TL0 = 0x66;
  359.         TH0 = 0xfc;
  360.         count++;
  361.         if(count == 18)//超声波回声脉宽最多18ms
  362.         {
  363.                 TR0 =0;
  364.                 TL0 = 0x66;
  365.                 TH0 = 0xfc;
  366.                 count = 0;
  367.         }
  368. }

  369. void UART_INTERRUPT() interrupt 4
  370. {
  371.     static int i = 0;  // 静态局部变量,被初始化一次
  372.     if (RI) {  // 中断处理函数中,对于接收中断的响应
  373.         RI = 0;  // 清除接收中断标志位
  374.         pass[i] = SBUF;
  375.         i++;
  376.         if (i == 2) {
  377.             pass[i] = '\0';  // 添加字符串结束符
  378.             i = 0;
  379.         }
  380.     }
  381.     if (TI);  // 处理发送中断
  382. }注释部分是蓝牙
复制代码

回复

使用道具 举报

ID:123289 发表于 2023-5-19 09:00 | 显示全部楼层
想想看当你让CPU做DELAY时,超声波测距与蓝牙在干什么?它们这期间能好好地干活吗?
回复

使用道具 举报

ID:161164 发表于 2023-5-19 10:15 | 显示全部楼层
78行 TMOD = 0x20; 改为 TMOD |= 0x20;
271行 TMOD = 0x01; 改为 TMOD |= 0x01;
回复

使用道具 举报

ID:1029098 发表于 2023-5-19 23:59 | 显示全部楼层
yzwzfyz 发表于 2023-5-19 09:00
想想看当你让CPU做DELAY时,超声波测距与蓝牙在干什么?它们这期间能好好地干活吗?

我没有听懂,可以再指导我一下吗
回复

使用道具 举报

ID:123289 发表于 2023-5-20 08:08 | 显示全部楼层
随着你的进步,会懂的。布置一个作业:
禁用DELAY()函数,这个东东最害人。它是初学者最喜欢用,而对多功能妨害最多的函数。
提示:延时用定时器中断做。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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