NUCLEO-U5A5ZJ-Q开发板使用PWM(脉宽调制)功能时,可以实现对电机、LED等设备的精确控制。以下是一些关于在NUCLEO-U5A5ZJ-Q上使用PWM的测评和建议:
PWM原理:PWM是一种模拟控制技术,它利用数字信号来模拟生成一个可以变化的模拟信号。通过改变数字信号的占空比(即高电平时间占整个周期的比例),可以控制模拟信号的强度。
PWM配置:
选择PWM通道:首先,需要确定使用哪个PWM通道。NUCLEO-U5A5ZJ-Q上的STM32U5微控制器通常具有多个PWM通道,可以根据具体需求选择。
配置PWM参数:接下来,需要配置PWM的参数,如频率、占空比等。这些参数可以通过软件编程进行设置。
编写代码:使用HAL库或标准外设库中的PWM函数,编写代码来初始化PWM通道并设置参数。
PWM应用:
LED亮度控制:通过PWM控制LED的亮度。通过改变PWM信号的占空比,可以控制LED的亮度变化。
电机控制:PWM也可以用于控制电机的转速和方向。例如,对于SG90舵机,可以通过PWM信号来控制其转动的角度和速度。通常,PWM信号的占空比与舵机的角度呈线性关系。
PWM的工作模式: PWM模式1(向上计数) :计数器从0计数加到自动重装载值(TIMx_ARR),然后重新从0开始计数,并且产生一个计数器溢出事件 PWM模式2(向下计数) :计数器从自动重装载值(TIMx_ARR)减到0,然后重新从重装载值(TIMx_ARR)开始递减,并且产生一个计数器溢出事件 设置寄存器TIMx_CCMR1的OC1M[2:0]位来确定PWM的输出模式: PWM模式1:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。 PWM模式2:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
参考程序的方向:
在主程序中,编写代码来控制PWM的占空比,以实现呼吸灯效果。这通常涉及到在定时器中断服务例程中更新PWM的占空比。
为了实现呼吸效果,可以设定一个变量(如pwm_value)来表示PWM的占空比,并在每个定时器中断周期中增加或减少该变量的值。当pwm_value达到最大值或最小值时,改变增加或减少的方向。
使用HAL库中的函数(如__HAL_TIM_SET_COMPARE)来设置TIM3_CH2的占空比。
参考示例:
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
while (pwmVal< 500)
{
pwmVal++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
while (pwmVal)
{
pwmVal--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
HAL_Delay(200);
/* USER CODE END 3 */
}
详细的代码示例:
#include "stm32u5xx_hal.h"
// 假设你已经使用STM32CubeMX配置了一个PWM通道(例如TIM2_CH1)
TIM_HandleTypeDef htim2; // 假设这是你的PWM定时器句柄
uint16_t pwm_value = 0; // PWM占空比初始值
int8_t direction = 1; // 控制PWM值增加或减少的方向
// 定时器中断服务例程(ISR)
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim2);
}
// 定时器周期结束回调
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2)
{
// 更新PWM值以实现呼吸效果
pwm_value += direction;
if (pwm_value == 0 || pwm_value == htim2.Init.Period)
{
direction = -direction; // 改变方向
}
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_value); // 更新PWM通道1的占空比
}
}
// 主函数或其他初始化函数中的代码
int main(void)
{
// HAL库初始化等代码...
// 初始化PWM定时器
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
// 启动定时器中断
HAL_TIM_Base_Start_IT(&htim2);
// 主循环或其他逻辑...
// 无限循环
while (1)
{
// 你的主循环代码...
}
}
LED的简单GPIO驱动改成PWM方式的呼吸灯。
选择PC7驱动的GREEN绿色LED。
CUBE配置:
定时器3
引脚定义:
下面是自己写的代码:
// 循环,当pwmVal小于500时执行
while (pwmVal < 500)
{
// pwmVal递增
pwmVal++;
// 使用HAL库函数设置TIM3的PWM比较值,从而改变PWM占空比
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal);
// 注释掉的代码与上一行功能相同,直接操作CCR1寄存器来设置比较值
// TIM3->CCR1 = pwmVal; // 与上方相同
// 延时1毫秒
HAL_Delay(1);
}
// 循环,当pwmVal大于0时执行
while (pwmVal)
{
// pwmVal递减
pwmVal--;
// 使用HAL库函数设置TIM3的PWM比较值,从而改变PWM占空比
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal);
// 注释掉的代码与上一行功能相同,直接操作CCR1寄存器来设置比较值
// TIM3->CCR1 = pwmVal; // 与上方相同
// 延时1毫秒
HAL_Delay(1);
}
// USER CODE END 3 标志结束
/* USER CODE END 3 */
// 定义TIM_MasterConfigTypeDef结构体变量,用于TIM主从模式配置
TIM_MasterConfigTypeDef sMasterConfig = {0};
// 定义TIM_OC_InitTypeDef结构体变量,用于PWM输出通道配置
TIM_OC_InitTypeDef sConfigOC = {0};
// USER CODE BEGIN TIM3_Init 1 标志开始
/* USER CODE BEGIN TIM3_Init 1 */
// USER CODE END TIM3_Init 1 标志结束
/* USER CODE END TIM3_Init 1 */
// 初始化htim3结构体,设置TIM3的参数
htim3.Instance = TIM3;
htim3.Init.Prescaler = PRESCALER_VALUE; // 设置预分频值
htim3.Init.CounterMode = TIM_COUNTERMODE_UP; // 设置计数器模式为向上计数
htim3.Init.Period = PERIOD_VALUE; // 设置自动重装载寄存器周期的值
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 设置时钟分频因子
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 设置是否允许在运行时更改自动重载寄存器的值
// 调用HAL_TIM_PWM_Init函数初始化TIM3的PWM功能
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
// 如果初始化失败,调用错误处理函数
Error_Handler();
}
// 配置TIM3的主输出触发源和主从模式
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
// 调用HAL_TIMEx_MasterConfigSynchronization函数配置TIM3的主从同步
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
// 如果配置失败,调用错误处理函数
Error_Handler();
}
// 配置TIM3的PWM通道2
sConfigOC.OCMode = TIM_OCMODE_PWM1; // 设置PWM模式
sConfigOC.Pulse = PULSE_VALUE; // 设置PWM脉冲宽度
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 设置PWM输出极性为高
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 设置PWM快速模式为禁用
// 调用HAL_TIM_PWM_ConfigChannel函数配置TIM3的PWM通道2
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
// 如果配置失败,调用错误处理函数
Error_Handler();
}
// USER CODE BEGIN TIM3_Init 2 标志开始
/* USER CODE BEGIN TIM3_Init 2 */
// USER CODE END TIM3_Init 2 标志结束
/* USER CODE END TIM3_Init 2 */
// 调用HAL库提供的函数完成TIM3的Msp层初始化
HAL_TIM_MspPostInit(&htim3);
使用STM32 HAL库来配置TIM3的PWM输出,以及如何通过递增和递减PWM值来模拟呼吸灯效果。
逻辑分析仪采样:
总结:
功能总结
初始化:
定义了PWM占空比的初始值pwmVal为0。
定义了控制PWM值增加或减少的方向变量direction为1(表示初始时PWM值将增加)。
初始化了一个定时器(假设为TIM3),并设置了相关的参数,如预分频值、计数模式、周期值等。
配置了TIM3的中断,包括设置中断优先级和使能中断。
启动了定时器的中断功能(HAL_TIM_Base_Start_IT)和PWM通道(HAL_TIM_PWM_Start)。
定时器中断服务例程:
当TIM3的更新中断被触发时,执行TIM3_IRQHandler中断服务例程。
在中断服务例程中,首先通过HAL库函数处理TIM3的中断。
检查TIM3的更新中断标志位是否被设置。
如果更新中断标志位被设置,则清除该标志位,并更新PWM占空比的值。
更新PWM占空比时,根据direction变量的值增加或减少pwmVal的值。
当pwmVal达到预设的最大值(PERIOD_VALUE)或最小值(0)时,切换direction变量的值以改变PWM值的增减方向。
通过HAL库函数设置TIM3的通道2的比较值,从而改变PWM的占空比。
呼吸效果:
由于PWM占空比的值在最大值和最小值之间来回变化,并且变化的速率也在改变(由direction变量控制),因此连接到TIM3通道2的PWM输出将产生类似呼吸灯的效果。