久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3281|回復: 3
收起左側

單片機串口通信控制步進電機,為什么每次上電只能接收一次數據控制一次?

[復制鏈接]
ID:451441 發表于 2019-9-10 18:10 | 顯示全部樓層 |閱讀模式
求助,上面的程序我單片機上電后可以正常串口通信收到數據,也可以按照設定返回給串口助手相應信息,電機也可以轉動指定的脈沖數,但接下來接不能正常通信了,再發數據串口助手就沒有反映了,電機也不轉了,單片機關掉再上電就又可以正確接收一次數據。我想不明白哪里的問題,特來求助,望指導。

單片機源程序如下:
  1. #include<reg52.h>  //共陽極接法
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. #define N 8           //可一次接收數據量 幀頭(# ascii碼)0x23        幀頭(+/-號)+——0x2b  --0x2d     5位數據   幀尾(* ascii碼)0x2a

  5. sbit dula=P2^6;
  6. sbit wela=P2^7;
  7. sbit pul=P1^0;        //脈沖端
  8. sbit dir=P1^2;        //方向端
  9. sbit ena=P1^1;        // 電機軸使能端
  10. sbit limita=P1^3; //起始端極限位
  11. sbit limitb=P1^4;//遠端極限位
  12. sbit origin=P1^5;//原點位

  13. sbit led=P1^1;
  14. sbit led2=P1^3;

  15. uchar forward=0,backward=0,flag,i,w,j=0,serial_con;
  16. uint n,m,l,k,r,a,b,c,d,e,sum;


  17. uchar code table[]={           //數碼管編碼組
  18. 0x3f,0x06,0x5b,0x4f,
  19. 0x66,0x6d,0x7d,0x07,
  20. 0x7f,0x6f,0x77,0x7c,
  21. 0x39,0x5e,0x79,0x71};                           
  22. uchar code table1[]="MCU gets ";
  23. uchar code table2[]=" pluses!\r\n";
  24. uchar code table3[]="Error 1!\r\n";        //幀頭錯誤反饋代碼
  25. uchar code table4[]="Error 2!\r\n";        //幀尾錯誤反饋代碼
  26. uchar code table5[]="Error 3!\r\n";//脈沖數超過38500

  27. uchar rectable[N];        //用于接收串口通信數據的數組

  28. void delayms(uint xms)                  //延時子程序
  29. {
  30.         uint i,j;
  31.         for(i=xms;i>0;i--)
  32.                 for(j=110;j>0;j--);
  33. }

  34. void display(uchar num)          //顯示子函數
  35. {
  36.         P0=table[num];
  37.         dula=1;
  38.         dula=0;
  39. }



  40. void tmod(uint m)                   //設置定時器0中斷時間的子函數
  41. {
  42.         TMOD=0x01;//設定定時器0 工作方式1(16位定時/計數器)
  43.         TH0=(65536-m)/256;                //設定中斷發生時間
  44.         TL0=(65536-m)%256;
  45.         ET0=1;                 //開定時器0中斷
  46.         EA=1;                 //開總中斷
  47.         TR0=1;                 //開啟定時器0
  48. }

  49. void rs232_init()           //串口通信初始化子程序
  50. {
  51.         TMOD=0x20;
  52.     TH1=0xfd;                   //9600波特率
  53.     TL1=0xfd;
  54.     TR1=1;                                //波特率的發生利用定時器1
  55.     SM0=0;
  56.     SM1=1;
  57.     REN=1;    //先設定好工作方式,再打開允許接收
  58.     EA=1;          //打開總中斷
  59.     ES=1;     //打開串口中斷  
  60. }

  61. void serial_control()                         //根據串口通信收到脈沖數轉動子程序
  62. {
  63.         if(serial_con==1)
  64.         {
  65.                         r=0;                                                                  //進入幾次定時器0中斷計數用
  66.                         serial_con=0;
  67.                 /*        a=rectable[2]-'0';
  68.                         b=rectable[3]-'0';
  69.                         c=rectable[4]-'0';
  70.                         d=rectable[5]-'0';
  71.                         e=rectable[6]-'0';
  72.                         sum=a*10000+b*1000+c*100+d*10+e;         //把輸入的脈沖數的字符型字轉變成數字         */
  73.                         if(limita==1&&limitb==1)
  74.                         {
  75.                                 switch(rectable[1])                                 //判斷方向 +號ASC碼 0x2b
  76.                                 {
  77.                                         case 0x2b:
  78.                                                  dir=0;
  79.                                                  tmod(500);
  80.                                                  n=2;
  81.                                                  forward=1;
  82.                                                  break;
  83.                                         case 0x2d:                                   ////判斷方向 -號ASC碼 0x2d
  84.                                                  dir=1;
  85.                                                  tmod(500);
  86.                                                  n=2;
  87.                                                  backward=1;
  88.                                                  break;        
  89.                                 }
  90.                         }        
  91.                          serial_con=0;                                
  92.          }         
  93.          
  94.                   
  95. }

  96. void serial_com()                                                  //串口通信子程序
  97. {
  98.              if(flag==1)
  99.         {
  100.                                 a=rectable[2]-'0';
  101.                                 b=rectable[3]-'0';
  102.                                 c=rectable[4]-'0';
  103.                                 d=rectable[5]-'0';
  104.                                 e=rectable[6]-'0';
  105.                                 sum=a*10000+b*1000+c*100+d*10+e;         //把輸入的脈沖數的字符型字轉變成數字
  106.                                 if(sum<=38500)                                                //判斷是否超限,如果沒有超限
  107.                                 {                                       
  108.                                 ES=0;                  //關閉串口中斷
  109.                             for(i=0;i<9;i++)           //發送既定字符
  110.                             {
  111.                                     SBUF=table1[i];
  112.                                 while(!TI);
  113.                                 TI=0;
  114.                              }
  115.                              for(j=2;j<(N-1);j++) //發送接收數組               
  116.                              {
  117.                                      SBUF=rectable[j];
  118.                                 while(!TI);
  119.                                 TI=0;
  120.                               }        
  121.                                          for(i=0;i<12;i++)           //發送既定字符
  122.                                           {
  123.                                                   SBUF=table2[i];
  124.                                                 while(!TI);
  125.                                                 TI=0;
  126.                                           }        
  127.                                           j=0;
  128.                                           ES=1;
  129.                                           flag=0;
  130.                                           serial_con=1;                //進入根據收到脈沖數運動的子函數的標志位
  131.                                   }
  132.                           if(sum>38500)                                //如果輸入脈沖超限
  133.                           {
  134.                                   ES=0;
  135.                                   for(i=0;i<12;i++)
  136.                                 {
  137.                                         SBUF=table5[i];
  138.                                         while(!TI);
  139.                                         TI=0;
  140.                                 }
  141.                           }
  142.                           j=0;
  143.                           ES=1;
  144.                           flag=0;
  145.          }
  146.                  if(flag==2)                  //幀頭不正確的報錯
  147.                  {
  148.                          ES=0;
  149.                          for(i=0;i<12;i++)
  150.                         {
  151.                                 SBUF=table3[i];
  152.                                 while(!TI);
  153.                                 TI=0;
  154.                         }
  155.                         ES=1;
  156.                         flag=0;
  157.                  }     
  158.                  if(flag==3)                        //幀尾不正確的報錯
  159.                  {
  160.                          ES=0;
  161.                         for(i=0;i<12;i++)
  162.                         {
  163.                                 SBUF=table4[i];
  164.                                 while(!TI);
  165.                                 TI=0;
  166.                         }
  167.                         ES=1;
  168.                         flag=0;
  169.                  }                           
  170. }





  171. void time0() interrupt 1                  //定時器0中斷子程序 中斷頻率在此函數內設置不同的頻率,即不同的轉速
  172. {

  173.         switch(n)
  174.         {        
  175.         //        case 0:
  176.         //                TH0=(65536-12500)/256; //n=12500 頻率為40Hz     400脈沖/圈時轉速為 6r/m
  177.         //                TL0=(65536-12500)%256;
  178.         //                break;
  179.                 case 0:
  180.                         TH0=(65536-5000)/256; //n=5000 頻率為100Hz     400脈沖/圈時轉速為 15r/m
  181.                         TL0=(65536-5000)%256;
  182.                         break;
  183.         //        case 0:
  184.         //                TH0=(65536-2500)/256; //n=2500 頻率為200Hz     400脈沖/圈時轉速為 30r/m
  185.         //                TL0=(65536-2500)%256;
  186.         //                break;
  187.                 case 1:
  188.                         TH0=(65536-1250)/256; //n=1250 頻率為400Hz     400脈沖/圈時轉速為 60r/m
  189.                         TL0=(65536-1250)%256;
  190.                         break;
  191.         //        case 0:
  192.         //                TH0=(65536-1000)/256; //n=1000 頻率為500Hz     400脈沖/圈時轉速為 75r/m
  193.         //                TL0=(65536-1000)%256;
  194.         //                break;
  195.         //        case 0:
  196.         //                TH0=(65536-800)/256; //n=800 頻率為625Hz     400脈沖/圈時轉速為 93.75r/m
  197.         //                TL0=(65536-800)%256;
  198.         //                break;
  199.                 case 2:
  200.                         TH0=(65536-500)/256; //n=500 頻率為1KHz     400脈沖/圈時轉速為 150r/m
  201.                         TL0=(65536-500)%256;
  202.                         break;
  203.         //        case 2:
  204.         //                TH0=(65536-312)/256; //n=312 頻率為1.6KHz     400脈沖/圈時轉速為 240r/m
  205.         //                TL0=(65536-312)%256;
  206.         //                break;
  207.                 case 3:
  208.                         TH0=(65536-200)/256;//根據調整n的數值,n為200時,速度較快且可正常運行,n為150時啟動不正常(n=150時,頻率為3.33KHz,可能這個頻率對于起步太快了)
  209.                         TL0=(65536-200)%256; //n為200 頻率為2.5KHz     400脈沖/圈時轉速為 375r/m
  210.                         break;
  211.           //case 1:
  212.                 //        TH0=(65536-175)/256; //n=175 頻率為2.86KHz           400脈沖/圈時轉速為 430r/m
  213.                 //        TL0=(65536-175)%256;
  214.                 //        break;
  215.         //        case 4:
  216.         //                TH0=(65536-150)/256;  //n=150 頻率為3.33KHz           400脈沖/圈時轉速為 500r/m
  217.         //                TL0=(65536-150)%256;
  218.         //                break;
  219.                 case 4:                                                                                          
  220.                         TH0=(65536-125)/256; //n=125 頻率為4KHz                   400脈沖/圈時轉速為 600r/m
  221.                         TL0=(65536-125)%256;
  222.                         break;
  223.                 case 5:
  224.                         TH0=(65536-100)/256; //n=100 頻率為5KHz                  400脈沖/圈時轉速為 750r/m
  225.                         TL0=(65536-100)%256;
  226.                         break;
  227.                 case 6:
  228.                         TH0=(65536-75)/256;         //n=75 頻率為6.67KHz         400脈沖/圈時轉速為 1000r/m
  229.                         TL0=(65536-75)%256;
  230.                         break;
  231.                 case 7:
  232.                         TH0=(65536-50)/256;         //n=50 頻率為10KHz                 400脈沖/圈時轉速為 1500r/m
  233.                         TL0=(65536-50)%256;
  234.                         break;
  235.         }
  236. //        REN=0;//禁止串口接收數據
  237.         ES=0;
  238.         pul=~pul;   //進入中斷后,開始高低電平變換以產生脈沖
  239.         r++;
  240.         if(r==(sum*2))
  241.         {
  242.                 pul=1;
  243.                 TR0=0;
  244.                 r=0;
  245.                 n=0;   //0檔最慢速度
  246.                 forward=0;
  247.                 backward=0;
  248.         //        REN=1;
  249.                 ES=1;
  250.         }
  251.         if(limita==0||limitb==0)  //如果起始方向極限或遠端極限被觸發,pul輸出高電平,停止轉動并關閉定時器0
  252.         {        
  253.                 pul=1;
  254.                 TR0=0;
  255.                 n=0;   //0檔最慢速度
  256.                 forward=0;
  257.                 backward=0;
  258.         //        REN=1;
  259.                 ES=1;        
  260.         }
  261. }


  262. void ser()interrupt 4                   //串口中斷子程序
  263. {                 
  264.         RI=0;
  265.     rectable[j++]=SBUF;     //存數據到接收緩存
  266.         if(rectable[0]!=0x23)         //幀頭驗證
  267.         {
  268.                 flag=2;
  269.         }
  270.     if(j==N)              //數組滿時,驗證幀尾再把flag置相應數值
  271.         {         
  272.                 if(rectable[7]!=0x2a)        //幀尾驗證
  273.                 {
  274.                         flag=3;
  275.                 }
  276.                 else
  277.                 {
  278.                     flag=1;
  279.             }
  280.         }
  281. }


  282. void main()
  283. {
  284.         P0=0;                                                                        
  285.         dula=1;
  286.         dula=0;
  287.         P0=0xc0;
  288.         wela=1;
  289.         wela=0;
  290.         rs232_init();     //串口通信初始化設置
  291.         while(1)
  292.         {        
  293.                 serial_com();
  294.                 serial_control();

  295.          }               
  296. }
復制代碼

回復

使用道具 舉報

ID:451441 發表于 2019-9-11 11:55 | 顯示全部樓層
根據我的試驗,問題是在void serial_control()這個函數相關的地方,因為在主程序中如果屏蔽掉這個子程序,就可以實現連續正確接收。但我分析不出來這個子程序的問題在哪了,特在此求助。
回復

使用道具 舉報

ID:123289 發表于 2019-9-11 22:17 | 顯示全部樓層
經驗不足,
1、排除電機的電磁干擾。
2、排除程序的錯誤。
慢慢找吧。
回復

使用道具 舉報

ID:451441 發表于 2019-9-12 08:25 | 顯示全部樓層
我找到原因了,因為在主函數中我先進行串口通信接收串口助手的脈沖數信息時,TMOD設定的時定時器1的工作方式,然后在驅動步進電機是TMOD是設定定時器0的工作方式,所以在后續接收串口通信時就無法正常接受了。而修改也很簡單,在269行下面加一行代碼   rs232_init();    就可以實現后續的正常接收了。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲一区二区三区四区五区午夜 | 特级毛片爽www免费版 | 国产精品免费一区二区三区四区 | 亚洲三区视频 | 中文字幕第一页在线 | 国内自拍第一页 | 91色视频在线观看 | 欧美不卡视频一区发布 | 99久久久无码国产精品 | 国产国拍亚洲精品av | 久久精品久久久久久 | 久久精品手机视频 | 国产精品九九九 | 国产精品2区 | 日韩成人在线播放 | av毛片在线播放 | 国产一区91精品张津瑜 | 中文字幕一区二区三区四区 | 国产成人av电影 | 国产亚洲一区在线 | 日韩成人高清在线 | 免费看a | 久久小视频 | 一区二区三区在线 | 欧美激情一区二区 | 国产1区 | 在线中文字幕av | 欧美日韩高清免费 | 国产免费一区二区三区最新6 | 国产午夜精品一区二区三区四区 | 亚洲一区中文 | 亚洲国产成人在线视频 | 欧美日本韩国一区二区三区 | 国产精品99免费视频 | 日日日干干干 | 国产一级片一区二区三区 | av在线免费观看网址 | 国产99视频精品免费播放照片 | 国产高清在线精品一区二区三区 | 精品国产高清一区二区三区 | 激情毛片|