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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10138|回復: 11
打印 上一主題 下一主題
收起左側

L298N+51單片機串口、按鍵控制直流電機,PID速度閉環控制程序,串口和數碼管顯示

  [復制鏈接]
跳轉到指定樓層
樓主
這是樓主的課程作業,代碼寫的可能有點亂,見諒見諒。
可能后面串口部分代碼注釋不是很多,趕時間,沒辦法
移植注意了,我用的是12Mhz的晶振,1200波特率
數碼管用了IO擴展芯片,所以看代碼時注意

直流電機速度閉環控制實驗
.實物圖
1.1 補充材料清單
序號
材料名稱
1
51單片機開發板
(帶數碼管和矩陣鍵盤)
2
12V直流減速電機
3
12V電池
4
L298N電機驅動模塊
  • 系統電路連接示意圖
  • 實驗原理及配置
1)原理:直流減速電機尾部為霍爾測速傳感器,每轉一圈,產生兩個脈沖,單片機外部中斷計數,在用定時器得到準確的時間,可以計算出電機轉速和位置。
2用讀取脈沖的單片機資源配置如下

  • 速度和角度解算
每500ms讀取一次速度,由于電機每一轉產生兩個脈沖,因此500ms的計數可以近似看作每一秒鐘轉過的圈數。
分正反轉累加或累減,可以得到電機的位置。
  • 實驗數據記錄
用Keil C編寫程序,串口調試助手控制和顯示電機狀態,如下圖


單片機源程序如下:
  1. /************************************
  2. 在基礎版上增加了串口控制功能
  3. 計數方式由計數器變為外部中斷0,編碼器輸出口接P32
  4. 波特率為1200,晶振為12Mhz      移植需注意

  5. 串口控制命令
  6. #start#                    啟動
  7. #stop#                    停止
  8. #foreward#             正轉
  9. #back#                    反轉
  10. #speed up-N#        占空比增加N%
  11. #speed down-N#   占空比減少N%
  12. #pwm-N#               占空比調到N%

  13. ***************************************/

  14. #include "reg52.h"               //此文件中定義了單片機的一些特殊功能寄存器
  15. #include "stdio.h"                                 //printf頭文件
  16. #include "string.h"                                 //字符串處理  頭文件

  17. #define T0_time 1000             //計時器T0時間   單位us      晶振12MHz
  18. #define Total_PWM 100                         //占空比可以100級調整
  19. #define GPIO_KEY P1              //矩陣鍵盤

  20. typedef unsigned char u8;
  21. typedef unsigned int  u16;

  22. sbit Int1=P2^0;
  23. sbit Int2=P2^1;

  24. sbit LSA=P2^2;
  25. sbit LSB=P2^3;
  26. sbit LSC=P2^4;

  27. int SetPoint=0;          //目標速度
  28. double Proportion=0.32;  //比例常數
  29. double Integral=0.15;     //積分常數
  30. double Derlvative=0.12;   //微分常數
  31. int LastError;                //Error[-1]
  32. int PrevError;      //Error[-2]
  33. int Pid_flag=0;

  34. long angle=0;                 //記錄角度
  35. int  i=0,j=0,Data=0,flag=1;         //用于串口接受數據,不得用于其他地方,flag用于區分接收指令1還是數據0
  36. char ReceiveData,Command[15];   //command接收指令
  37. char code Command_Choose[][20]={"start","stop","foreward","back","speed up","speed down","pwm","pid"};
  38.         
  39. int PWM_TIME_H=0,PWM=0;                  //用于控制占空比,高電平比例,最大為100
  40. u16 count=0,int_time=0,speed=0;               //count計脈沖數,int_time多少時間讀取一次脈沖數
  41. u8 key=0,gear=0,speed_show_time=0;                                                //key表示被按下的按鍵,gear=1正轉,2反轉        .0停止           speed_show_time用于顯示數碼管
  42. u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  43.                                         0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//顯示0~F的值
  44. u8 code smgduan_direction[3]={0x00,0x00,0x40};


  45. void delay(unsigned int z);                    //延時函數
  46. void speed_out();      //數碼管速度顯示
  47. void Init(void);                //初始化定時器T0,計數器T1
  48. void Motor();                //電機驅動
  49. void KeyDown(void);                                //檢測按鍵
  50. int PID(int NextPoint);                         //增量式PID算法
  51. void ChooseFunction(void);                 //執行按鍵對應的功能



  52. void main()
  53. {        
  54.         Init();

  55.         while(1)
  56.         {
  57.                 if(gear)
  58.                 {
  59.                         if(gear==1)
  60.                               printf("PWM=%d%%, Speed=%dn/s",PWM_TIME_H,speed);
  61.                         if(gear==2)
  62.                               printf("PWM=%d%%, Speed=-%dn/s",PWM_TIME_H,speed);
  63.                         
  64.                         if(Pid_flag||key>=5&&key<=8)                 //如果處于pid模式
  65.                                 printf(", PID=%d",SetPoint);

  66.                                                                                  //角度讀取
  67.                                 printf(", angle=180*%ld\n",angle);

  68.                 }
  69.                 else
  70.                       printf("PWM=%d%%, Waiting to start\n",PWM_TIME_H);
  71.                 KeyDown();                                  //按鍵        
  72.         }               
  73. }

  74. int PID(int NextPoint)
  75. {
  76.         int iError,PID;                                         //當前誤差和反饋量
  77.         iError = SetPoint-NextPoint;         //計算當前誤差
  78.         PID = Proportion*iError                         //E[K]
  79.                 + Integral*LastError                 //E[K-1]
  80.                 + Derlvative*PrevError;                 //E[K-2]
  81.                                                                         
  82.         PrevError = LastError;                        //存儲誤差
  83.         LastError = iError;
  84.         return PID;
  85. }


  86. void uart_receiver(void) interrupt 4 //串口中斷
  87. {
  88.     if(RI)  // 判斷是串口接收產生中斷
  89.     {
  90.         RI = 0;       // 清接收中斷標志
  91.         ReceiveData = SBUF;  // 接收到的數據寫入緩沖BUF

  92.                 if(flag)          Command[i++]= ReceiveData;                        //保存到字符組
  93.                 if(flag==0 && ReceiveData != '#')        
  94.                         Data=Data*10 + (int)ReceiveData-48;        //計算出數值
  95.                  
  96.                 if(ReceiveData == '-')        
  97.                         Data=0,flag=0,Command[i-1]='\0';        //準備開始接收數據
  98.                
  99.                 if(ReceiveData == '#')                                                         
  100.                  {        Command[i-1]='\0',i=0,flag=1;           //接收數據完成,i清零,準備下次接收
  101.                         Pid_flag=0,key=0;                                            //每次先關閉pid調速
  102.                         for(j=0;j<10;j++)
  103.                         {
  104.                                 if(strcmp(Command,Command_Choose[j])==0)
  105.                                 {
  106.                                         switch(j)                                   //每個按鍵對應相應的功能
  107.                                         {
  108.                                         case(0):                                                        //開始               
  109.                                                 gear=1;break;
  110.                                         case(1):                                                        //停止   
  111.                                                 gear=0;break;
  112.                                         case(2):                                                         //正轉
  113.                                                 gear=1;break;
  114.                                         case(3):                                                         //反轉
  115.                                                 gear=2;break;
  116.                                         case(4):                                                          //加速
  117.                                                 PWM_TIME_H+=Data;
  118.                                                 if(PWM_TIME_H>Total_PWM)   PWM_TIME_H=Total_PWM;
  119.                                                 break;
  120.                                         case(5):                                                           //減速
  121.                                                 PWM_TIME_H-=Data;
  122.                                                 if(PWM_TIME_H<0)   PWM_TIME_H=0;
  123.                                                 break;
  124.                                         case(6):                                                           //pwm
  125.                                                 if(Data>100)   PWM_TIME_H=100;
  126.                                                 else                    PWM_TIME_H=Data;
  127.                                                 break;
  128.                                         case(7):                                                                   //PID目標速度
  129.                                                 if(Data>70)    SetPoint=70;
  130.                                                 else                    SetPoint=Data;
  131.                                                 Pid_flag=1;
  132.                                                 break;
  133.                                         }
  134.                                 }        
  135.                         }
  136.                 }
  137.         }
  138. }


  139. void Count_EX0(void) interrupt 0        //外部中斷0的中斷函數
  140. {
  141.                    count++;                                        //脈沖計數
  142. }


  143. void timer0(void) interrupt 1                //定時器T0的中斷函數
  144. {
  145.   TH0=(65536-T0_time)/256;                //TH0=(2^16-t)/256          晶振12MHZ   t單位us           
  146.   TL0=(65536-T0_time)/256;                //TL0=(2^16-t)%256          晶振12MHZ   t單位us
  147.   
  148.   PWM++;
  149.   if(PWM==Total_PWM)  PWM=0;
  150.   
  151.   int_time++;
  152.   if(int_time==500)                            //每500次(500ms)T0中斷,測速一次
  153.   {
  154.           int_time=0;                     //重新賦值0
  155.         speed=count;                                //讀取速度

  156.         if(gear==1)
  157.         angle+=count;                                //讀取角度正轉+
  158.         if(gear==2)
  159.         angle-=count;                                //反轉-

  160.         count=0;                                    //計數清零
  161.   /******PID***********/
  162.         if(key>=5&&key<=8||Pid_flag)
  163.                 if((speed-SetPoint>1) || (speed-SetPoint<-1))
  164.                     {
  165.                         PWM_TIME_H+=PID(speed);
  166.                           if(PWM_TIME_H>Total_PWM) PWM_TIME_H=Total_PWM;
  167.                  }
  168. /*************************/
  169.   }
  170.   Motor();
  171.   speed_out();

  172. }

  173. void ChooseFunction(void)
  174. {
  175.         Pid_flag=0;                                            //每次先關閉pid調速
  176.         switch(key)                                   //每個按鍵對應相應的功能
  177.         {
  178.         case(1):                                                        //選擇正反轉,1正轉,2反轉
  179.                 if(gear==1)             gear=2;
  180.                 else if(gear==2)        gear=1;
  181.                 else gear=0;
  182.                 break;
  183.         case(2):                                                        //加占空比   
  184.                 PWM_TIME_H+=10;
  185.                 if(PWM_TIME_H>Total_PWM)  PWM_TIME_H=Total_PWM;
  186.                 break;
  187.         case(3):                                                         //減占空比
  188.                 PWM_TIME_H-=10;
  189.                 if(PWM_TIME_H<0)  PWM_TIME_H=0;
  190.                 break;
  191.         case(4):                                                         //開關
  192.                 if(gear==1||gear==2)        gear=0;
  193.                 else                                        gear=1;
  194.                 break;
  195.         case(5):                                                          //PID目標速度40
  196.                 SetPoint=40;
  197.                 break;
  198.         case(6):                                                           //PID目標速度50
  199.                 SetPoint=50;
  200.                 break;
  201.         case(7):                                                           //PID目標速度60
  202.                 SetPoint=60;
  203.                 break;
  204.         case(8):                                                                   //PID目標速度70
  205.                 SetPoint=70;
  206.                 break;
  207.         }
  208. }


  209. void KeyDown(void)
  210. {
  211.         char a=0;
  212.         GPIO_KEY=0x0f;
  213.         if(GPIO_KEY!=0x0f)//讀取按鍵是否按下
  214.         {
  215.                 delay(100);//延時1ms進行消抖
  216.                 if(GPIO_KEY!=0x0f)//再次檢測鍵盤是否按下
  217.                 {        
  218.                         //測試列
  219.                         GPIO_KEY=0X0F;
  220.                         switch(GPIO_KEY)
  221.                         {
  222.                                 case(0X07):        key=1;break;
  223.                                 case(0X0b):        key=2;break;
  224.                                 case(0X0d): key=3;break;
  225.                                 case(0X0e):        key=4;break;
  226.                         }
  227.                         //測試行
  228.                         GPIO_KEY=0XF0;
  229.                         switch(GPIO_KEY)
  230.                         {
  231.                                 case(0X70):        key=key;break;
  232.                                 case(0Xb0):        key=key+4;break;
  233.                                 case(0Xd0): key=key+8;break;
  234.                                 case(0Xe0):        key=key+12;break;
  235.                         }
  236.                         if(key==16) key=0;
  237.                         ChooseFunction();
  238.                         while((a<50)&&(GPIO_KEY!=0xf0))         //檢測按鍵松手檢測
  239.                         {
  240.                                 delay(100);
  241.                                 a++;
  242.                         }
  243.                 }         
  244.         }

  245. }


  246. void speed_out()//數碼管顯示速度與檔位
  247. {        
  248.         u8 speed_3=speed%1000/100;                //速度百位數字
  249.         u8 speed_2=speed%100/10;                //速度十位數字
  250.         u8 speed_1=speed%10;                         //速度個位數字

  251.         u8 PWM_TIME_H_2=PWM_TIME_H/10;                         //檔位十位數字
  252.         u8 PWM_TIME_H_1=PWM_TIME_H%10;                         //檔位個位數字
  253.         
  254.         speed_show_time++;
  255.         if(speed_show_time==7)
  256.                 speed_show_time=0;
  257.         P0=0x00;                          //消影
  258.         switch(speed_show_time)
  259.         {
  260.         case(0):
  261.                 LSA=0;LSB=0;LSC=0;
  262.                 P0=smgduan[speed_1];
  263.                 break;
  264.         case(1):                                                           
  265.                 LSA=1;LSB=0;LSC=0;
  266.                 P0=smgduan[speed_2];
  267.                 break;
  268.         case(2):
  269.                 LSA=0;LSB=1;LSC=0;
  270.                 P0=smgduan[speed_3];
  271.                 break;
  272.         case(3):
  273.                 LSA=0;LSB=0;LSC=1;
  274.                 P0=smgduan[PWM_TIME_H_1];
  275.                 break;
  276.         case(4):
  277.                 LSA=1;LSB=0;LSC=1;
  278.                 P0=smgduan[PWM_TIME_H_2];
  279.                 break;
  280.         case(5):
  281.                 LSA=0;LSB=1;LSC=1;
  282.                 P0=smgduan_direction[gear];
  283.                 break;
  284.         case(6):
  285.                 LSA=1;LSB=1;LSC=1;
  286.                 P0=smgduan[key];
  287.                 break;        
  288.         }
  289. }

  290. void Motor(void)           //電機驅動
  291. {         switch(gear)
  292.          {
  293.          case(0):                 //電機停止
  294.                 Int2=Int1=0;
  295.                 break;

  296.          case(1):                        //電機正轉
  297. ……………………

  298. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
程序源代碼.zip (2.29 MB, 下載次數: 212)



評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏8 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:454653 發表于 2018-12-26 19:42 | 只看該作者
感覺不錯
回復

使用道具 舉報

板凳
ID:462570 發表于 2019-7-5 11:50 | 只看該作者
前來學習一波。
回復

使用道具 舉報

地板
ID:578419 發表于 2019-7-5 12:42 | 只看該作者
強如大佬,表示好多地方看不懂,好高深的樣子
回復

使用道具 舉報

5#
ID:462570 發表于 2019-7-6 11:14 | 只看該作者
我仔細看了一下代碼,發現里面錯誤很多,比如高級版 timer0中斷函數里TL0的賦值就是不對的。還有基礎版里面的問題就更多了,感覺牛頭不對馬嘴,貌似是硬湊出來的代碼。我不知道樓主代碼是否實際運行過,抑或這是樓主修改后(刻意)再發出來的代碼。 如果是這樣,那真是在坑人了。   不過這段代碼可以借鑒,還是感謝樓主的分享。
回復

使用道具 舉報

6#
ID:421308 發表于 2019-7-22 18:57 | 只看該作者
好多都看不懂啊
回復

使用道具 舉報

7#
ID:645875 發表于 2019-11-26 16:34
時隔一年,變成了我的課程設計

8#
ID:436394 發表于 2019-12-21 20:52 | 只看該作者
覺得很棒
回復

使用道具 舉報

9#
ID:671899 發表于 2019-12-23 23:23 | 只看該作者
感謝分享,對我的課程設計很有幫助
回復

使用道具 舉報

10#
ID:298008 發表于 2020-2-17 19:13 | 只看該作者
謝謝樓主分享!!!
回復

使用道具 舉報

11#
ID:110278 發表于 2020-4-7 14:51 | 只看該作者
感謝分享
回復

使用道具 舉報

12#
ID:803822 發表于 2022-4-20 20:56 | 只看該作者
請問有沒有電路仿真圖哇
回復

使用道具 舉報

13#
ID:228452 發表于 2022-4-20 23:34 | 只看該作者
"DC Motor Speed ​​Closed-loop"
What about position closed loop ?
Thanks for code...
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 午夜爱爱网 | 久久久精品亚洲 | 自拍偷拍第一页 | 黄色网址大全在线观看 | 日韩在线免费 | 激情五月婷婷 | 国产精品欧美日韩 | 亚洲欧美日韩在线不卡 | 一区中文字幕 | a级在线免费 | 亚洲国产欧美一区 | 久久小视频 | 亚洲精彩视频在线观看 | 久夜精品| 国产资源一区二区三区 | 国产一级在线观看 | 91av视频在线| 农夫在线精品视频免费观看 | 天堂男人av| 国产免费一区二区三区网站免费 | 久久男人| 成人午夜激情 | 精品不卡| 欧美一级欧美一级在线播放 | 亚洲精品在线视频 | 久久久久久99 | 精品久久99 | 国产视频一区二区 | 午夜精品久久 | 欧美激情国产精品 | 亚洲综合在线视频 | 国产91丝袜在线播放 | 欧美成人在线影院 | 国产精品一区二区三区四区五区 | 久久一二区 | 久久久久久久一区 | 亚洲精品乱码久久久久久按摩观 | 成人一区二区三区在线观看 | a级网站 | 国产精品一区二区久久精品爱微奶 | 国产午夜精品久久久久免费视高清 |