找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3261|回复: 5
收起左侧

超声波测距模块和语音模块同时使用,但是2个单片机定时器问题解决不了,求大神指教

[复制链接]
ID:291819 发表于 2018-9-19 21:34 | 显示全部楼层 |阅读模式
  1. #include <REG52.h>       //调用51单片机的头文件
  2. #include <intrins.h>
  3. #include <math.h>
  4. #include <string.h>
  5. //---------------------------------------
  6. //1602液晶相关I/O设置
  7. sbit E=P0^5;               //1602液晶的E脚接在P2.3口上
  8. sbit RW=P0^6;              //1602液晶的RW脚接在P2.4口上
  9. sbit RS=P0^7;              //1602液晶的RS脚接在P2.5口上
  10. //---------------------------------------
  11. //---------------------------------------
  12. //HC-SR04相关I/O设置
  13. sbit TIRG=P3^4;                   //定义IO口,具体可以去查看原理图
  14. sbit ECHO=P3^2;                   //定义IO口,具体可以去查看原理图        
  15. //---------------------------------------
  16. sbit mang= P0^7;
  17. unsigned long BJS=50;//报警距离50CM
  18. //unsigned char disbuff[4]           ={0,0,0,0};
  19. //unsigned char disbuff_BJ[4]        ={0,0,0,0};//报警信息
  20. unsigned int  time=0;
  21. bit      flag =0;
  22. unsigned char k;
  23. //名称:1602液晶用延时函数
  24. void Delay1602(unsigned int t)
  25. {
  26.      unsigned int k;      //定义一个16位寄存器用来做延时用
  27.      for(k=0;k<t;k++);    //延时
  28. }

  29. //名称:1602液晶忙检测函数
  30. void LCD1602_busy(void)
  31. {
  32.      mang=1;              //将P0.7置1,为读状态做准备
  33.      RS=0;                //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
  34.      RW=1;                //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
  35.      E=1;                 //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
  36.      while(mang==1);      //由P0.7读入1,表示1602液晶忙,需要等待
  37.      E=0;                 //读完以后,恢复E的电平
  38. }

  39. //名称:1600写命令函数
  40. void LCD1602_Write_com(unsigned char combuf)
  41. {
  42.      RS=0;                //选择指令寄存器
  43.      RW=0;                //选择写状态
  44.      P2=combuf;           //将命令字通过P0口送至DB
  45.      E=1;                 //E高电平将命令字写入1602液晶
  46.      E=0;                 //写完以后,恢复E的电平
  47. }

  48. //名称:1602写命令函数(带忙检测)
  49. void LCD1602_Write_com_busy(unsigned char combuf)
  50. {
  51.      LCD1602_busy();            //调用忙检测函数
  52.      LCD1602_Write_com(combuf); //调用忙检测函数
  53. }

  54. //名称:1602写数据函数(带忙检测)
  55. void LCD1602_Write_data_busy(unsigned char databuf)
  56. {
  57.      LCD1602_busy();      //调用忙检测函数
  58.      RS=1;                //选择数据寄存器
  59.      RW=0;                //选择写状态
  60.      P2=databuf;          //将命令字通过P0口送至DB
  61.      E=1;                 //E高电平将命令字写入1602液晶
  62.      E=0;                 //写完以后,恢复E的电平
  63. }

  64. //名称:1602液晶显示地址写函数
  65. void LCD1602_Write_address(unsigned char x,unsigned char y)
  66. {
  67.      x&=0x0f;             //列地址限制在0-15间
  68.      y&=0x01;             //行地址限制在0-1间
  69.      if(y==0)             //如果是第一行
  70.          LCD1602_Write_com_busy(x|0x80);        //将列地址写入
  71.      else                 //如果是第二行
  72.          LCD1602_Write_com_busy((x+0x40)|0x80); //将列地址写入
  73. }


  74. //名称:1602液晶初始化函数
  75. void LCD1602_init(void)
  76. {
  77.      Delay1602(1500);               //调用延时函数
  78.      LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
  79.      Delay1602(500);                //调用延时函数
  80.      LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
  81.      Delay1602(500);                //调用延时函数
  82.      LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
  83.      LCD1602_Write_com_busy(0x38);  //8位数据总线,两行显示模式,5*7点阵显示
  84.      LCD1602_Write_com_busy(0x08);  //显示功能关,无光标
  85.      LCD1602_Write_com_busy(0x01);  //清屏
  86.      LCD1602_Write_com_busy(0x06);  //写入新的数据后,光标右移,显示屏不移动
  87.      LCD1602_Write_com_busy(0x0C);  //显示功能开,无光标
  88. }
  89. void chuankou()
  90. {
  91.           //    串口的初始化
  92.          TL1 = 0xFA;        // 在11.0592MHz 下,设置波特率9600bps,工作方式2
  93.          TH1 = 0xFA;              
  94.         TMOD|=0x21;
  95.                 TMOD = 0x21;
  96.                SCON = 0x50;       // 串口工作方式1,允许接收
  97.          PCON = 0x80;
  98.          EA  = 0;
  99.          REN = 1;
  100.          TI = 0;            //发送中断标志位置零
  101.          RI = 0;            //接收中断标志位置零
  102.          TR1 = 1;           //定时器1 用作波特率发生

  103. }


  104. //名称:1602液晶指定地址显示函数
  105. void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
  106. {
  107.      LCD1602_Write_address(x,y);    //先将地址信息写入
  108.      LCD1602_Write_data_busy(buf);  //再写入要显示的数据
  109. }

  110. //名称:定时器0中断服务程序
  111. void Timer0(void) interrupt 1
  112. {                       
  113.    //
  114.         flag=0;
  115.                  
  116.    //******************************************
  117. }

  118. void yuyin()
  119. {
  120.          //需要发送的文本
  121.                  char code text[] =  {"观看时间太长了!"};
  122.                  unsigned  char  headOfFrame[5];
  123.          unsigned  char  length;  
  124.                  unsigned  char  ecc  = 0;                          //定义校验字节
  125.              unsigned  int i=0;
  126.                  length =sizeof(text);                         //需要发送文本的长度
  127.                  chuankou();
  128.         //发送过程/           
  129.                  headOfFrame[0] = 0xFD ;                         //构造帧头FD
  130.                  headOfFrame[1] = 0x00 ;                         //构造数据区长度的高字节
  131.                  headOfFrame[2] = length + 3;                 //构造数据区长度的低字节
  132.                  headOfFrame[3] = 0x01 ;                         //构造命令字:合成播放命令
  133.        //带背景音乐                  
  134.             // headOfFrame[4] = 0x21 ;                         //构造命令参数:编码格式为GBK

  135.       //不带背景音乐                  
  136.                 headOfFrame[4] = 0x01 ;                         //构造命令参数:编码格式为GBK

  137.                  for(i = 0; i<5; i++)                                   //依次发送构造好的5个帧头字节
  138.              {  
  139.                  ecc=ecc^(headOfFrame[i]);                 //对发送的字节进行异或校验        
  140.                  SBUF = headOfFrame[i];
  141.                  while (TI== 0) {;}                           //等待发送中断标志位置位
  142.                  TI = 0;                                                 //发送中断标志位清零
  143.              }

  144.                     for(i = 0; i<length; i++)                   //依次发送待合成的文本数据
  145.              {  
  146.                  ecc=ecc^(text[i]);                                 //对发送的字节进行异或校验        
  147.                  SBUF = text[i];
  148.                  while (TI== 0) {;}
  149.                  TI = 0;                                 
  150.              }
  151.                    SBUF=ecc;                                                        //最后发送校验字节
  152.                    while (TI== 0) {;}
  153.                 TI=0;         
  154.                   while(1);
  155. }

  156. void main(void)            //主函数,单片机开机后就是从这个函数开始运行
  157. {
  158.         long S;
  159.         unsigned int i;
  160.         unsigned int  Timeout;
  161.     LCD1602_init();        //调用1602液晶初始化函数
  162.         //***定时器Timer0初始化***
  163.    TMOD&=0xF0;                    //将TMOD的低4位定时器0控制部分清零
  164.    TMOD|=0x01;                    //设置定时器0为方式1
  165.    TMOD=0x01;
  166.    TL0=0;                              //设置定时器0初值低8位
  167.    TH0=0;                              //设置定时器0初值高8位
  168.    TR0=0;                         //停止定时器0
  169.    ET0=1;                         //Timer0中断允许
  170.    //**********************
  171.    //***开全局中断设置****
  172.    //定时器Timer0设置了中断允许,此处要开全局中断
  173.    EA=1;                          //开全局中断
  174.   // ES=1;
  175.    //*********************
  176.         while(1)
  177.         {               
  178.                 TIRG=1;                                             //发一个脉冲触发信号
  179.                   i=4;                                             //维持约17US,符合不低于10US的要求
  180.       while(i>0)                                  //维持约17US,符合不低于10US的要求
  181.               i--;                                     //维持约17US,符合不低于10US的要求               
  182.                   TIRG=0;                                             //撤销触发信号
  183.                 TR0=0;                                                //关闭定时器
  184.                 TL0=0;                             //设置定时器0初值低8位为0
  185.              TH0=0;                              //设置定时器0初值高8位为0
  186.                 k=0;                         //清除溢出标志
  187.                 flag=0;
  188.                 Timeout=0;
  189.            while((ECHO==0)&&((Timeout++)<50000));                                //等待回响高电平               
  190.            TR0=1;                                            //回响高电平来后启动定时器
  191.                 Timeout=0;
  192.            while((ECHO==1)&&((Timeout++)<50000));                                //等待回响高电平结束后
  193.            TR0=0;                                                //关闭定时器
  194.       S=((TH0*256+TL0)*1.7)/100;
  195.           if(S<=50)
  196.           {
  197.                  yuyin();
  198.           }        
  199.                 if(flag==1||S>400)                //超出测量范围显示“-”
  200.                 {                                                         
  201.                            LCD1602_Disp(0, 0, '-');                                  //显示百位-
  202.                            LCD1602_Disp(1, 0, '-');                                  //显示十位-
  203.                            LCD1602_Disp(2, 0, '-');                                  //显示个位-
  204.                            LCD1602_Disp(3, 0, 'C');                                  //显示C
  205.                            LCD1602_Disp(4, 0, 'M');                                //显示M
  206.                 }
  207.                 else                                                                  
  208.                 {         
  209.                         if(S<=50){
  210.                         //yuyin();               
  211.                         LCD1602_Disp(0, 0, S%1000/100+'0');                  //显示百位
  212.                            LCD1602_Disp(1, 0, S%1000%100/10+'0');  //显示十位
  213.                            LCD1602_Disp(2, 0, S%1000%100%10+'0');        //显示个位
  214.                            LCD1602_Disp(3, 0, 'C');                                          //显示C
  215.                            LCD1602_Disp(4, 0, 'M');                                        //显示M
  216.                     
  217.                         }
  218.                 }
  219.                 i=18000;                                          //维持约77400US,符合不低于60MS的要求
  220.       while(i>0)                                  //维持约77400US,符合不低于60MS的要求
  221.               i--;                                     //维持约77400US,符合不低于60MS的要求

  222.         }
  223. }

复制代码
回复

使用道具 举报

ID:291819 发表于 2018-9-19 21:37 | 显示全部楼层
超声波测距功能与语音模块单独分开都能实现功能,放在一起就什么功能不能实现,我知道用到了俩个定时器,但就是这俩个定时器程序不太会
回复

使用道具 举报

ID:303383 发表于 2018-9-20 09:18 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

ID:387733 发表于 2018-9-20 17:21 | 显示全部楼层
函数“chuankou()”中 EA=0; 把全局中断关闭了,这样调用一次以后,就不会再有中断了,这里没必要关闭全局中断的。
把 EA=0;去掉应该就可以了。
回复

使用道具 举报

ID:291819 发表于 2018-9-27 16:19 | 显示全部楼层
sxhwdz 发表于 2018-9-20 17:21
函数“chuankou()”中 EA=0; 把全局中断关闭了,这样调用一次以后,就不会再有中断了,这里没必要关闭全 ...

把EA=0去掉也不行
回复

使用道具 举报

ID:291819 发表于 2018-9-27 16:20 | 显示全部楼层
小猫猫爱吃鱼 发表于 2018-9-20 09:18
你好!两次定时器的使用出现了冲突,要重新写一部分程序了。。。

是不是需要写这俩个定时器的中断优先级程序
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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