stm32 PWM 指令

Posted

技术标签:

【中文标题】stm32 PWM 指令【英文标题】:stm32 PWM command 【发布时间】:2021-09-20 22:18:30 【问题描述】:

我是 stm32 的初学者,也是这个社区的新手 我正在尝试以下程序:

-运行 DC 电机(使用 PWM 命令)速度为“1”并等待 5 秒,然后以速度“2”运行并等待 5 秒然后电机停止。

问题是电机处于循环状态:开始转动大约 1 秒然后停止。

    #include "main.h"
    TIM_HandleTypeDef htim3;
    int puls ;
    float duty ;
    UART_HandleTypeDef huart2;
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_USART2_UART_Init(void);
    static void MX_TIM3_Init(void);
    
    int main(void)
    
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      MX_USART2_UART_Init();
      MX_TIM3_Init();
      /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start(&htim3);
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
      while (1)
      puls=150 ; // motor with speed 1
       duty =(puls*100)/31999; 
            MX_TIM3_Init();
            HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
            HAL_Delay(5000);
    
      puls=300 ; //motor with  speed  2
        duty =(puls*100)/31999;
        MX_TIM3_Init();
        HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
        HAL_Delay(5000);
        HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_2);

    
      
    
    
static void MX_TIM3_Init(void)

  TIM_ClockConfigTypeDef sClockSourceConfig = 0;
  TIM_MasterConfigTypeDef sMasterConfig = 0;
  TIM_OC_InitTypeDef sConfigOC = 0;
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 31999;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 65535;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  
    Error_Handler();
  
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  
    Error_Handler();
  
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  
    Error_Handler();
  
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  
    Error_Handler();
  
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = puls;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  
    Error_Handler();
  
  
  HAL_TIM_MspPostInit(&htim3);


我正在使用 stm32f4。

电机引脚 C7。

我已经用 STM32CubeIDE 配置了我的项目。

感谢您的帮助。

【问题讨论】:

如果不使用命令它工作正常,如你所说,那么问题是什么? 无论实际发生什么,逻辑都不正确,在停止电机后立即重新启动它;它永远不会停止。 您实际上并没有对变量 dutypuls 做任何事情,或者根本没有尝试设置占空比。此外,您为duty 分配一个整数表达式,在这两种情况下都将导致零。在这两种情况下,这些值都可以是编译时间常数。如果电机完全移动,那并不是因为这段代码以任何有意义的方式控制它。 duty的计算或者puls的值无论如何是什么意思。 PWM 信号以频率和占空比为特征,任何人都可以在这里猜测您的意图是什么。 您至少需要调用HAL_TIM_PWM_ConfigChannel() 才能设置占空比。很遗憾您选择使用 HAL 接口,它很糟糕,而且对您的作用很小。它绝不是“PWM 命令”,它只是 PWM 生成硬件的抽象接口——抽象仅足以使所有支持 STM32 PWM 的定时器看起来或多或少相似——你应该构建一个 API最重要的是。 【参考方案1】:

将您的初始化与占空比设置分开。在`

sConfigOC.Pulse = puls ;

sConfigOC.Pulse = 0 ;

然后添加一个函数来设置占空比,例如:

int setDutyCycle( unsigned duty_cycle_pecent_X10 )

    TIM_OC_InitTypeDef sConfigOC;

    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = ((htim3.Init.Period + 1) * duty_cycle_pecent_X10) / 1000 ;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

    if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
    
        Error_Handler();
    

不再需要全局变量puls。事实上no global variables 是需要的或者是一个好主意; CubeMX 生成依赖于全局变量的代码(例如在这种情况下为 htim3)这一事实令人沮丧,但这是一个不同的问题 - 没有必要加剧您自己的问题。

HAL_TIM_PWM_Stop() 上的输出状态未定义,可能会使电机处于全速状态。这不会在您的代码中发生,因为在停止循环后会迭代并立即再次启动它。停止运行电机的正确方法是将占空比设置为零。

那么你的main()就可以被简化:

int main (void) HAL_Init(); SystemClock_Config(); MX_GPIO_Init (); MX_USART2_UART_Init (); MX_TIM3_Init();

while (1)

    // Duty cycle 20% for 5 seconds
    speed_percent_x10 = 200u ;           
    setDutyCycle( speed_percent_x10 ) ;
    HAL_Delay (5000u);
    
    // Duty cycle 50% for 5 seconds
    speed_percent_x10 = 500u ;           
    setDutyCycle( speed_percent_x10 ) ;
    HAL_Delay (5000u);
    
    // Duty cycle 0% (stop) for 5 seconds
    speed_percent_x10 = 0u ;             
    setDutyCycle( speed_percent_x10 ) ;
    HAL_Delay (5000u);


return 0 ;

这可能无法解决代码的所有问题;我无法测试它,但我严重怀疑您的 PWM 频率是否足够高以正确稳定地驱动电机。

CubeMX代码在这方面特别差,建议修改MX_TIM3_Init()如下:

htim3.Init.Prescaler = 0 ;  // run at SystemCoreClock / 2 (APB1 bus clock)
htim3.Init.Period = SystemCoreClock / (2 * PWM_FREQ) ;

PWM_FREQ 的含义如下:

#define PWM_FREQ 20000u

如果您有精确的电机数据,理论上您可以计算出最佳频率,但通常足以确保它听不到。当然不是您的设置使用的低于 10Hz(取决于SystemCoreClock)。

【讨论】:

我会超过 20kHz。它可以被人听到,这对动物来说会很烦人 @0___________ :也许;电机必须共振才能被听到,它的机械结构使得在大多数情况下,通常很难在 20kHz 时将大量可听能量输入其中。 YMMV。对于低时钟速度,如果频率太高,您可能无法获得足够的 PWM 分辨率。在 60MHz 的 APB1 时钟上,重载为 3000,因此您可以转到 60kHz 并仍然保持我选择的(任意)1000 步分辨率。太高,所有功率可能会通过电机两端的电容器损失,以减少电气噪声。这通常是多种因素的权衡。

以上是关于stm32 PWM 指令的主要内容,如果未能解决你的问题,请参考以下文章

STM32单片机算法指令?

STM32学习-嵌入式微处理器指令集架构

为啥 PC 加载了包含未定义指令的地址? - STM32H745

8-STM32物联网开发WIFI+GPRS基础篇(STM32+GPRS(AT指令)实现MQTT远程通信控制)

stm32输出的pwm有啥用

stm32h750pwm有多少个