简体   繁体   English

stm32 PWM指令

[英]stm32 PWM command

I am a beginner in stm32 and new in this community I am trying this following program:我是 stm32 的初学者,也是这个社区的新手,我正在尝试以下程序:

-run a DC motor (using PWM command) with speed "1" and wait 5 seconds then run with speed "2" and wait for 5 seconds then the motor stops. - 以速度“1”运行直流电机(使用 PWM 命令)并等待 5 秒,然后以速度“2”运行并等待 5 秒,然后电机停止。

The problem is that the motor stays in a loop: starts turning about 1 second and stops.问题在于电机处于循环状态:开始转动约 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);

}

I am using stm32f4.我正在使用 stm32f4。

motor pin C7.电机引脚 C7。

I've configured my project with STM32CubeIDE.我已经使用 STM32CubeIDE 配置了我的项目。

Thanks for your help.谢谢你的帮助。

Separate your initialisation from the duty cycle setting.将您的初始化与占空比设置分开。 Change:改变:

sConfigOC.Pulse = puls ;

to

sConfigOC.Pulse = 0 ;

Then add a function to set the duty cycle, for example:然后添加一个function来设置占空比,例如:

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();
    }
}

The global variable puls is no longer needed.不再需要全局变量puls In fact no global variables are needed or ever a good idea;事实上,不需要全局变量,也不是一个好主意; the fact that the CubeMX generates code dependent on globals (such as htim3 in this case) is depressing, but that is a different issue - there is no need to exacerbate the problem with your own. CubeMX 生成依赖于全局变量的代码(例如本例中的htim3 )这一事实令人沮丧,但这是一个不同的问题 - 没有必要加剧您自己的问题。

The state of the output on HAL_TIM_PWM_Stop() is undefined, and coluld leave the motor on full speed. HAL_TIM_PWM_Stop()上的 output 的 state 未定义,可能会使电机全速运行。 That does not happen in your code because after stopping the loop iterates and immediately starts it again.这不会在您的代码中发生,因为在停止循环后会进行迭代并立即再次启动它。 The correct way to stop running the motor is to set the duty cycle to zero.停止运行电机的正确方法是将占空比设置为零。

Then your main() can then be simplified:然后可以简化您的main()

int main (void) { HAL_Init (); int main (void) { HAL_Init (); SystemClock_Config (); SystemClock_Config(); MX_GPIO_Init (); MX_GPIO_Init(); MX_USART2_UART_Init (); MX_USART2_UART_Init(); MX_TIM3_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 ;

} }

That may not solve all the problems with the code;这可能无法解决代码的所有问题; I am not able to test it, but I seriously doubt that your PWM frequency is high enough to correctly and stably drive the motor.我无法对其进行测试,但我严重怀疑您的 PWM 频率是否足够高以正确稳定地驱动电机。

The CubeMX code is particularly poor in this respect, and I would suggest modifying MX_TIM3_Init() as follows: CubeMX 代码在这方面特别差,我建议修改MX_TIM3_Init()如下:

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

Where PWM_FREQ is something sensible like:其中PWM_FREQ是明智的,例如:

#define PWM_FREQ 20000u

If you have precise motor data you can in theory calculate an optimal frequency, but it is usually sufficient to ensure it is not audible.如果你有精确的电机数据,理论上你可以计算出一个最佳频率,但通常足以确保它是听不见的。 Certainly not the sub-10Hz that your settings appear to use (depending on SystemCoreClock ).当然不是您的设置似乎使用的 10Hz 以下(取决于SystemCoreClock )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM