基于 STM32 的步进电机速度控制实例剖析

出处:网络整理 发布于:2026-05-28 15:40:33

  在电子工程领域,步进电机的应用十分广泛,尤其是在制作使用全向轮的机器人底盘时,步进电机的高精度特性显得尤为重要。因为对于全向轮而言,电机的精度是影响机器人底盘运行效果的关键因素。步进电机的一大优点是可以不使用编码器,通过开环控制就能达到高精度的效果。
  PWM(脉冲宽度调制)有两个重要参数,即周期与占空比。步进电机的运动方式是每收到一个脉冲,就旋转指定的角度,所以影响电机速度的参数就是 PWM 的频率。下面通过附图来详细说明调整占空比与调整周期的区别。

  周期固定,调整占空比

  图中有 4 个 PWM,它们的周期相同,但占空比从 80% 至 20% 不等。可以看到,无论占空比为多少,在 1s 内,它们产生的高电平数量是一样的,也就是说 PWM 的频率是一致的。因此,仅调整占空比无法调整步进电机的速度,因为步进电机的速度仅与 PWM 的频率有关。
  占空比固定,调整周期

  

  图中的 4 个 PWM 占空比都固定为 50%,但周期不同。由此可见,即使占空比固定,只要动态调整周期,PWM 就能在相同时间内产生数量不同的脉冲。所以,固定占空比,动态调整 PWM 周期,就可以达到控制步进电机速度的效果。
  基于 STM32 的实现
  在 STM32F1 中,定时器具有 PWM 模式,可用于产生 PWM。不过,STM32 的 PWM 模式在确定时基单元(即确定 PWM 周期)后,改变输出比较寄存器只能改变 PWM 的占空比。若要改变 PWM 周期,就需要不停地改变定时器的时基单元,但时基单元与硬件相关,不适合频繁变更。因此,步进电机的调速不适合使用 STM32 下定时器的 PWM 模式来控制。经过多方查找资料,确定了一种利用输出比较控制 PWM 周期的方式。
  利用输出比较产生频率可变的 PWM
  利用输出比较产生频率可变的 PWM,其原理如下:
  首先,配置定时器时基单元,确定脉冲长度单位 CK。然后,开启定时器的输出比较,设置模式为翻转模式,并开启输出比较中断。将定时器内计数器 CNT 当前值,加上脉冲长度 X(单位为 CK),写入输出比较寄存器。在 X 个 CK 后,会触发输出比较中断,同时电平翻转。在中断中再次将当前计数器 CNT 的值,加上脉冲长度 X,写入输出比较寄存器,如此往复,就可以得到一个占空比为 50%,周期为 2X 个 CK 的 PWM。
  确定单位 CK,配置时基单元
  要先确定一个的间隔 CK,规定 PWM 的高电平长度和低电平长度的单位都是 CK,即高电平的长度一定是 CK 的整数倍,低电平也是如此。然后配置定时器的时基单元,通过 CK 的长度确定预分频系数。已知 STM32F103 的主频为 72MHZ,则时基单元中预分频系数为:
  PSC = 72M / (1/CK)
  例如,若确定的 CK 长度为 10us(0.00001s),可得出方程。预分频系数确定为 720 后,由高速晶振产生的 72MHZ 的时钟信号被 720 分频,得到 100000HZ 的时钟信号,即时钟信号每秒变动 100000 次,每次 10us。同时可将重装载值设定为 0XFFFF(16 位定时器的值),因为本次使用的输出比较模式不使用更新中断,该值可随意设置。
  TIM_TimeBaseStructure.TIM_Period = 0XFFFF;
  TIM_TimeBaseStructure.TIM_Prescaler = 720;
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  开启输出比较通道,设置输出比较模式为翻转模式,并配置 NVIC,开启输出比较中断,配置输出比较通道
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  TIM_OCInitStructure.TIM_Pulse = 500;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
  TIM_OC1Init(TIM2, &TIM_OCInitStructure);
  开启输出比较中断,配置 NVIC 优先级:
  TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  编写中断服务函数
  在输出比较中断中,要做的事情就是把当前 CNT 的值取出,加上脉冲长度 X,写入输出比较寄存器。当计数器达到 0XFFFF(之前设定的重装载值)后,再加一会自动变为 0。例如,当前 CNT 值为 0XFFFF,脉冲长度为 5,很明显,输出比较寄存器应设置为 0X0004 才可触发下中断,而不是 0X10004,这样会造成溢出。因此将 CNT 的值与脉冲长度相加后,需要取 0XFFFF 的余数后,再写入输出比较寄存器。
  int t_m = 5; // 低电平和高电平的长度
  void TIM2_IRQHandler(void) {
  if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
  TIM_SetCompare1(TIM2, (TIM2->CNT + t_m) % 0XFFFF);
  TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
  }
  }
关键词:步进电机

版权与免责声明

凡本网注明“出处:维库电子市场网”的所有作品,版权均属于维库电子市场网,转载请必须注明维库电子市场网,https://www.dzsc.com,违反者本网将追究相关法律责任。

本网转载并注明自其它出处的作品,目的在于传递更多信息,并不代表本网赞同其观点或证实其内容的真实性,不承担此类作品侵权行为的直接责任及连带责任。其他媒体、网站或个人从本网转载时,必须保留本网注明的作品出处,并自负版权等法律责任。

如涉及作品内容、版权等问题,请在作品发表之日起一周内与本网联系,否则视为放弃相关权利。

ULN2003系列晶体管为步进电机做的贡献,估计西德尼·林顿看了都会说好!
广告
OEM清单文件: OEM清单文件
*公司名:
*联系人:
*手机号码:
QQ:
有效期:

扫码下载APP,
一键连接广大的电子世界。

在线人工客服

买家服务:
卖家服务:
技术客服:

0571-85317607

网站技术支持

13606545031

客服在线时间周一至周五
9:00-17:30

关注官方微信号,
第一时间获取资讯。

建议反馈

联系人:

联系方式:

按住滑块,拖拽到最右边
>>
感谢您向阿库提出的宝贵意见,您的参与是维库提升服务的动力!意见一经采纳,将有感恩红包奉上哦!