找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于MSP430G2553的直流电机调速测速装置源程序

[复制链接]
跳转到指定楼层
楼主
本设计基于MSP430G2553单片机,主要用了PWM输出和捕获功能,控制算法是PID.
设置二级菜单,功能一:调速功能;通过按键加减占空比调速,通过返回按键退出此功能。
                       功能二:定速功能:通过按键设置目标转速,确认按键按下后,启动电机,自动调整到目标转速,通过返回按键退出此功能。
(附件限制了大小,能上传的也就只有程序了,有相关视频去B站搜索:飞檐走壁王不羁,即可观看相关视频)


单片机源程序如下:
  1. #include <msp430G2553.h>
  2. #include "Lcd1602.h"

  3. unsigned int DUTY=1000;   //PWM占空比           (DUTY/10000)%

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

  6. uchar flag=0,disp_table[6],cap_table[10],n=0;
  7. volatile uint fre_num=0;
  8. long sum=0;
  9. uint  Redge,frequence,key=4,count=0,speed=0,yes=0,fanhui=0;
  10. uint Period[10];
  11. volatile long AvgPeriod;
  12. unsigned char distr[3];

  13. //uint Real,Target;
  14. /*------------------PID参数初始化----------------------*/
  15. float kp=0.0457,ki=0.005,kd=0.1;  //PI控制参数设置
  16. float error=0,Last_error=0,Prev_error=0;
  17. float IncremDuty;

  18. /****************************增量式PI控制函数******************************/
  19. float Incremental_PID(float Real,float Target)
  20. {
  21.     error = Target - Real;
  22.     IncremDuty = kp*(2.45*error - 3.5*Last_error + 1.25*Prev_error) ;
  23.     Prev_error = Last_error;
  24.     Last_error = error;

  25.     return IncremDuty;
  26. }

  27. /****************************************字符类型转换函数***********************************************/
  28. char int_to_char(char x)
  29. {
  30.     distr[0] = (x/10) + 0x30;
  31.     distr[1] = x%10 + 0x30;
  32.     distr[2] = '\0';
  33. }

  34. /*---------------------数字转换成字符------------------------------------------------*/
  35. void num_to_char(uint k)
  36. {
  37.     uchar i=0;

  38. //    disp_table[0] = k/10000 + 0x30;      //'0'的ASCII码0x30
  39.     disp_table[0] = k%10000/1000 + 0x30;
  40.     disp_table[1] = k%1000/100 + 0x30;
  41.     disp_table[2] = k%100/10 + 0x30;
  42.     disp_table[3] = k%10 + 0x30;
  43.     disp_table[4] = 0x20;
  44.     disp_table[5] = '\0';

  45.     for(i=0;i<4;i++)  //去掉无效的前导'0'字符
  46.     {
  47.         if(disp_table[i]==0x30)
  48.             disp_table[i] = 0x20; //0x20是空格的ASCII码
  49.         else
  50.             break;
  51.     }
  52. }

  53. void long_to_char(long k)
  54. {
  55.     uchar j=0;

  56.     cap_table[0] = k/100000000 + 0x30;      //'0'的ASCII码0x30
  57.     cap_table[1] = k%100000000/10000000 + 0x30;
  58.     cap_table[2] = k%10000000/1000000 + 0x30;
  59.     cap_table[3] = k%1000000/100000 + 0x30;
  60.     cap_table[4] = k%100000/10000 + 0x30;
  61.     cap_table[5] = k%10000/1000 + 0x30;
  62.     cap_table[6] = k%1000/100 + 0x30;
  63.     cap_table[7] = k%100/10 + 0x30;
  64.     cap_table[8] = k%10 + 0x30;
  65.     cap_table[9] = '\0';

  66.     for(j=0;j<8;j++)  //去掉无效的前导'0'字符
  67.     {
  68.         if(cap_table[j]==0x30)
  69.             cap_table[j] = 0x20; //0x20是空格的ASCII码
  70.         else
  71.             break;
  72.     }
  73. }

  74. /*****************************************系统时钟源设置******************************************************/

  75. void OSC_CLK_Init(void)
  76. {
  77.    if (CALBC1_8MHZ == 0xFF || CALDCO_8MHZ == 0xFF)
  78.    {while(1);}                      // If calibration constants erased, trap CPU!!
  79.     BCSCTL1 = CALBC1_8MHZ;          // Set range
  80.     DCOCTL = CALDCO_8MHZ;           // Set DCO step + modulation

  81.     IFG1 &= ~OFIFG;                 // Clear OSCFault flag
  82.     BCSCTL2 |= SELM_1 + DIVS_3 ;    // Set MCLK=8MHz, SMCLK/
  83. }

  84. /****************************************PWM设置函数(比较模块)**************************************************/

  85. void PWM()
  86. {
  87.     TA1CTL=TASSEL_2+MC_1+TACLR;     //(定时器A1控制寄存器 )SMCLK 1MHZ+不分频+增计数+清零
  88.     TA1CCTL2=OUTMOD_7;              //(定时器A1捕获控制寄存器2)高电平 PWM
  89.     TA1CCR0=10000-1;                //周期10000us==10ms    100HZ
  90.     TA1CCR2=DUTY;                   //高电平时间
  91. }

  92. /********************************************捕获模块寄存器设置*******************************************************/
  93. //P1.2端口设置为捕获功能,用于测量信号频率 ,当捕获频率f=1MHz时
  94. //能捕获到最大信号周期为65.536ms,频率为15.26Hz(最低信号频率)
  95. void Timer_A0_1_CAP()
  96. {
  97.      TACTL   = TASSEL_2 + MC_2 + ID_3 + TACLR;  //SMCLK=1MHz/8=0.125MHz,连续计数模式,清TAR
  98.      TACCTL1 = CAP + CCIS_0 + SCS + CM_1 + CCIE;//CCISxA,开捕获,上升沿捕获,使能,同步捕获
  99. }

  100. /*******************************************GPIO设置*****************************************************/

  101. void IO_RE()
  102. {
  103.     P2DIR |=BIT4;    //pwm输出   P2.4
  104.     P2SEL |=BIT4;    //

  105.     P1DIR&=~BIT2;    //转速捕获    P1.2
  106.     P1SEL|=BIT2;     //

  107.     //查询方式
  108.     P1DIR&=~(BIT0+BIT1+BIT3+BIT4);   //四个用户按键    0加速   1减速   3加50   4减50
  109.     P1OUT|=BIT0+BIT1+BIT3+BIT4;      //输出高电平
  110.     P1REN|=BIT0+BIT1+BIT3+BIT4;      //上拉(硬件有上拉)

  111.     P1DIR|=BIT7;                     //P1.7   LED指示灯   用于调试
  112. }

  113. /**************************************按键消抖延时函数*******************************************************/

  114. void delay_Nms(unsigned int n)
  115. {
  116.     unsigned int i;
  117.     unsigned int j;
  118.     for(i = n;i > 0;i--)
  119.         for(j = 100;j > 0;j--)
  120.             _NOP();
  121. }

  122. /****************************************主函数***************************************************/
  123. void main(void)
  124. {
  125.     WDTCTL = WDTPW | WDTHOLD;  //
  126.     OSC_CLK_Init();            //SMCLK  1M
  127.     Timer_A0_1_CAP();          //定时器A
  128.     lcdinit();
  129.     IO_RE();
  130.     _EINT();                   //开总中断

  131. while(1)
  132. {
  133. /**************************************一级菜单************************************************/

  134.     if(key==4)                        //主界面
  135.     {
  136.       disp_str(1,0,"   A: MODE 1   ");
  137.       disp_str(2,0,"   B: MODE 2   ");
  138.       DUTY=1000;
  139.       PWM();
  140.     }
  141.          //功能选项一
  142.           if(!(P1IN&BIT0))
  143.                  {
  144.                    delay_Nms(10);
  145.                      if(!(P1IN&BIT0))
  146.                        {
  147.                           while(!(P1IN&BIT0));
  148.                              {
  149.                               key=1;
  150.                              }
  151.                        }
  152.                  }
  153.          //功能选项二
  154.           if(!(P1IN&BIT1))
  155.                   {
  156.                     delay_Nms(10);
  157.                       if(!(P1IN&BIT1))
  158.                         {
  159.                           while(!(P1IN&BIT1));
  160.                              {
  161.                               key=2;
  162.                              }
  163.                         }
  164.                   }
  165. /*******************************************对应功能***************************************************/
  166. switch(key)
  167. {
  168. /********************************************功能一***************************************************/
  169.     case 1:
  170.         while(1)
  171.         {
  172.         if(count==0)                    //清除主界面
  173.         {
  174.             count=1;
  175.             lcd_clr();
  176.         }


  177.                             /********************功能一主页面***********************/
  178.                                   disp_str(1,0,"DUTY=");
  179.                                   int_to_char(DUTY/100);   //占空比数值显示
  180.                                   disp_str(1,6,"   ");
  181.                                   disp_str(1,9,distr);
  182.                                   disp_str(1,11,"%   ");
  183.                                   disp_str(2,0,"n=");      //转速
  184.                                   disp_str(2,6,"r/min ");

  185.                             /*****************计算显示频率(转速)*********************/
  186.                                       if(flag==1)
  187.                                       {
  188.                                           frequence = (uint)(125000/AvgPeriod)*30;     //计算信号转速
  189.                                           num_to_char(frequence);
  190.                                           disp_str(2,2,disp_table);
  191.                                           flag = 0;
  192.                                       }

  193. /*********************************************加速按键1************************************************/
  194.         if(!(P1IN&BIT0)&&key==1)
  195.            {
  196.              delay_Nms(10);
  197.                if(!(P1IN&BIT0)&&key==1)
  198.                  {
  199.                     disp_str(1,5,"+1%");
  200.                     while(!(P1IN&BIT0)&&key==1);
  201.                        {
  202.                             P1OUT^=BIT7;
  203.                             DUTY+=100;
  204.                                if(DUTY>9000)
  205.                                   {
  206.                                       DUTY=9000;
  207.                                   }
  208.                             PWM();
  209.                             disp_str(1,5,"   ");

  210.                        }
  211.                   }
  212.             }
  213. /*********************************************减速按键2**************************************************/
  214.         if(!(P1IN&BIT1)&&key==1)
  215.            {
  216.              delay_Nms(10);
  217.                if(!(P1IN&BIT1)&&key==1)
  218.                  {
  219.                     disp_str(1,5,"-1%");
  220.                     while(!(P1IN&BIT1)&&key==1);
  221.                        {
  222.                             P1OUT^=BIT7;
  223.                             DUTY-=100;
  224.                                if(DUTY<1000)
  225.                                   {
  226.                                       DUTY=1000;
  227.                                   }
  228.                             PWM();
  229.                             disp_str(1,5,"   ");
  230.                        }
  231.                   }
  232.             }

  233. /*********************************************返回按键4*********************************************/
  234.         if(!(P1IN&BIT4))
  235.                     {
  236.                       delay_Nms(10);
  237.                         if(!(P1IN&BIT4))
  238.                           {
  239.                              while(!(P1IN&BIT4));
  240.                                 {
  241.                                   key=4;
  242.                                   break;
  243.                                 }
  244.                           }
  245.                     }
  246.         }
  247.         ;
  248.      break;


  249. /********************************************功能二******************************************/
  250.     case 2:
  251.         while(1)
  252.         {
  253.         if(count==0)                    //清除主界面
  254.         {
  255.             count=1;
  256.             lcd_clr();
  257.         }
  258.         DUTY=0;
  259.         PWM();
  260.         disp_str(1,1,"Input:");
  261.         disp_str(2,1,"speed:");
  262.         /*****************计算显示频率(转速)*********************/
  263.           if(flag==1)
  264.           {
  265.               frequence = (uint)(125000/AvgPeriod)*30;     //计算信号转速
  266.               num_to_char(frequence);
  267.               disp_str(2,7,disp_table);
  268.               flag = 0;
  269.           }

  270.           /*******************************************加按键1***********************************************/
  271.                   if(!(P1IN&BIT0)&&key==2)
  272.                      {
  273.                        delay_Nms(10);
  274.                          if(!(P1IN&BIT0)&&key==2)
  275.                            {
  276.                               while(!(P1IN&BIT0)&&key==2);
  277.                                  {
  278.                                       speed+=60;
  279.                                       if(speed>2400)  speed = 2400;
  280.                                  }
  281.                             }
  282.                       }
  283.           /*******************************************减按键2***********************************************/
  284.                           if(!(P1IN&BIT1)&&key==2)
  285.                              {
  286.                                delay_Nms(10);
  287.                                  if(!(P1IN&BIT1)&&key==2)
  288.                                    {
  289.                                       while(!(P1IN&BIT1)&&key==2);
  290.                                          {
  291.                                               speed-=60;
  292.                                               if(speed<900)   speed = 900;
  293.                                          }
  294.                                     }
  295.                               }

  296.                           num_to_char(speed);
  297.                           disp_str(1,7,disp_table);
  298.          /*********************************************确认按键3*********************************************/
  299.                           if(!(P1IN&BIT3)&&key==2)
  300.                              {
  301.                                delay_Nms(10);
  302.                                  if(!(P1IN&BIT3)&&key==2)
  303.                                    {
  304.                                       while(!(P1IN&BIT3)&&key==2);
  305.                                          {
  306.                                            yes=3;
  307.                                          }
  308.                                     }
  309.                               }
  310.                             if(yes==3)
  311.                             {
  312.                                 DUTY=900;
  313.                                 PWM();
  314.                                 while(fanhui==0) //如果没有按返回按键
  315.                                   {
  316.                                      delay_Nms(150);
  317.                                      if(flag==1) //检测当前风扇转速并显示
  318.                                        {
  319.                                          frequence = (uint)(125000/AvgPeriod)*30; //计算信号转速
  320.                                          num_to_char(frequence);
  321.                                          disp_str(2,7,disp_table);   //显示当前转速
  322.                                          flag = 0;
  323.                                        }
  324.                                        //根据设定转速进行PID调节
  325.                                      if(fabs(frequence-speed)>20)
  326.                                        {
  327.                                          DUTY = DUTY + (int)Incremental_PID(frequence,speed);
  328.                                          TA1CCR2 = DUTY;
  329.                                        }
  330.                                      if(!(P1IN&BIT4))
  331.                                        {
  332.                                         delay_Nms(10);
  333.                                           if(!(P1IN&BIT4))
  334.                                              {
  335.                                                while(!(P1IN&BIT4));
  336.                                                    {
  337.                                                      fanhui=1;
  338.                                                      break;
  339.                                                    }
  340.                                              }
  341.                                        }
  342.                                   }

  343.                                 if(!(P1IN&BIT4))
  344.                                    {
  345.                                      delay_Nms(10);
  346.                                        if(!(P1IN&BIT4))
  347.                                          {
  348.                                             while(!(P1IN&BIT4));
  349.                                                {
  350.                                                  fanhui=0;speed=0;DUTY=0;yes=0;
  351.                                                  key=4;
  352.                                                  break;
  353.                                                }
  354.                                           }
  355.                                    }


  356.                            }
  357.          /*********************************************返回按键4*********************************************/
  358.       }
  359.      break;

  360. }

  361. }
  362. }





  363. /******************************************************************
  364. * TA0.1  P1.2捕获中断
  365. * 捕获测频原理:分别记录第1次和第2次捕获到上升沿的时刻Redge1、Redge2,
  366. * 则信号周期为:Period = Redge2 - Redge1
  367. *******************************************************************/
  368. #pragma vector = TIMER0_A1_VECTOR
  369. __interrupt void TIMER0_A1_ISR(void)
  370. {
  371.        switch(TAIV)
  372.        {
  373.            case  0x02:                   //Vector 2:TACCR1 CCIFG
  374.                  if(fre_num == 0)        // 捕获上升沿信号
  375.                  {
  376.                      Redge = TACCR1;
  377.                      fre_num++;
  378.                  }
  379.                  else
  380.                  {
  381.                      _DINT();
  382.                      if(TACCR1 > Redge)  //第二次捕获上升沿
  383.                          Period[n] = TACCR1 - Redge;  //计算周期
  384.                      else
  385.                          Period[n] = 65536 + TACCR1 - Redge;

  386.                      Redge = TACCR1; //保存上次捕获值

  387.                      sum += (long)Period[n];
  388.                      n++;
  389.                      if(n==10)
  390.                      {flag=1;AvgPeriod = sum/10;n=0;sum=0;} //取10次捕获值的平均
  391.                      _EINT();
  392.                  }
  393.                  break;
  394.            case 0x0A:
  395.                     //溢出次数计数
  396.                break;

  397.            default: break;
  398.      }
  399. }
复制代码

所有资料51hei提供下载:
test speed 程序.rar (71.68 KB, 下载次数: 31)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:625113 发表于 2019-12-26 08:39 来自手机 | 只看该作者
感谢分享
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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