找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机控制PS2手柄程序,貌似PWM和串口冲突了

[复制链接]
跳转到指定楼层
楼主
ID:445766 发表于 2018-12-13 16:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大佬们,求助啊。
背景:PS2手柄与STC89C52RC串口发送数据,89C52驱动74HC595,74HC595驱动两个L293D。目的:PS2控制四个马达,PWM无级调速(PS手柄按键加减占空比实现)。
问题:用定时器产生PWM控制马达转速时,PWM周期设置貌似有问题,周期7秒左右,改TH0和TL0小于500手柄就无法通讯。
纯新手,只要能给我指出问题,随便喷。。。另,若是能帮我解决调通,耐心指导我一下相关知识,可给报酬20R,我知道不多,但是毕竟有点穷。。。
代码如下(暂时为4种占空比):
  1. #include<reg52.h>
  2. #include<intrins.h>

  3. #define  uchar unsigned char
  4. #define  uint  unsigned int



  5. //#define Self_Define_ISP_Download_Command 0x3D
  6. //sfr IAP_CONTR=0xE7;

  7. sbit  DATA=P0^0;
  8. sbit  CMND=P0^1;
  9. sbit  ATT=P0^2;
  10. sbit  CLK=P0^3;

  11. uchar code scan[9]={0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  12. uchar  out[9];            

  13. uchar time;
  14. double count=0;        //定义占空比
  15. bit PWM=0;   
  16. int mid_TH0,mid_TL0;
  17. sbit sck=P1^0;
  18. sbit ser=P1^1;
  19. sbit rck=P1^2;


  20. sbit EN1=P1^3;          //ic2          M4
  21. sbit EN2=P1^4;          //ic2          M3
  22. sbit EN3=P1^5;          //ic1          M2
  23. sbit EN4=P1^6;          //ic1          M1

  24. uchar code Tab[]={0x99,0x66};

  25. void timer0_init();                //定时器0初始化
  26. /************函数声明**************/
  27. void delayxms(uint z); //延时
  28. /********************************************************************
  29. * 名称 : void delayms(uint xms)
  30. * 功能 : 延时
  31. * 输入 : 有
  32. * 输出 : 无
  33. ***********************************************************************/
  34. void delayms(uint xms)
  35. {
  36.    uint i,j;
  37.    for(i=xms;i>0;i--)
  38.       for(j=1700;j>0;j--);
  39. }
  40. /********************************************************************
  41. * 名称 : Com_Init()
  42. * 功能 : 初始化串口程序,晶振11.0592, 波特率9600
  43. * 输入 : 无
  44. * 输出 : 无
  45. ***********************************************************************/
  46. void Com_Init()
  47. {

  48.         TMOD &=        0x0F;
  49.         TMOD |= 0x20;
  50. /************ps2*************/               
  51.     PCON = 0x00;  //波特率不加倍
  52.     SCON = 0x50;  //配置串口工作模式,使能串口接收中断,等价于SM0=0,SM1=1,REN=1
  53.         TH1 = 0xFd;
  54.     TL1 = 0xFd;
  55.     TR1 = 1;
  56.           EA=1;          //总中断开关
  57.         ES=1;          //串口中断开关
  58.         ET1=0;          //定时器1中断开关
  59. //        IP=0x10;
  60. /**************烧写***********/        
  61. //        SM0=0;
  62. //        SM1=1;
  63. //        REN=1;                        
  64. }

  65. void input(uchar dat)
  66. {
  67.         uchar i;
  68.         for(i=0;i<8;i++)
  69.         {
  70.                 if((dat<<i)&0x80)
  71.                 {
  72.                         ser=1;
  73.                 }
  74.                 else
  75.                 {
  76.                         ser=0;
  77.                 }
  78.                 sck=0;
  79.                 sck=1;
  80.         }
  81. }

  82. void output()
  83. {
  84.         rck=0;
  85.         rck=1;
  86.         rck=0;
  87. }


  88. void delay(uint n)  //delay(x)=(2.5+x)us;
  89. {
  90.         uint i;
  91.         for(i=0;i<n;i++) _nop_();      
  92. //                _nop_();//每个_nop_();大概0.1微秒        
  93. }
  94. uchar scanout(uchar command)//手柄
  95. {
  96.     uchar i,j=1;
  97.         uchar res=0;
  98.     for(i=0;i<=7;i++)     //逐位接收     
  99.     {
  100.          if(command&0x01)
  101.         CMND=1;
  102.      else
  103.         CMND=0;
  104.      command=command>>1;
  105.                  _nop_();        
  106.                 _nop_();
  107.      CLK=0;
  108.      delay(10);
  109.          if(DATA) res=res+j;
  110.      j=j<<1;
  111.          CLK=1;
  112.          delay(3);                 
  113.     }
  114.     CMND=1;
  115.     return res;        
  116. }
  117. void Read_PS2(void)//手柄读取程序
  118. {
  119.          uchar i;
  120.      ATT=0;
  121.          for(i=0;i<9;i++)        //扫描按键
  122.         {
  123.          out[i]=scanout(scan[i]);        
  124.                  }
  125.      ATT=1;                     
  126.          
  127. }                                             


  128. void main()
  129. {
  130.         IP=0x10;
  131.         Com_Init();
  132.         timer0_init();
  133.         
  134.         EN1=0;          //M4         FR
  135.         EN2=0;          //M3         RR
  136.         EN3=0;          //M2         FL
  137.         EN4=0;          //M1         RL

  138.         while(1)
  139.         {
  140.         Read_PS2();
  141.         delayms(10);        
  142.         if(out[3]==0xEF)//上,PS2手柄按键
  143.         {
  144.                 count=100;
  145.                 EN1=PWM;          //M4
  146.                 EN2=PWM;          //M3
  147.                 EN3=PWM;          //M2
  148.                 EN4=PWM;          //M1
  149.                 input(Tab[1] );
  150.                 output();
  151.         }
  152.         else if(out[3]==0xBF)//下
  153.         {
  154.                 count=60;
  155.                 EN1=PWM;          //M4
  156.                 EN2=PWM;          //M3
  157.                 EN3=PWM;          //M2
  158.                 EN4=PWM;          //M1
  159.                 input(Tab[1] );
  160.                 output();
  161.         }
  162.         else if(out[3]==0x7F)//左
  163.         {
  164.                 count=30;
  165.                 EN1=PWM;          //M4
  166.                 EN2=PWM;          //M3
  167.                 EN3=PWM;          //M2
  168.                 EN4=PWM;          //M1
  169.                 input(Tab[1] );
  170.                 output();
  171.         }
  172.         else if(out[3]==0xDF)//右
  173.         {
  174.                 count=10;
  175.                 EN1=PWM;          //M4
  176.                 EN2=PWM;          //M3
  177.                 EN3=PWM;          //M2
  178.                 EN4=PWM;          //M1
  179.                 input(Tab[1] );
  180.                 output();
  181.         }
  182.         else if(out[4]==0xFB)//停
  183.         {
  184.                                         EN1=0;          //M4
  185.                 EN2=0;          //M3
  186.                 EN3=0;          //M2
  187.                 EN4=0;          //M1
  188.                 input(Tab[0] );
  189.                 output();
  190.         }
  191.         else{
  192.                 EN1=0;          //M4        FR
  193.                 EN2=0;          //M3          RR
  194.                 EN3=0;          //M2         FL
  195.                 EN4=0;          //M1         RL
  196.         }

  197.         }
  198. }

  199. /****************延时处理**********************/
  200. void delayxms(uint z) //延时xms程序
  201. {
  202.     uint x,y;
  203.         for(y=z;x>0;x--)
  204.                 for(y=110;y>0;y--);
  205. }

  206. void timer0_init()
  207. {
  208.   TMOD&=0xF0;
  209.   TMOD|=0x01;
  210.   mid_TH0=(65536-500)/256;                        
  211.   mid_TL0=(65536-500)%256;               
  212.   TR0=1;
  213.   ET0=1;
  214.   EA=1;
  215. }

  216. /**************定时0中断处理******************/
  217. void timer0_int() interrupt 1
  218. {
  219.   TMOD&=0xF0;  
  220.   TMOD|=0x01;         
  221.   TR0=0;    //设置定时器初值期间,关闭定时器
  222.   TH0=mid_TH0;
  223.   TL0=mid_TL0;
  224.   TR0=1;
  225.          
  226.   time++;
  227.   if(time<count)          //count为占空比
  228.   {
  229.         PWM=1;           //输出高电平
  230.   }
  231.   else
  232.         PWM=0;        
  233.   if(time>=100)
  234.   {
  235.         time=0;
  236.   }
  237. }
  238. void Com_Int() interrupt 4
  239. {
  240. if(RI==1)
  241.     {
  242.                 RI=0;
  243.         }
  244. }
复制代码


评分

参与人数 1黑币 +12 收起 理由
通天塔 + 12

查看全部评分

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

使用道具 举报

沙发
ID:445766 发表于 2018-12-13 16:49 | 只看该作者
mid_TH0=(65536-500)/256;
设置500及以上时,可通过手柄实现四种占空比,但是每个PWM周期大约有7秒。
200-500有时可以有时不行,200以下操纵手柄完全无反应。
猜测应该是串口和PWM冲突,但是查找百度解决方法都不可用。
回复

使用道具 举报

板凳
ID:445766 发表于 2018-12-13 17:38 | 只看该作者
  mid_TH0=(65536-500)/256;                        
  mid_TL0=(65536-500)%256;
按照这个设置,频率应该很高啊,但是实际驱动电机周期约为7秒。
而且设置为500以下时,PS2手柄操纵会失效,猜测是和PWM冲突。
但是按照百度解决方法还不能解决。
回复

使用道具 举报

地板
ID:275479 发表于 2018-12-13 18:12 | 只看该作者
定时器频繁中断,导致按键无法正常扫描了,用其他芯片,自动产生PWM波的那种,就不需要频繁进入中断了
回复

使用道具 举报

5#
ID:275479 发表于 2018-12-13 18:14 | 只看该作者
或者把波特率跳高一些试试
回复

使用道具 举报

6#
ID:445766 发表于 2018-12-14 08:36 | 只看该作者
通天塔 发表于 2018-12-13 18:12
定时器频繁中断,导致按键无法正常扫描了,用其他芯片,自动产生PWM波的那种,就不需要频繁进入中断了

大佬,问题是定时器频繁中断应该保证PWM输出无误啊,现在PWM周期很长,不符合道理啊
回复

使用道具 举报

7#
ID:275479 发表于 2018-12-14 09:17 | 只看该作者
初学者小白 发表于 2018-12-14 08:36
大佬,问题是定时器频繁中断应该保证PWM输出无误啊,现在PWM周期很长,不符合道理啊

void timer0_int() interrupt 1
{
  TMOD&=0xF0;  
  TMOD|=0x01;         
  TR0=0;    //设置定时器初值期间,关闭定时器
  TH0=mid_TH0;
  TL0=mid_TL0;
  TR0=1;
         
  time++;
  if(time<count)          //count为占空比
  {
        PWM=1;           //输出高电平
  }
  else
        PWM=0;        
  if(time>=100)
  {
        time=0;
  }
}
你考虑以下多长时间就进这么一次中断,200*200us的话,大约4MS就要进一次中断
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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