一、深入了解STM32定时器原理,掌握脉宽调制pwm生成方法。
PWM(脉冲宽度调制)简介
- 定义:PWM是一种数字信号,通常用于控制电路。它在预定义的时间内以高电平(5V或3.3V)和低电平(0V)之间切换。我们通常将高电平称为1,低电平称为0。
- 主要参数:
- 占空比:PWM信号高电平时间占整个周期的百分比。如果信号始终为高电平,则占空比为100%;如果始终为低电平,则占空比为0%。
- 频率:PWM信号的频率决定了一个周期内的速度。就是一秒钟PWM有多少个周期。STM32的MDK编译器可以选择5MHZ,10MHZ,20MHZ和50MHZ。
周期T=1/频率f
假设周期T为 1s ,那么频率就是 1Hz, 高电平时间0.5s ,低电平时间0.5s ,总的占空比就是 0.5 /1 =50%。
PWM产生方式
-
普通IO口与PWM口:
- PWM端口:除了TIM6和TIM7,STM32的其他定时器都可以产生PWM输出。高级定时器(如TIM1和TIM8)甚至可以同时产生多达7路的PWM输出。
- 普通IO口:这些IO口可以用来产生PWM,但一般不推荐,因为模拟PWM的输出频率较高,可能影响其他中断处理。
- 区别:
- 尽量选用PWM口进行PWM输出,因为普通IO口的中断频率较高,可能影响控制精度。
- 普通IO也可以输出PWM,但一般用于特定场景,如开关电源等。
-
普通IO口产生PWM:
- 方法:利用定时器中断,通过周期性改变高低电平来产生PWM。
- 示例代码:
这段代码演示了如何通过定时器中断产生占空比可变的PWM信号。#include "stm32f10x.h" // ...其他初始化代码... void TIM2_IRQHandler(void) { // 计中断次数 if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { if (count % 10 < i) { ucLed = 0xff; // 高电平 } else { ucLed = 0; // 低电平 } TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } void TIM2_Init(void) { // 初始化TIM2定时器,产生0.1ms定时 // ... }
二、练习题1
使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。
首先我选择TIM2计时器,进入CubeMX进行配置
-
将debug模式改为 Serial Wire
-
RCC页面设置HSE和LSE
-
配置TIM2,选PC13管脚配置如图
7199+1 = 7200 分频,7200/72M = 7200/72000000 = 0.0001
所以经过0.0001S之后,就计数加一,再计4999+1个数,就是(4999+1)*0.0001 = 0.5S
所以定时时间就是0.5S
- 配置Clock Configuration界面
- 选择MDK5并做如下配置并生成代码
- 由于题目中要求的是小灯以2s的频率闪烁,所以在tim.c里把周期修改为2s,(19999+1)*0.0001 = 2S。
- 在main.c里重写中断回调函数
在while(1){}前进行中断使能//重写中断回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) // { HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); //PC13 } }
HAL_TIM_Base_Start_IT(&htim2); //定时器2的中断使能
- 编译下载并检查结果
三、练习题2
接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。
- 创建项目并配置好,生成项目。
这里我选的是TIM3和TIM4,配置一样。
- 编写代码
- 添加全局变量,占空比。
uint16_t pwm=0; //占空比
- 添加pwm通道
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
- 在while(1){}里添加如下代码
while (pwm< 500)
{
pwm++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwm);
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, pwm);
HAL_Delay(1);
}
while (pwm)
{
pwm--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwm);
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, pwm);
HAL_Delay(1);
}
HAL_Delay(200);
编译下载,效果如下。
调整函数周期
输出效果如下
四、观察输出波形
点击魔法棒进行配置,打开debug和逻辑分析仪,根据下面这张图添加需要观察的引脚
观察波形