找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2066|回复: 3
收起左侧

51单片机用蓝牙控制小车的舵机一些问题,求大神解答

[复制链接]
ID:900662 发表于 2021-4-12 19:25 | 显示全部楼层 |阅读模式
我想做一个用蓝牙控制小车的舵机,但是遇到很多问题
1.我看到说是51单片机里面t0和t1定时器是可以同时工作的,又查到小车的蓝牙波特率是用T1做的(T1的ET0=0,没有开中断允许位),然后我就自己写了个T0定时器产生pwm控制舵机的程序,单独打开并且下载进去之后,舵机可以正常使用,但是我移植到蓝牙控制小车的大程序之后,我将TR0置0,然后通过蓝牙写入一个字符串,调用舵机函数,舵机函数中把TR0打开,但是进不了T0的中断函数,蓝牙也失效。这是什么问题,有时候我用蓝牙控制小车的时候前进后退的时候,舵机也会转,我不知道怎么办了,用T2做波特率发生器,用T1做PWM能行吗?不知道是舵机会影响单片机,还是T0和T1冲突,还是我用蓝牙调用函数开T0中断的问题。程序如下,求大神解答。

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


  3.         //HJ-4WD小车驱动接线定义
  4. #define Left_moto_go      {P1_4=1,P1_5=0,P1_6=1,P1_7=0;}  //左边两个电机向前走
  5. #define Left_moto_back    {P1_4=0,P1_5=1,P1_6=0,P1_7=1;}  //左边两个电机向后转
  6. #define Left_moto_Stop    {P1_4=0,P1_5=0,P1_6=0,P1_7=0;}  //左边两个电机停转                     
  7. #define Right_moto_go     {P1_0=1,P1_1=0,P1_2=1,P1_3=0;}        //右边两个电机向前走
  8. #define Right_moto_back   {P1_0=0,P1_1=1,P1_2=0,P1_3=1;}        //右边两个电机向后走
  9. #define Right_moto_Stop   {P1_0=0,P1_1=0,P1_2=0,P1_3=0;}        //右边两个电机停转   

  10. #define left     'C'
  11. #define right    'D'
  12. #define up       'A'
  13. #define down     'B'
  14. #define stop     'F'
  15. #define guiwei1  '1'

  16.         #define uchar unsigned char
  17.         #define ulong unsigned long
  18.         #define uint  unsigned int
  19.                
  20.         char code str[] =  "收到指令,向前!\n";
  21.         char code str1[] = "收到指令,向后!\n";
  22.         char code str2[] = "收到指令,向左!\n";
  23.         char code str3[] = "收到指令,向右!\n";
  24.         char code str4[] = "收到指令,停止!\n";
  25.         char code str5[] = "收到指令,舵机归位!\n";

  26.         bit  flag_REC=0;
  27.         bit  flag    =0;  
  28.         
  29.                 sbit Sevro_moto_pwm1=P2^7;           //左右
  30.         sbit Sevro_moto_pwm2=P2^1;    //伸缩
  31.         sbit Sevro_moto_pwm3=P2^2;    //上下
  32.         sbit LED=P2^0;//用来测试的LED
  33.         
  34.         
  35.         uchar  i=0;
  36.         uchar  dat=0;
  37.   uchar  buff[5]=0; //接收缓冲字节

  38.         
  39.   uchar pwm_val_left1=0;//变量定义
  40.         uchar pwm_val_left2=0;//变量定义
  41.         uchar pwm_val_left3=0;//变量定义
  42.         uchar push_val_left1=18;//1舵机归位,产生约,1.9MS 信号
  43.         uchar push_val_left2=11;//2舵机归位,产生约,1.2MS 信号
  44.         uchar push_val_left3=15;//3舵机归位,产生约,1.6MS 信号
  45.         uint flag1=1;
  46.         uint timer=0;
  47. /************************************************************************/        
  48. //延时函数        
  49.    void delay(unsigned int k)
  50. {   
  51.      unsigned int x,y;
  52.          for(x=0;x<k;x++)
  53.            for(y=0;y<2000;y++);
  54. }


  55. void motoinit()//舵机初始位置定义
  56. {
  57.     push_val_left1=18;           
  58.           push_val_left2=11;
  59.           push_val_left3=15;
  60. }




  61. /************************************************************************/
  62. /*                    PWM信号产生控制舵机                               */
  63. /************************************************************************/
  64. /*                                                                      */
  65. /*调节push_val_left的值改变电机转速,占空比            */
  66.                 void pwm_Servomoto1(void)
  67. {  
  68.   if(pwm_val_left1<=push_val_left1)//1号舵机控制
  69.                Sevro_moto_pwm1=1;

  70.         else
  71.         {                          
  72.                Sevro_moto_pwm1=0;
  73.                      flag1++;
  74.         }
  75.         if(pwm_val_left1>=200)
  76.         pwm_val_left1=0;
  77. }
  78.                 void pwm_Servomoto2(void)
  79. {
  80.         if(pwm_val_left2<=push_val_left2)//2号舵机控制
  81.                Sevro_moto_pwm2=1;
  82.         else
  83.         {
  84.                         Sevro_moto_pwm2=0;
  85.                 flag1++;
  86.         }               
  87.         if(pwm_val_left2>=200)
  88.         pwm_val_left2=0;
  89. }
  90.                 void pwm_Servomoto3(void)//三号舵机控制
  91.                 {
  92. if(pwm_val_left3<=push_val_left3)
  93.                Sevro_moto_pwm3=1;
  94.         else
  95.         {               
  96.                Sevro_moto_pwm3=0;
  97.                      flag1=1;
  98.                      TR=0;//三个舵机归位后,定时器0关闭
  99.         }
  100.         if(pwm_val_left3>=200)
  101.         pwm_val_left3=0;
  102. }
  103.                




  104. void guiwei()//三个舵机归位函数
  105. {
  106.           TR0=1;//打开T0定时器,后面会考虑增加延时函数,确保舵机归位完成
  107. }



  108. /************************************************************************/
  109. //字符串发送函数
  110.           void send_str( )
  111.                    // 传送字串
  112.     {
  113.             unsigned char i = 0;
  114.             while(str[i] != '\0')
  115.            {
  116.                 SBUF = str[i];
  117.                 while(!TI);                                // 等特数据传送
  118.                 TI = 0;                                        // 清除数据传送标志
  119.                 i++;                                        // 下一个字符
  120.            }        
  121.     }
  122.         
  123.                   void send_str1( )
  124.                    // 传送字串
  125.     {
  126.             unsigned char i = 0;
  127.             while(str1[i] != '\0')
  128.            {
  129.                 SBUF = str1[i];
  130.                 while(!TI);                                // 等特数据传送
  131.                 TI = 0;                                        // 清除数据传送标志
  132.                 i++;                                        // 下一个字符
  133.            }        
  134.     }        

  135.                           void send_str2( )
  136.                    // 传送字串
  137.     {
  138.             unsigned char i = 0;
  139.             while(str2[i] != '\0')
  140.            {
  141.                 SBUF = str2[i];
  142.                 while(!TI);                                // 等特数据传送
  143.                 TI = 0;                                        // 清除数据传送标志
  144.                 i++;                                        // 下一个字符
  145.            }        
  146.     }        
  147.                     
  148.                           void send_str3()
  149.                    // 传送字串
  150.     {
  151.             unsigned char i = 0;
  152.             while(str3[i] != '\0')
  153.            {
  154.                 SBUF = str3[i];
  155.                 while(!TI);                                // 等特数据传送
  156.                 TI = 0;                                        // 清除数据传送标志
  157.                 i++;                                        // 下一个字符
  158.            }        
  159.     }        

  160.               void send_str4()
  161.                    // 传送字串
  162.     {
  163.             unsigned char i = 0;
  164.             while(str4[i] != '\0')
  165.            {
  166.                 SBUF = str4[i];
  167.                 while(!TI);                                // 等特数据传送
  168.                 TI = 0;                                        // 清除数据传送标志
  169.                 i++;                                        // 下一个字符
  170.            }        
  171.     }        
  172.                     
  173.         
  174.               void send_str5()
  175.                    // 传送字串
  176.     {
  177.             unsigned char i = 0;
  178.             while(str4[i] != '\0')
  179.            {
  180.                 SBUF = str5[i];
  181.                 while(!TI);                                // 等特数据传送
  182.                 TI = 0;                                        // 清除数据传送标志
  183.                 i++;                                        // 下一个字符
  184.            }        
  185.     }                        
  186. /************************************************************************/
  187. //前速前进
  188.      void  run(void)
  189. {

  190.          Left_moto_go;   //左电机往前走
  191.          Right_moto_go;  //右电机往前走
  192. }

  193. //前速后退
  194.      void  backrun(void)
  195. {

  196.          Left_moto_back ;   //左电机往前走
  197.          Right_moto_back ;  //右电机往前走
  198. }

  199. //左转
  200.      void  leftrun(void)
  201. {

  202.          Left_moto_back ;   //左电机往前走
  203.          Right_moto_go ;  //右电机往前走
  204. }

  205. //右转
  206.      void  rightrun(void)
  207. {

  208.          Left_moto_go;   //左电机往前走
  209.          Right_moto_back;  //右电机往前走
  210. }
  211. //STOP
  212.      void  stoprun(void)
  213. {

  214.          Left_moto_Stop ;   //左电机往前走
  215.          Right_moto_Stop ;  //右电机往前走
  216. }
  217. /************************************************************************/
  218. void sint() interrupt 4          //中断接收3个字节
  219. {

  220.     if(RI)                         //是否接收中断
  221.     {
  222.        RI=0;
  223.        dat=SBUF;
  224.        if(dat=='O'&&(i==0)) //接收数据第一帧
  225.          {
  226.             buff[i]=dat;
  227.             flag=1;        //开始接收数据
  228.          }
  229.        else
  230.       if(flag==1)
  231.      {
  232.       i++;
  233.       buff[i]=dat;
  234.       if(i>=2)
  235.       {i=0;flag=0;flag_REC=1 ;}  // 停止接收
  236.      }
  237.          }
  238.                   if(flag_REC==1)                                    //
  239.            {
  240.                 flag_REC=0;
  241.                 if(buff[0]=='O'&&buff[1]=='N')        //第一个字节为O,第二个字节为N,第三个字节为控制码
  242.                 switch(buff[2])
  243.              {
  244.                       case up :                                                    // 前进
  245.                           send_str( );
  246.                           run();
  247.                           break;
  248.                       case down:                                                // 后退
  249.                            send_str1( );
  250.                           backrun();
  251.                           break;
  252.                       case left:                                                // 左转
  253.                            send_str3( );
  254.                           leftrun();
  255.                           break;
  256.                       case right:                                                // 右转
  257.                           send_str2( );
  258.                           rightrun();
  259.                           break;
  260.                       case stop:                                                // 停止
  261.                            send_str4( );
  262.                           stoprun();
  263.                           break;
  264.                                         case guiwei1:                                                // 停止
  265.                            send_str5( );
  266. //                                        LED=~LED;
  267.                           guiwei();
  268.                           break;

  269.              }                                         
  270.          }
  271. }
  272.          void time1()interrupt 1
  273. {        
  274.    TH0=(65536-10000)/256;          //100US定时
  275.          TL0=(65536-10000)%256;
  276.         timer++;//定时器100US为准。在这个基础上延时,在后续增加延时确保舵机归位完成。
  277.           LED=~LED;        
  278.                 if(flag1==1)//三个舵机分别归位的函数
  279.                 {
  280.                pwm_val_left1++;
  281.          pwm_Servomoto1();
  282. //                        LED=0;
  283.                 }         

  284.     if(flag1==2)
  285.                 {
  286.                         pwm_val_left2++;
  287.                   pwm_Servomoto2();                        
  288.                 }
  289.      else
  290.                  {
  291.       pwm_val_left3++;
  292.                   pwm_Servomoto3();
  293.         }
  294. }
  295.         
  296. /*********************************************************************/                 
  297. /*--主函数--*/
  298.         void main(void)
  299. {
  300.         
  301.         TMOD=0x01;
  302.         IE|=0x82;
  303.         TH0=(65536-100)/256;          //100US定时
  304.         TL0=(65536-100)%256;
  305.         ET0=1;
  306.         TR0=1;
  307.         
  308.           TMOD=0x20;  
  309.     TH1=0xFd;                     //11.0592M晶振,9600波特率
  310.     TL1=0xFd;
  311.     SCON=0x50;  
  312.     PCON=0x00;                 
  313.     TR1=1;
  314.     ES=1;       //开串口中断  
  315.     EA=1;         //打开总中断
  316.     TR0=0;        //关闭定时器0,在蓝牙发出对应的调用指令后开启。
  317.     Sevro_moto_pwm1=0;
  318.     Sevro_moto_pwm2=0;
  319.     Sevro_moto_pwm3=0;
  320.                  motoinit();       //舵机的归位数值(分别产生数个100us的高脉冲)
  321.                  LED=1;
  322.            while(1)                                                        /*无限循环*/
  323.         {
  324.                
  325.         }        

  326. }
复制代码



回复

使用道具 举报

ID:900662 发表于 2021-4-13 16:22 | 显示全部楼层
大哥们,,有没有啥51单片机的好书推荐一下我康康也可以、
回复

使用道具 举报

ID:65956 发表于 2021-4-15 08:17 | 显示全部楼层
TMOD=0x01;和TMOD=0x20;  这个要改成TMOD|=0x01;和TMOD|=0x20;  就不会互相影响到各自的定时器配置了

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:900662 发表于 2021-4-15 19:03 | 显示全部楼层
aking991 发表于 2021-4-15 08:17
TMOD=0x01;和TMOD=0x20;  这个要改成TMOD|=0x01;和TMOD|=0x20;  就不会互相影响到各自的定时器配置了

这么做还是不行,后来多次测试,我又换了T2定时器做波特率发生器,然后T1产生PWM波形,最终发现中断只进了一次,舵机1的PWM输出口一直保持的是高电平,好像是硬件没有清零溢出的标志位,最后没办法了,我又买了一块单片机单独控制三个舵机,
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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