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 配置了我的项目。
感谢您的帮助。
【问题讨论】:
如果不使用命令它工作正常,如你所说,那么问题是什么? 无论实际发生什么,逻辑都不正确,在停止电机后立即重新启动它;它永远不会停止。 您实际上并没有对变量duty
或 puls
做任何事情,或者根本没有尝试设置占空比。此外,您为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 指令的主要内容,如果未能解决你的问题,请参考以下文章
为啥 PC 加载了包含未定义指令的地址? - STM32H745