找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1735|回复: 0
收起左侧

STM8单片机直流电机伺服控制设计程序

[复制链接]
ID:860145 发表于 2020-12-15 09:37 | 显示全部楼层 |阅读模式
有需要的可以直接下载
51hei.png
单片机源程序如下:
  1. //#include "iostm8s103k3.h"
  2. #include "iostm8s207r8.h"



  3. //STM8S207单片机; 连上仿真器后,ST-LINK-->Option Bytes: AFR5,右键-->Alternate Active,使PB0/PB1/PB2为PWM输出端口功能。
  4. //下载运行后,View-->Livewatch,观察PID控制参数的变化,观察LED1的亮度;
  5. //TIM2中断作为计时时间;PE0作为外中断输入;把外部频率信号与PE0连接,进行脉冲计数(频率测量)

  6. //开发板上用杜邦线把PB0与PD5连接起来;
  7. //单片机PC1(PWM输出)与焊的电路板PC1端子连接;电机编码器转速信号(黄线)与单片机PE0连接;
  8. //电机编码器供电正极(蓝线)接+5V;电机编码器供电负极(黑线)接GND;
  9. //电机本身供电正极(红线)接+12V,电机本身供电负极(白线)接焊的电路板的P1排针的第3脚(功率三极管集电极),
  10. //焊的电路板接线参考《直流电机PWM调速电路图》

  11. unsigned long   pulsecount=0;
  12. unsigned long   frequency=0;   
  13. static const unsigned int ArrPwmVal = 16000; //PWM信号周期:1ms, 1KHz
  14. int    pwmvalue=8000;                          //pwm1value取值范围0~16000;
  15. float  Kp=10,Ki=0.1,Kd=0;                      //PID参数
  16. float  set_velocity=1000.0, sample_velocity=0;
  17. float  PIDoutvalue=0;                          //PID运算输出值
  18. int    duty=0;                                 //PWM波占空比

  19. void Delay1ms(unsigned int c )                //1ms延迟函数                  
  20. {
  21.     unsigned int i;
  22.    
  23.     while(c--!=0)                             //一个while循环占用3个机器周期
  24.         for(i=0;i<3000;i++);                   //一条for循环占用4个机器周期
  25. }

  26. void InitLED(void)
  27. {
  28.     PD_DDR|=0x60;  //设置PD5、PD6为输出模式
  29.     PD_CR1|=0x60;  //设置PD5、PD6为推挽输出
  30. }


  31. //1KHZ PWM频率;//上桥臂PWM---PC1\PC2\PC3;下桥臂PWM---PB0\PB1\PB2
  32. void InitTIM1_PWM(void)  //16 位高级控制定时器(TIM1);定时器16MHz基准; 只使用了CC1P通道
  33. {
  34.                    //分频,1分频; 计数器的时钟频率(fCK_CNT)等于fCK_PSC/( PSCR[15:0]+1)
  35.     TIM1_PSCRH=0;  //预分频器高8位(TIM1_PSCRH)
  36.     TIM1_PSCRL=0;  //预分频器低8位(TIM1_PSCRL)
  37.      
  38.     TIM1_ARRH=ArrPwmVal/256;
  39.     TIM1_ARRL=ArrPwmVal%256;
  40.    
  41.     TIM1_CR1 = 0x04;   //DIR0:向上计数;URS=1:寄存器被更新时,产生更新中断
  42.     TIM1_CCMR1 = 0x60; //PWM1模式,禁止预装载
  43.    
  44.     TIM1_CCER1=0x01;   //CH1通道输出PWM使能,高电平有效

  45.     TIM1_BKR|=0x80;    //使能PWM输出 //0x80;使能OC和OCN输出;MOE: 主输出使能
  46.    
  47.            
  48.     TIM1_CR1 |= 0x01;  //使能定时计数器
  49. }


  50. void TIM2_Init(unsigned int psc,unsigned int arr)  //psc  分频系数  arr  计数值
  51. {
  52.     TIM2_CR1 = 0x00;       //向上计数   中断继续计数   关闭计数器
  53.     TIM2_IER = 0x01;       //UIE=1:允许更新中断
  54.     TIM2_PSCR = psc;       //fMASTER/2^psc;
  55.     TIM2_ARRH = arr/256;
  56.     TIM2_ARRL = arr%256;
  57.     TIM2_CR1 |=0x01;       //开始计数
  58.   
  59. }

  60. void InitEXTI(void)  //PE0作为外中断输入
  61. {                     //PEx对应EXTI4_IRQHandler
  62.     EXTI_CR2=0x02;   //PE端口下降沿触发中断
  63.     PE_DDR&=0xFE;    //PE0为输入模式
  64.     PE_CR1|=0x01;    //PE0上拉
  65.     PE_CR2|=0x01;    //PE0使能外部中断
  66. }

  67. /**************************************************************************
  68. 函数功能:位置式PID控制器
  69. 入口参数:编码器测量位置信息,目标位置
  70. 返回  值:sum
  71. 根据位置式离散PID公式
  72. pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
  73. e(k)代表本次偏差
  74. e(k-1)代表上一次的偏差  
  75. ∑e(k)代表e(k)以及之前的偏差的累积和;
  76. pwm代表输出
  77. **************************************************************************/
  78. float Position_PID (float set_value,float feedback_value)
  79. {        
  80.      static float error,sum,Integral_part,pre_error;
  81.    
  82.      error=set_value-feedback_value;                       //计算偏差
  83.      Integral_part+=error;                                       //求出偏差的积分
  84.      if(Integral_part>15000) Integral_part=15000;
  85.      if(Integral_part<0) Integral_part=0;
  86.      sum=Kp*error+Ki*Integral_part+Kd*(error-pre_error);   //位置式PID控制器
  87.      pre_error=error;                                      //保存上一次偏差
  88.    
  89.      if(sum<0)
  90.        sum=0;
  91.      
  92.      PIDoutvalue=sum;
  93.       
  94.      return sum;                                           //增量输出
  95. }



  96. void main( void )
  97. {
  98.     CLK_CKDIVR=0x00;      //HSI不分频,主时钟16M  
  99.    
  100.     InitLED();
  101.     InitTIM1_PWM();
  102.     InitEXTI();
  103.    
  104.     asm("sim");          //disable all interrupt  EA=0;
  105.     TIM2_Init(8,62499);  // 定时器2中断周期: 2^8/16M *62500=1s;  
  106.     asm("rim");          //开中断
  107.    
  108.     frequency=0;
  109.    
  110.     while(1)
  111.     {   
  112.         sample_velocity=frequency;
  113.       //  pwmvalue=(int)Position_PID(set_velocity,sample_velocity);
  114.         
  115.         if(pwmvalue<0)
  116.             pwmvalue=0;
  117.         if(pwmvalue>15900)
  118.             pwmvalue=15900;         //PWM限幅
  119.       
  120.            
  121.         TIM1_CCR1H = pwmvalue/256;  //PWM1通道占空比寄存器赋值
  122.         TIM1_CCR1L = pwmvalue%256;
  123.         
  124.         duty=pwmvalue/160;          //占空比duty=pwmvalue/16000 *100%;
  125.         
  126.         Delay1ms(10);               //转速闭环控制周期:10ms;

  127.     }

  128. }



  129. #pragma vector=0x09   // 9:  EXTI4  端口E外部中断
  130. __interrupt void EXTI4_IRQHandler(void) //PE
  131. {
  132.     pulsecount++;
  133. }

  134. #pragma vector=15
  135. __interrupt void TIM2_OVER_INT(void)
  136. {
  137.     TIM2_SR1 = 0x00;
  138.    
  139.     frequency=pulsecount;   //电机旋转1周输出6个脉冲
  140.     pulsecount=0;
  141.    
  142.     PD_ODR ^=0x60;            //PD5、PD6闪烁
  143.    
  144. }
复制代码
  1. //#include "iostm8s103k3.h"
  2. #include "iostm8s207r8.h"



  3. //207单片机; 连上仿真器后,ST-LINK-->Option Bytes: AFR5,右键-->Alternate Active,使PB0/PB1/PB2为PWM输出端口功能。
  4. //16KHZ PWM频率
  5. //上桥臂PWM---PC1\PC2\PC3
  6. //下桥臂PWM---PB0\PB1\PB2
  7. //用杜邦线把PB0与PD5连接起来;先下载程序,再连线;
  8. //下载运行后,View-->Livewatch,改变pwmvalue1的值,改变PWM1占空比,观察LED1的亮度;

  9. static const unsigned int ArrPwmVal = 1000; //PWM信号周期; 1000
  10. unsigned int pwm1value=500;


  11. void InitTIM1_PWM(void)  //16 位高级控制定时器(TIM1);1us定时器时钟基准
  12. {
  13.                    //分频,1分频; 计数器的时钟频率(fCK_CNT)等于fCK_PSC/( PSCR[15:0]+1)
  14.     TIM1_PSCRH=0;  //预分频器高8位(TIM1_PSCRH)
  15.     TIM1_PSCRL=15;  //预分频器低8位(TIM1_PSCRL)
  16.      
  17.     TIM1_ARRH=ArrPwmVal/256;
  18.     TIM1_ARRL=ArrPwmVal%256;
  19.    
  20.     TIM1_CR1 = 0x04;   //DIR0:向上计数;URS=1:寄存器被更新时,产生更新中断
  21.     TIM1_CCMR1 = 0x60; //PWM1模式,禁止预装载
  22.    
  23.     TIM1_CCER1=0x05;   //CH1、CH2通道输出PWM使能,高电平有效

  24.     TIM1_BKR|=0x80;    //使能PWM输出 //0x80;使能OC和OCN输出;MOE: 主输出使能
  25.     TIM1_DTR=16;       //死区62.5ns*16=1us
  26.    
  27.            
  28.     TIM1_CR1 |= 0x01;  //使能定时计数器
  29. }




  30. void main( void )
  31. {
  32.   
  33.   CLK_CKDIVR=0x00;//HSI不分频,主时钟16M  
  34.   InitTIM1_PWM();
  35.   
  36.   while(1)
  37.   {
  38.       TIM1_CCR1H = pwm1value/256;  //PWM1通道占空比10%
  39.       TIM1_CCR1L = pwm1value%256;     
  40.       
  41.   }

  42. }
复制代码
51hei.png
所有资料51hei提供下载:
直流电机伺服控制设计训练.zip (1.29 MB, 下载次数: 23)

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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