文章目录
一、 任务
-
使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。
-
接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。
二、 原理
STM32-PWM介绍
STM32-PWM是STM32系列微控制器上的一种重要外设,用于生成脉宽调制(PWM)信号。脉宽调制技术在许多应用中都起着关键作用,如电机控制、LED亮度调节、音频处理等。STM32PWM模块提供了灵活的配置选项和高精度的PWM输出能力。
PWM工作原理
PWM是一种周期性的方波信号,通过调整方波的高电平时间(占空比)来控制输出信号的特性。PWM信号的频率和占空比可以根据应用需求进行配置。在STM32PWM模块中,通过设置定时器的计数周期和比较值,可以实现不同频率和占空比的PWM输出。
STM32PWM模块
STM32PWM模块通常由一个或多个通用定时器(TIM)和相关的GPIO引脚组成。通用定时器提供了灵活的PWM配置选项,可以根据需要进行定时器和GPIO引脚的映射、预分频设置、计数周期和比较值的设定等。
PWM参数配置
为了配置和控制STM32PWM模块,我们可以使用相应的库函数或直接操作寄存器。以下是一些常用的PWM参数和配置选项:
- 频率设置:通过设置定时器的计数周期来控制PWM信号的频率。频率 = 定时器时钟频率 / (预分频系数 * 计数周期)
- 占空比设置:通过设置比较值来控制PWM信号的占空比。占空比 = (比较值 / 计数周期) * 100%
- 极性设置:可以选择正极性或反极性,以控制PWM信号的电平极性。
- 中断使能:可以选择是否使能PWM定时器的中断功能,用于触发中断任务。
三、 实操
1. LED以2s的频率周期性地亮-灭
Ⅰ 创建工程
选择一个载有TIM2的管脚,此处选择A6
在RCC栏选择:
在SYS栏选择:
在TIM3勾选:
并在按下图进行配置:
原理:
PWM频率:
Fpwm =Tclk / ((arr+1)*(psc+1))(单位:Hz)
arr 是计数器值
psc 是预分频值
占空比:
duty circle = TIM3->CCR1 / arr(单位:%)
TIM3->CCR1 用户设定值
比如 定时器频率Tclk = 72Mhz arr=499 psc=71 那么PWM频率就是720000/500/72= 2000Hz,即2KHz
arr=499,TIM3->CCR1=250 则pwm的占空比为50%
改CCR1可以修改占空比,修改arr可以修改频率
在NVIC里面选择TIM中断:
转到PROJECT MANAGER,勾选:
选择编译器
点击右上角GENERATE CODE生成项目
Ⅱ 编程
在 /* USER CODE BEGIN 2 */启动定时器和中断
// 启动 PWM 和定时器
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
// 启动定时器并启用中断
HAL_TIM_Base_Start_IT(&htim3);
重写中断:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM3) {
static int toggle = 0;
if (toggle == 0) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
toggle = 1;
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
toggle = 0;
}
}
}
Ⅲ 编译烧录
2. 渐亮渐灭呼吸灯
Ⅰ 创建项目
同上
Ⅱ 编程
在 /* USER CODE BEGIN 1 */里添加变量声明:
uint16_t pwmVal=0;
uint8_t dir=1;
在 /* USER CODE BEGIN 2*/里开启时钟
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
在 /* USER CODE BEGIN 3 */里 添加:
while (pwmVal< 500)
{
pwmVal++;
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, pwmVal);
HAL_Delay(1);
}
while (pwmVal)
{
pwmVal--;
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, pwmVal);
HAL_Delay(1);
}
HAL_Delay(200);
Ⅲ 编译烧录
3. 获取pwm周期和带宽由串口发送
Ⅰ 创建项目
在前面创建的基础上,增加关于串口通信的设置,按顺序勾选:
将用于获取带宽的管脚的tim设置为:
使能
将gpio设置为下降沿
点击GENERATE CODE
Ⅱ 编程
在原代码的基础上,增加中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"light\n", strlen("light\n"));
if (htim->Instance == TIM4)
{
static uint32_t captureTime = 0;
static uint32_t lastCaptureTime = 0;
uint32_t period = 0;
uint32_t pulseWidth = 0;
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
{
captureTime = HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_3);
if (captureTime > lastCaptureTime)
{
period = captureTime - lastCaptureTime;
pulseWidth = lastCaptureTime;
}
else
{
period = (0xFFFF - lastCaptureTime) + captureTime;
pulseWidth = (0xFFFF - captureTime);
}
lastCaptureTime = captureTime;
char uartMsg[50];
snprintf(uartMsg, sizeof(uartMsg), "Period: %lu, Pulse Width: %lu\r\n", (unsigned long)period, (unsigned long)pulseWidth);
HAL_UART_Transmit(&huart1, (uint8_t *)uartMsg, strlen(uartMsg), HAL_MAX_DELAY);
}
}
}
参考链接: