找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 3575|回復(fù): 8
收起左側(cè)

單片機(jī)控制PS2手柄程序,貌似PWM和串口沖突了

[復(fù)制鏈接]
ID:445766 發(fā)表于 2018-12-13 16:41 | 顯示全部樓層 |閱讀模式
大佬們,求助啊。
背景:PS2手柄與STC89C52RC串口發(fā)送數(shù)據(jù),89C52驅(qū)動(dòng)74HC595,74HC595驅(qū)動(dòng)兩個(gè)L293D。目的:PS2控制四個(gè)馬達(dá),PWM無(wú)級(jí)調(diào)速(PS手柄按鍵加減占空比實(shí)現(xiàn))。
問(wèn)題:用定時(shí)器產(chǎn)生PWM控制馬達(dá)轉(zhuǎn)速時(shí),PWM周期設(shè)置貌似有問(wèn)題,周期7秒左右,改TH0和TL0小于500手柄就無(wú)法通訊。
純新手,只要能給我指出問(wèn)題,隨便噴。。。另,若是能幫我解決調(diào)通,耐心指導(dǎo)我一下相關(guān)知識(shí),可給報(bào)酬20R,我知道不多,但是畢竟有點(diǎn)窮。。。
代碼如下(暫時(shí)為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();                //定時(shí)器0初始化
  26. /************函數(shù)聲明**************/
  27. void delayxms(uint z); //延時(shí)
  28. /********************************************************************
  29. * 名稱 : void delayms(uint xms)
  30. * 功能 : 延時(shí)
  31. * 輸入 : 有
  32. * 輸出 : 無(wú)
  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. * 輸入 : 無(wú)
  44. * 輸出 : 無(wú)
  45. ***********************************************************************/
  46. void Com_Init()
  47. {

  48.         TMOD &=        0x0F;
  49.         TMOD |= 0x20;
  50. /************ps2*************/               
  51.     PCON = 0x00;  //波特率不加倍
  52.     SCON = 0x50;  //配置串口工作模式,使能串口接收中斷,等價(jià)于SM0=0,SM1=1,REN=1
  53.         TH1 = 0xFd;
  54.     TL1 = 0xFd;
  55.     TR1 = 1;
  56.           EA=1;          //總中斷開關(guān)
  57.         ES=1;          //串口中斷開關(guān)
  58.         ET1=0;          //定時(shí)器1中斷開關(guān)
  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_();//每個(gè)_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. /****************延時(shí)處理**********************/
  200. void delayxms(uint z) //延時(shí)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. /**************定時(shí)0中斷處理******************/
  217. void timer0_int() interrupt 1
  218. {
  219.   TMOD&=0xF0;  
  220.   TMOD|=0x01;         
  221.   TR0=0;    //設(shè)置定時(shí)器初值期間,關(guān)閉定時(shí)器
  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. }
復(fù)制代碼


評(píng)分

參與人數(shù) 1黑幣 +12 收起 理由
通天塔 + 12

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:445766 發(fā)表于 2018-12-13 16:49 | 顯示全部樓層
mid_TH0=(65536-500)/256;
設(shè)置500及以上時(shí),可通過(guò)手柄實(shí)現(xiàn)四種占空比,但是每個(gè)PWM周期大約有7秒。
200-500有時(shí)可以有時(shí)不行,200以下操縱手柄完全無(wú)反應(yīng)。
猜測(cè)應(yīng)該是串口和PWM沖突,但是查找百度解決方法都不可用。
回復(fù)

使用道具 舉報(bào)

ID:445766 發(fā)表于 2018-12-13 17:38 | 顯示全部樓層
  mid_TH0=(65536-500)/256;                        
  mid_TL0=(65536-500)%256;
按照這個(gè)設(shè)置,頻率應(yīng)該很高啊,但是實(shí)際驅(qū)動(dòng)電機(jī)周期約為7秒。
而且設(shè)置為500以下時(shí),PS2手柄操縱會(huì)失效,猜測(cè)是和PWM沖突。
但是按照百度解決方法還不能解決。
回復(fù)

使用道具 舉報(bào)

ID:275479 發(fā)表于 2018-12-13 18:12 | 顯示全部樓層
定時(shí)器頻繁中斷,導(dǎo)致按鍵無(wú)法正常掃描了,用其他芯片,自動(dòng)產(chǎn)生PWM波的那種,就不需要頻繁進(jìn)入中斷了
回復(fù)

使用道具 舉報(bào)

ID:275479 發(fā)表于 2018-12-13 18:14 | 顯示全部樓層
或者把波特率跳高一些試試
回復(fù)

使用道具 舉報(bào)

ID:445766 發(fā)表于 2018-12-14 08:36 | 顯示全部樓層
通天塔 發(fā)表于 2018-12-13 18:12
定時(shí)器頻繁中斷,導(dǎo)致按鍵無(wú)法正常掃描了,用其他芯片,自動(dòng)產(chǎn)生PWM波的那種,就不需要頻繁進(jìn)入中斷了

大佬,問(wèn)題是定時(shí)器頻繁中斷應(yīng)該保證PWM輸出無(wú)誤啊,現(xiàn)在PWM周期很長(zhǎng),不符合道理啊
回復(fù)

使用道具 舉報(bào)

ID:275479 發(fā)表于 2018-12-14 09:17 | 顯示全部樓層
初學(xué)者小白 發(fā)表于 2018-12-14 08:36
大佬,問(wèn)題是定時(shí)器頻繁中斷應(yīng)該保證PWM輸出無(wú)誤啊,現(xiàn)在PWM周期很長(zhǎng),不符合道理啊

void timer0_int() interrupt 1
{
  TMOD&=0xF0;  
  TMOD|=0x01;         
  TR0=0;    //設(shè)置定時(shí)器初值期間,關(guān)閉定時(shí)器
  TH0=mid_TH0;
  TL0=mid_TL0;
  TR0=1;
         
  time++;
  if(time<count)          //count為占空比
  {
        PWM=1;           //輸出高電平
  }
  else
        PWM=0;        
  if(time>=100)
  {
        time=0;
  }
}
你考慮以下多長(zhǎng)時(shí)間就進(jìn)這么一次中斷,200*200us的話,大約4MS就要進(jìn)一次中斷
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表