目录
一、定时器与PWM介绍
1.1定时器
1.1.1定时器分类简介
1.1.2STM32定时器分类比较表
1.1.3定时器启动操作:
1.2 PWM
1.2.1 简介:
1.2.2PWM工作原理
1.2.3使用步骤:
二、定时器计数控制LED灯亮灭
2.1HAL库
2.1.1使用HAL库创建程序(熟悉HAL库使用)
编辑
2.1.2计算定时器溢出时间
2.2烧录结果:
三、PWM驱动LED呼吸灯
3.1HAL库点灯
3.2烧录结果:
四、总结
一、定时器与PWM介绍
1.1定时器
1.1.1定时器分类简介
STM32定时器种类多,功能强大,这些定时器完全独立、互不干扰,可以同步操作。
1.SysTick定时器
SysTick系统时钟位于Cortex-M3内核,是一个24位的递减计数器,主要用于:精确延时,在多任务操作系统中为系统提供时间基准(时基);任务切换,为每个任务分配时间片。
2.WatchDog看门狗
作用:当微控制器受到外部干扰或程序中出现不可预知的逻辑故障导致应用程序脱离正常的执行流程时(俗称程序跑飞),在一定的时间间隔内使系统复位,回到初始状态;
看门狗设计是用来监视MCU程序运行状态的,是确保系统可靠稳定运行的一种有效措施。
1.1.2STM32定时器分类比较表
定时器 | 基本定时器 (TIM6、TIM7) | 通用定时器 TIMx(x=2~5) | 高级定时器 (TIM1、TIM8) |
计数器类型 | 16位,向上 | 16位, 向上、 向下、 向上/向下 | 16位, 向上、 向下、 向上/向下 |
预分频系数 | 1~65535 之间的任意数 | 1~65535 之间的任意数 | 1~65535 之间的任意数 |
输入/捕获通道 | 无 | 四个独立通道:输入捕获、输出比较、 PWM生成、单脉冲模式输出 | |
产生中断/DMA | 可以 | 可以 | 可以 |
刹车(电机控制) | 无 | 无 | 可以 |
1通用定时器:
TIM2、TIM3、TIM4、TIM5为STM32的4个独立的16位通用定时器,具有定时、测量输入信号的脉冲长度(输入捕获)、输出所需波形(输出比较、产生PWM、单脉冲输出等)等功能。
2.基本定时器:
STM32有2个基本定时器TIM6和TIM7,可用作:通用的16位计数器、产生DAC触发信号基本定时器的计数模式只有向上计数模式。
3.高级定时器
高级定时器相比基本定时器、通用定时器,功能更为强大
1.1.3定时器启动操作:
操作步骤:
1.时钟配置:配置定时器使用的时钟源和时钟分频器,确保定时器的工作频率符合应用需求。
2.定时器初始化:选择并初始化所需的定时器模块,设置计数模式、PWM模式、计数方向等。
3.定时器功能配置:根据应用需求配置定时器的比较器、捕获/比较通道、PWM输出等功能。
4.中断或DMA配置:如有需要,配置定时器的中断或DMA,以便在特定事件发生时执行相应的处理程序或数据传输操作。
5.启动定时器:启动定时器开始计数或PWM输出,监控定时器的状态并根据应用需要调整参数。
1.2 PWM
1.2.1 简介:
PWM(Pulse Width Modulation,脉冲宽度调制)是一种利用脉冲宽度即占空比实现对模拟信号进行控制的技术,即是对模拟信号电平进行数字表示的方法。
广泛应用于电力电子技术中,比如PWM控制技术在逆变电路中的应用; PWM还应用于直流电机调速,如变频空调的交直流变频调速,除实现调速外,还具有节能等特性。
周期为10ms(频率为100Hz)的PWM波形
1.2.2PWM工作原理
占空比(Duty Cycle),是指在一个周期内,高电平时间占整个信号周期的百分比,即高电平时间与周期的比值,是PWM工作中的重要环节。
占空比=Tp/T
1.2.3使用步骤:
1.选择合适的PWM频率:通常选择一个高频率的PWM,以确保控制精度和减少可听见的开关噪声。
2.设定周期:确定PWM信号的周期,即脉冲的重复频率。
3.设定占空比:根据需要设定高电平(ON时间)相对于总周期的比例,这决定了输出信号的平均功率或效果。
4.应用于输出设备:将PWM信号输出到需要控制的设备,如电机驱动电路、LED控制电路或音频放大器。
二、定时器计数控制LED灯亮灭
要求:使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin,连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。
2.1HAL库
2.1.1使用HAL库创建程序(熟悉HAL库使用)
在生成代码上进行修改和配置:
HAL_TIM_Base_Start_IT(&htim2);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//这里灯亮一秒,灭一秒,则中断产生20次改变一次电平
static uint32_t time_cnt =0; //记录中断次数
if(htim->Instance == TIM2)
{
if(++time_cnt >= 20) //判断是否已经达到一秒
{
time_cnt =0; //点灯用的中断次数归零
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); //改变LED所接引脚的电平
}
}
}
2.1.2计算定时器溢出时间
2.2烧录结果:
LED闪烁
三、PWM驱动LED呼吸灯
要求:采用定时器PWM模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整占空比变化到一个满意效果,
3.1HAL库点灯
选择芯片F103C8T6
创建好文件后修改代码:
在tim.c中添加:
/* USER CODE BEGIN 1 */
#include "usart.h"
uint16_t CCR1, CCR2, CCR3;
uint8_t measure_flag = 0;
// 定时器3 捕获中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
static uint8_t measure_cnt = 1;
// 初始设置的是捕获上升沿
if (htim == &htim3)
{
// 1. 第一次发生中断肯定是上升沿
if (measure_cnt == 1)
{
// 2. 获取此时定时器计时数据
CCR1 = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1);
// 3. 将定时器设置为捕获下降沿
__HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
measure_cnt = 2;
}
// 4. 捕获到下降延
else if (measure_cnt == 2)
{
// 5. 获取此时定时器计时数据
CCR2 = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1);
// 6. 将定时器重新设置为捕获上升沿
__HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
measure_cnt = 3;
}
// 7. 再次捕获到上升沿,说明一个周期结束了。
else if (measure_cnt == 3)
{
// 8. 获取此时定时器计时的数据
CCR3 = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1);
// 9. 关闭定时器中断。
HAL_TIM_IC_Stop_IT(&htim3, TIM_CHANNEL_1);
measure_cnt = 1;
measure_flag = 1;
}
}
}
// 捕获函数
void capture(void)
{
// diff1:高电平持续时间
// diff2:一个周期的时间
uint16_t diff1 = 0, diff2 = 0;
uint32_t freq; // 频率
uint8_t duty; // 占空比
if (measure_flag)
{
measure_flag = 0;
if (CCR1 < CCR2)
diff1 = CCR2 - CCR1;
else
diff1 = 0xffff + 1 + CCR2 - CCR1; // 设置的最多能数65535,也就是0xffff + 1
if (CCR1 < CCR3)
diff2 = CCR3 - CCR1;
else
diff2 = 0xffff + 1 + CCR3 - CCR1;
// 每秒能数 1000000.一个周期是 diff2。
freq = (72000000 / 72) / diff2;
// 高电平持续时间/低电平持续时间 不让出现小数,所以*100
duty = diff1 * 100 / diff2;
}
printf("freq: %d HZ, duty: %d %% \r\n", freq, duty);
}
/* USER CODE END 1 */
主函数中:
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
while (pwmVal< 500)
{
pwmVal++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
while (pwmVal)
{
pwmVal--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
HAL_Delay(200);
}
/* USER CODE END 3 */
3.2烧录结果:
PWM呼吸灯
四、总结
本次博客主要介绍了定时器和PWM,都是非常常用的模块,在单片机的使用过程中,通过计时器和PWM完成了很多延时、点灯、舵机旋转等工作,从中学习到很多东西。本人才疏学浅,还请各位友友批评指正。我们下期再见!