找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机循迹过程中怎么实现无干扰超声波避障?

[复制链接]
跳转到指定楼层
楼主
ID:465205 发表于 2019-4-21 15:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
100黑币
  1. StartModule();        //启动模块测距
  2.                  while(!RX);                //当RX(ECHO信号回响)为零时等待
  3.                  TR1=1;                            //开启计数
  4.                  while(RX);                        //当RX为1计数并等待
  5.                  TR1=0;                                //关闭计数
  6.              Dist();                        //计算距离
复制代码
  1. void zd0() interrupt 1        //T0中断用来计数器溢出,超过测距范围
  2. {
  3.         
  4.         flag=1;        
  5.                                                          //中断溢出标志                        
  6. }
复制代码

上面是一段普通的超声波避障代码,可以实现基本避障,但是我需要在巡线过程中用超声波识别碍物并作出动作,小车的pwm用的T0,定时1ms,如果都在T0里面中断,超声波发送接收信号会使T0开关,然后pwm就会乱,怎么才能在一个定时器里面同时做超声波中断和pwm中断,或者说怎么在T0不单独清零时,计算出超声波发送和接受信号的时间。用上面代码放在循迹代码以前,只用超声波计算距离不执行其他动作,小车具体表现为:摇晃幅度较大,很容易就偏离轨迹,偶尔也可以循迹但是成功率特别低。            
  1. StartModule();        //启动模块测距
  2.                  while(!RX);                //当RX(ECHO信号回响)为零时等待
  3.                  l=0;
  4.                  l=(TH0<<8)|TL0;                            //记录为0的时间
  5.                  while(RX);                        //当RX为1计数并等待
  6.                  l=T*1000+l-((TH0<<8)|TL0);                //计算时间
  7.                   S=l*0.17;                  
  8.                   delay(60);
复制代码
  1. void zd0() interrupt 1        //T1中断用来计数器溢出,超过测距范围
  2. {
  3.         
  4.         flag=1;           //中断溢出标志
  5.         T++;
  6. }
复制代码



上面是朋友给我想的计算时间的办法,思路是这样:每执行一次中断,使T累加。启动超声波模块记录Rx为0时的时间,然后记录Rx为1的时间,算出时间差,再加上中断的时间,算出总时间,最后算距离。用这个代码在串口S的返回值为0,s放大100倍后,出现不稳定的正负巨大值。根本无法实现超声波测距功能,请问这个代码思路对不对,该怎么完善?或者有没有其他方式解决这个问题?
附上完整代码,感谢各位大神帮助
  1. #include<AT89X52.H>                  //包含51单片机头文件,内部有各种寄存器定义
  2. #include<8testpwm.h>                  //包含pwm等函数
  3.   /*超声波避障*/
  4. long int l;           //时间
  5. void Avoid(void)
  6. {
  7. //这段代码无法实现测距
  8.               StartModule();        //启动模块测距
  9.                  while(!RX);                //当RX(ECHO信号回响)为零时等待
  10.                  l=0;
  11.                  l=(TH0<<8)|TL0;                            //
  12.                  while(RX);                        //当RX为1计数并等待
  13.                  l=T*1000+l-((TH0<<8)|TL0);                //
  14.                   S=l*0.17;                  
  15.                   delay(60);

  16. //注解代码能正常测距,但在巡线过程测距干扰巡线
  17.         /*         StartModule();        //启动模块测距
  18.                  while(!RX);                //当RX(ECHO信号回响)为零时等待
  19.                  TR1=1;                            //开启计数
  20.                  while(RX);                        //当RX为1计数并等待
  21.                  TR1=0;                                //关闭计数
  22.              Dist();                        //计算距离         */
  23.                  
  24.                  
  25. }

  26.         void Go_line()
  27. {
  28.         if(Led_1==1&&Led_3==1)
  29.         {
  30.                 line='L';
  31.         }
  32.         else if(Led_6&&Led_8==1)
  33.         {
  34.                 line='R';
  35.         }
  36.         else if(Led_1==1)
  37.         {
  38.                 line='1';
  39.         }
  40.         else if(Led_2==1)
  41.         {
  42.                 line='2';
  43.         }
  44.         else if(Led_3==1)
  45.         {
  46.                 line='3';
  47.         }
  48.         else if(Led_4==1)
  49.         {
  50.                 line='4';
  51.         }
  52.         else if(Led_5==1)
  53.         {
  54.                 line='5';
  55.         }
  56.         else if(Led_6==1)
  57.         {
  58.                 line='6';
  59.         }
  60.         else if(Led_7==1)
  61.         {
  62.                 line='7';
  63.         }
  64.         else if(Led_8==1)
  65.         {
  66.                 line='8';
  67.         }


  68. }
  69. /**************************巡线函数**********************************************/
  70. void Go()
  71. {

  72.         switch(line)
  73.         {
  74.                 case 'L':
  75.                 {
  76.                         
  77.                         counter();
  78.                         if(Count==3||Count==4||Count==7||Count==18||Count==20||Count==21)
  79.                         {        stop();
  80.                                 leftrun();
  81.                                 stop();
  82.                                 
  83.                                 
  84.                         }
  85.                         else if(Count==9||Count==14)
  86.                         {
  87.                                 run();
  88.                         
  89.                         }
  90.                         else if(Count==12||Count==17)
  91.                         {        stop();
  92.                                 rightrun();
  93.                                 stop();
  94.                         
  95.                                 
  96.                         }
  97.                         else if(Count==2||Count==5||Count==10||Count==13||Count==15)
  98.                         {        stop();
  99.                                 Return();
  100.                                 stop();        
  101.                         }
  102.                         else if(Count==22)
  103.                         {
  104.                                 stop();
  105.                         }
  106.                 }; break;

  107.                 case 'R':
  108.                 {
  109.                         counter();
  110.                         if(Count==8||Count==11||Count==12||Count==16||Count==17||Count==19)
  111.                         {
  112.                                 stop();
  113.                                 rightrun();
  114.                                 stop();
  115.                         
  116.                                 
  117.                         }
  118.                         else if(Count<2||Count==6)
  119.                         {
  120.                                 run();
  121.                                 
  122.                         }
  123.                         else if(Count==4||Count==21)
  124.                         {
  125.                                 stop();
  126.                                 leftrun();
  127.                                 stop();
  128.                         
  129.                                 
  130.                         }
  131.                         else if(Count==2||Count==5||Count==10||Count==13||Count==15)
  132.                         {
  133.                                 stop();
  134.                                 Return();
  135.                                 stop();
  136.                         
  137.                         }
  138.                         else if(Count==22)
  139.                         {
  140.                                 stop();
  141.                         }               
  142.                 };break;                  

  143.                 case '1':
  144.                 {
  145.                         leftp_3();
  146.                 }; break;
  147.                 case '2':
  148.                 {
  149.                         leftp_2();
  150.                 }; break;
  151.                 case '3':
  152.                 {
  153.                         leftp_1();
  154.                 }; break;
  155.                 case '4':
  156.                 {
  157.                         run();
  158.                 }; break;
  159.                 case '5':
  160.                 {
  161.                         run();
  162.                 }; break;
  163.                 case '6':
  164.                 {
  165.                         rightp_1();
  166.                 }; break;
  167.                 case '7':
  168.                 {
  169.                         rightp_2();
  170.                 }; break;
  171.                 case '8':
  172.                 {
  173.                         rightp_3();
  174.                 }; break;
  175.         
  176.         }

  177. }
  178. /**************************巡线函数**********************************************/

  179. //主函数
  180.         void main(void)
  181. {        
  182.                            P1=0X00;   //关电机        
  183.                         TMOD |= 0x01;//定时器0工作模块1,16位定时模式,测量PWM波
  184.                         TH0= 0XFc;                  //1ms定时
  185.                  TL0= 0X18;
  186.                    TR0= 1;
  187.                 ET0= 1;
  188.                         SCON=0x50;
  189.                 EA = 1;                           //开总中断
  190.                         TI=1;
  191.                         Count=0;
  192.                         push_val_left=0;
  193.                         push_val_right=0;
  194.         while(1)        //无限循环
  195.         {
  196.          
  197.                  //有信号为0  没有信号为1

  198.            Avoid();
  199.            Go_line();
  200.            Go();
  201.            delay(50);         
  202.         }

  203. }

  204. #include <intrins.h>   //包含nop等系统函数
  205. #ifndef _LED_H_
  206. #define _LED_H_


  207.     //定义小车驱动模块输入IO口
  208.    sbit L293D_IN1=P1^2;
  209.    sbit L293D_IN2=P1^3;
  210.    sbit L293D_IN3=P1^4;
  211.    sbit L293D_IN4=P1^5;
  212.    sbit L293D_EN1=P1^6;
  213.    sbit L293D_EN2=P1^7;
  214.         


  215.          #define  TX    P3_3
  216.         #define  RX    P3_2
  217.     #define ShowPort   P0          //数码管显示端口
  218. /****************定义传感器端口********************/
  219.         #define Led_1               P2_7         
  220.         #define Led_2                   P2_6         
  221.         #define Led_3                   P2_5         
  222.         #define Led_4                   P2_4         
  223.         #define Led_5          P2_3           
  224.         #define Led_6          P2_2           
  225.     #define Led_7          P2_1            
  226.            #define Led_8          P2_0         
  227.          
  228.    
  229.         #define Left_moto_pwm          P1_6         //PWM信号端

  230.         #define Right_moto_pwm          P1_7         //PWM信号端
  231.         
  232.         #define Left_moto_go      {P1_2=1,P1_3=0;}  //左电机向前走
  233.         #define Left_moto_back    {P1_2=0,P1_3=1;}         //左边电机向后转
  234.         #define Left_moto_Stop    {P1_2=0,P1_3=0;}  //左边电机停转                     
  235.         #define Right_moto_go     {P1_4=1,P1_5=0;}        //右边电机向前走
  236.         #define Right_moto_back   {P1_4=0,P1_5=1;}        //右边电机向后走
  237.         #define Right_moto_Stop   {P1_4=0,P1_5=0;}  //右边电机停转   

  238.         unsigned char code  LedShowData[]={0x03,0x9F,0x25,0x0D,0x99,  //定义数码管显示数据
  239.                                    0x49,0x41,0x1F,0x01,0x19        };//0,1,2,3,4,5,6,7,8,9
  240.         
  241.         unsigned char voice_sign;
  242.         unsigned int T;
  243.         unsigned char line;
  244.         unsigned int Count;
  245.         unsigned char pwm_val_left  =0;//变量定义
  246.         unsigned char push_val_left ;// 左电机占空比N/20
  247.         unsigned char pwm_val_right =0;
  248.         unsigned char push_val_right ;// 右电机占空比N/20
  249.         unsigned int  time = 0;//传输时间
  250.         unsigned long S = 0;//距离
  251.         bit Right_moto_stop=1;
  252.         bit Left_moto_stop =1;        
  253.         bit      flag = 0;//超出测量范围标志位

  254.    
  255. /************************************************************************/        
  256. //延时函数        
  257.    void delay(unsigned int k)        //1mm延时
  258. {   
  259.      unsigned int x,y;
  260.          for(x=0;x<k;x++)
  261.            for(y=0;y<110;y++);
  262. }
  263. void Delay10us(unsigned char i)            //10us延时函数 启动超声波模块时使用
  264. {
  265.    unsigned char j;
  266.         do{
  267.                 j = 10;
  268.                 do{
  269.                         _nop_();
  270.                 }while(--j);
  271.         }while(--i);
  272. }
  273. /************************************************************************/
  274. /*定时器0中断*/
  275. void zd0() interrupt 1        //T1中断用来计数器溢出,超过测距范围
  276. {
  277.         
  278.         flag=1;        
  279.         T++;                                                 //中断溢出标志                        
  280. }
  281. void  StartModule()                          //启动超声波模块
  282. {
  283.           TX=1;                                             //启动一次模块
  284.       Delay10us(2);
  285.           TX=0;
  286. }


  287. void Dist()           //测试距离
  288. {
  289.         time=TH1*256+TL1;
  290.         TH1=0;
  291.         TL1=0;
  292.         
  293.         S=(float)(time*1.085)*0.17;     //算出来是MM
  294.         if((S>=5000)||flag==1) //超出测量范围
  295.         {         
  296.                 flag=0;

  297.         }
  298. }



  299. /**************************计数函数**********************************************/
  300. void counter(void)
  301. {
  302.                         
  303.                         Count++;
  304.                         ShowPort = LedShowData[Count]  ;
  305.                         delay(200);
  306. }
  307. /**************************计数函数**********************************************/






  308. //前速前进
  309.      void  run(void)
  310. {
  311.      push_val_left=12;         //速度调节变量 0-20。。。0最小,20最大
  312.          push_val_right=12;
  313.          Left_moto_go ;   //左电机往前走
  314.          Right_moto_go ;  //右电机往前走
  315. }

  316. //后退函数
  317.      void  backrun(void)
  318. {
  319.      push_val_left=12;         //速度调节变量 0-20。。。0最小,20最大
  320.          push_val_right=12;
  321.          Left_moto_back;   //左电机往后走
  322.          Right_moto_back;  //右电机往后走
  323. }

  324. //左转
  325.      void  leftrun(void)
  326. {         
  327.          
  328.      push_val_left=12;
  329.          push_val_right=18;
  330.          Right_moto_go ;  //右电机往前走
  331.      Left_moto_back   ;  //左电机后走
  332.          delay(490);
  333. }
  334. //左小偏
  335. void  leftp_1(void)
  336. {         
  337.      push_val_left=3;
  338.          push_val_right=12;
  339.          Right_moto_go ;  //右电机往前走
  340.      Left_moto_go   ;  //左电机后走
  341.          
  342.          
  343. }
  344. //左中偏
  345. void  leftp_2(void)
  346. {         
  347.      push_val_left=1;
  348.          push_val_right=12;
  349.          Right_moto_go ;  //右电机往前走
  350.      Left_moto_back   ;  //左电机后走
  351.          
  352.          
  353. }
  354. //左大偏
  355. void  leftp_3(void)
  356. {         
  357.      push_val_left=3;
  358.          push_val_right=12;
  359.          Right_moto_go ;  //右电机往前走
  360.      Left_moto_back   ;  //左电机后走
  361.          
  362.          
  363. }
  364. //右转
  365.      void  rightrun(void)
  366. {
  367.          
  368.          push_val_left=18;
  369.          push_val_right=12;
  370.      Left_moto_go  ;   //左电机往前走
  371.          Right_moto_back    ;  //右电机往后走
  372.          delay(490)        ;
  373. }
  374. //右小偏
  375.      void  rightp_1(void)
  376. {
  377.          push_val_left=12;
  378.          push_val_right=3;
  379.      Left_moto_go  ;   //左电机往前走
  380.          Right_moto_go    ;  //右电机往后走               
  381. }
  382. //右中偏
  383.      void  rightp_2(void)
  384. {
  385.          push_val_left=12;
  386.          push_val_right=1;
  387.      Left_moto_go  ;   //左电机往前走
  388.          Right_moto_back    ;  //右电机往后走               
  389. }
  390. //右大偏
  391.      void  rightp_3(void)
  392. {
  393.          push_val_left=12;
  394.          push_val_right=3;
  395.      Left_moto_go  ;   //左电机往前走
  396.          Right_moto_back    ;  //右电机往后走
  397.          
  398.                
  399. }

  400. //停止
  401.      void  stop(void)
  402. {         
  403.             delay(200);
  404.          Right_moto_Stop ;  //右电机停止
  405.      Left_moto_Stop  ;  //左电机停止
  406.          delay(100);
  407. }



  408. //掉头
  409.      void  Return(void)
  410.          {
  411.          push_val_left=18;
  412.          push_val_right=18;
  413.      Left_moto_go  ;   //左电机往前走
  414.          Right_moto_back    ;  //右电机往后走
  415.          delay(700)        ;
  416.         
  417.          }

  418.    

  419. /************************************************************************/
  420. /*                    PWM调制电机转速                                   */
  421. /************************************************************************/
  422. /*                    左电机调速                                        */
  423. /*调节push_val_left的值改变电机转速,占空比            */
  424.                 void pwm_out_left_moto(void)
  425. {  
  426.    if(Left_moto_stop)
  427.    {
  428.     if(pwm_val_left<=push_val_left)
  429.                {
  430.                      Left_moto_pwm=1;

  431.                    }
  432.         else
  433.                {
  434.                  Left_moto_pwm=0;

  435.                    }
  436.         if(pwm_val_left>=20)
  437.                pwm_val_left=0;
  438.    }
  439.    else   
  440.           {
  441.            Left_moto_pwm=0;

  442.                   }
  443. }
  444. /******************************************************************/
  445. /*                    右电机调速                                  */  
  446.    void pwm_out_right_moto(void)
  447. {
  448.   if(Right_moto_stop)
  449.    {
  450.     if(pwm_val_right<=push_val_right)
  451.               {
  452.                Right_moto_pwm=1;

  453.                    }
  454.         else
  455.               {
  456.                    Right_moto_pwm=0;

  457.                   }
  458.         if(pwm_val_right>=20)
  459.                pwm_val_right=0;
  460.    }
  461.    else   
  462.           {
  463.            Right_moto_pwm=0;

  464.               }
  465. }
  466.       
  467. /***************************************************/
  468. ///*TIMER0中断服务子函数产生PWM信号*/
  469.          void timer0()interrupt 1   using 2
  470. {
  471.      TH0=0XFc;          //1Ms定时
  472.          TL0=0X18;
  473.          pwm_val_left++;
  474.          pwm_val_right++;
  475.          pwm_out_left_moto();
  476.          pwm_out_right_moto();
  477. }        

  478. /*********************************************************************/        







  479. #endif
复制代码





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

使用道具 举报

沙发
ID:164602 发表于 2019-4-22 08:28 | 只看该作者
我是用三个定时器的。
PWM用T2,发射超声波用T1——因为要每隔一定时间发射超声波测距,就是不让现在发射的超声波影响已经发射的超声波,超声波测距出错用的T0。
所以没有你说的问题。
其实看你的程序,为什么非要用一个定时器啊,加一个不就没事儿了?
回复

使用道具 举报

板凳
ID:432823 发表于 2019-4-22 14:32 | 只看该作者
AT89x52有三个定时器可用,PWM用一个,测距用一个,串口通讯用一个互不干扰。
回复

使用道具 举报

地板
ID:465205 发表于 2019-4-22 16:21 | 只看该作者
HC6800-ES-V2.0 发表于 2019-4-22 08:28
我是用三个定时器的。
PWM用T2,发射超声波用T1——因为要每隔一定时间发射超声波测距,就是不让现在发射 ...

我用过两个定时器,t1和t0,这个也会有干扰
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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