STM32
直播中

h1654155275.5748

7年用户 877经验值
私信 关注
[问答]

STM32F429输出PWM是如何实现对电机转速的控制的

PWM的工作原理是什么?

STM32F429的定时器是如何产生PWM输出的?
STM32F429输出PWM是如何实现对电机转速的控制的?

回帖(1)

徐波

2021-10-18 10:46:53
本次实验实现的是使用F429输出PWM,从而控制减速电机的速度。实验主要是通过对定时器3的通道3和通道4的配置来实现PWM的输出,并且可以通过调整占空比来实现对电机转速的控制。
  实验前准备
  本次实验需要用到的器材有:STM32F429开发板、两路减速电机、L298N电机驱动模块、杜邦线,电机及其驱动模块。
  原理介绍
  PWM工作原理
  PWM,即脉冲宽度调制(Pulse Width Modulation)的缩写,是利用微处理器的数字输出来对模拟威廉希尔官方网站 进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制, PWM 原理如下图所示:
  
  上图就是一个简单的 PWM 原理示意图。图中,我们假定定时器工作在向上计数 PWM模式,且当 CNT《CCRx 时,输出 0,当 CNT》=CCRx 时输出 1。那么就可以得到如上的 PWM示意图:当 CNT 值小于 CCRx 的时候, IO 输出低电平(0),当 CNT 值大于等于 CCRx 的时候,IO 输出高电平(1),当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。改变 CCRx的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的频率,这就是 PWM 输出的原理。
  定时器输出PWM
  STM32F429 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4 路的 PWM 输出!这里我们仅使用 TIM3 的CH3和CH4 产生两路 PWM 输出。要使 STM32F429 的通用定时器 TIMx 产生 PWM 输出,除了配置定时器的几个基本的寄存器外,还会用到 3 个寄存器,来控制 PWM 的。这三个寄存器分别是:捕获/比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4)。详细介绍参考正点原子配套资料教程:STM32F429开发指南-HAL库版本——定时器中断实验和PWM输出实验,里面有更为详细的介绍。
  程序源码
  程序改自正点原子的配套源码——实验八PWM输出实验:
  
  在该项目工程文件中,编写了两个主要的.c文件,分别是定时器中断配置文件和管脚输出文件各部分代码如下:
  timer.c文件:
  #include “timer.h”
  #include “motor.h”
  TIM_HandleTypeDef TIM3_Handler; //定时器3PWM句柄
  TIM_OC_InitTypeDef TIM3_CH3Handler;//定时器3通道3句柄
  TIM_OC_InitTypeDef TIM3_CH4Handler;//定时器3通道4句柄
  //TIM3 PWM部分初始化
  //PWM输出初始化
  //arr:自动重装值
  //psc:时钟预分频数
  void TIM3_PWM_Init(u16 arr,u16 psc)
  {
  TIM3_Handler.Instance=TIM3; //定时器3
  TIM3_Handler.Init.Prescaler=psc; //定时器分频
  TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上计数模式
  TIM3_Handler.Init.Period=arr; //自动重装载值
  TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_PWM_Init(&TIM3_Handler); //初始化PWM
  TIM3_CH3Handler.OCMode=TIM_OCMODE_PWM1; //模式选择PWM1
  TIM3_CH3Handler.Pulse=arr/2; //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为50%
  TIM3_CH3Handler.OCPolarity=TIM_OCPOLARITY_LOW; //输出比较极性为低
  HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH3Handler,TIM_CHANNEL_3);//配置TIM3通道3
  HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_3);//开启PWM通道3
  TIM3_CH4Handler.OCMode=TIM_OCMODE_PWM1; //模式选择PWM1
  TIM3_CH4Handler.Pulse=arr/2; //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为50%
  TIM3_CH4Handler.OCPolarity=TIM_OCPOLARITY_LOW; //输出比较极性为低
  HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH4Handler,TIM_CHANNEL_4);//配置TIM3通道4
  HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_4);//开启PWM通道4
  }
  //定时器底层驱动,时钟使能,引脚配置
  //此函数会被HAL_TIM_PWM_Init()调用
  //htim:定时器句柄
  void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
  {
  GPIO_InitTypeDef GPIO_Initure;
  __HAL_RCC_TIM3_CLK_ENABLE(); //使能定时器3
  __HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
  GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PB1/0
  GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
  GPIO_Initure.Pull=GPIO_PULLUP; //上拉
  GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
  GPIO_Initure.Alternate= GPIO_AF2_TIM3; //PB1复用为TIM3_CH4
  HAL_GPIO_Init(GPIOB,&GPIO_Initure);
  }
  //设置TIM通道4的占空比
  //compare:比较值
  void TIM_SetTIM3Compare3(u32 compare1)
  {
  TIM3-》CCR3=compare1;
  }
  void TIM_SetTIM3Compare4(u32 compare2)
  {
  TIM3-》CCR4=compare2;
  }
  timer.h文件:
  #ifndef __PWM_H
  #define __PWM_H
  #include “sys.h”
  extern TIM_HandleTypeDef TIM3_Handler; //定时器3PWM句柄
  extern TIM_OC_InitTypeDef TIM3_CH3Handler; //定时器3通道3句柄
  extern TIM_OC_InitTypeDef TIM3_CH4Handler; //定时器3通道4句柄
  void TIM3_Init(u16 arr,u16 psc);
  void TIM3_PWM_Init(u16 arr,u16 psc);
  void TIM_SetTIM3Compare3(u32 compare1);
  void TIM_SetTIM3Compare4(u32 compare2);
  #endif
  motor.c文件:
  #include “motor.h”
  #include “delay.h”
  void MOTOR_Init(void)
  {
  GPIO_InitTypeDef GPIO_Initure;
  __HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
  GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PB1,0
  GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
  GPIO_Initure.Pull=GPIO_PULLUP; //上拉
  GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
  HAL_GPIO_Init(GPIOB,&GPIO_Initure);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); //PB0置1
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); //PB1置1
  }
  motor.h文件:
  #ifndef _MOTOR_H
  #define _MOTOR_H
  #include “sys.h”
  #define LED0 PBout(1) //LED0
  #define LED1 PBout(0) //LED1
  void MOTOR_Init(void);
  #endif
  main.c文件:
  #include “sys.h”
  #include “delay.h”
  #include “usart.h”
  #include “motor.h”
  #include “timer.h”
  int main(void)
  {
  //u8 dir=1;
  u16 motor0pwmval=420; //具体数值(范围可取0~499)
  u16 motor1pwmval=100;//具体数值(范围可取0~499)
  HAL_Init(); //初始化HAL库
  Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
  delay_init(180); //初始化延时函数
  uart_init(115200); //初始化USART
  MOTOR_Init(); //初始化LED
  TIM3_PWM_Init(500-1,90-1); //90M/90=1M的计数频率,自动重装载为500,那么PWM频率为1M/500=2kHZ
  while(1)
  {
  delay_ms(10);
  /*if(dir)led0pwmval++; //dir==1 led0pwmval递增
  else led0pwmval--; //dir==0 led0pwmval递减
  if(led0pwmval》300)dir=0; //led0pwmval到达300后,方向为递减
  if(led0pwmval==0)dir=1; */ //led0pwmval递减到0后,方向改为递增
  TIM_SetTIM3Compare3(motor0pwmval); //修改比较值,修改占空比
  TIM_SetTIM3Compare4(motor1pwmval); //修改比较值,修改占空比
  }
  }
  至于硬件威廉希尔官方网站 连接,这里就不列出来了,要注意的是,要是驱动步进电机的话最好通过L298N去驱动,毕竟是大电流电机。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分