一、了解STM32定时器原理,掌握脉宽调制pwm生成方法
①TIM定时器原理
STM32的TIM(Timer)定时器是STMicroelectronics的STM32微控制器系列中用于生成精确定时的核心模块。它主要由以下几个部分组成:
- 计数器(Counter)
是一个用于计数的寄存器,可以通过自增或自减的方式来实现定时功能。STM32的TIM定时器通常使用16位计数器,最大计数值为65535(2^16-1)。 - 预分频器(Prescaler)
用于将外部时钟源进行分频,降低计数频率,以适应不同的定时要求。通过设置预分频器的值,可以控制计数器的计数速度。例如,如果外部时钟为72MHz,预分频器设置为7199,则计数器的计数频率为72MHz / (7199+1) = 10kHz。 - 自动重装载寄存器(Auto-Reload Register, ARR)
确定定时器计数的上限值。当计数器达到ARR的值时,定时器将自动重新加载预设的初始值,并继续计数。通过设置ARR的值,可以控制定时器的定时周期。
②TIM定时器分类
STM32的TIM定时器根据其功能和应用场景的不同,通常分为三种类型
- 基本定时器(TIM6、TIM7等)
主要用于简单的定时功能,如延时、PWM产生等。通常只有一个16位自动加载递增计数器和一个16位预分频器。 - 通用定时器(TIM2、TIM3、TIM4、TIM5等)
功能更为丰富,除了基本的定时功能外,还支持输入捕获、输出比较、PWM输出等功能。通常具有一个16位自动加载递增/递减计数器、一个16位预分频器和多个独立通道。 - 高级定时器(TIM1、TIM8等)
功能最为强大,除了通用定时器的所有功能外,还支持更复杂的控制功能,如死区插入、刹车信号输入等。通常用于需要高精度控制和保护的应用场景,如电机控制等。
③脉宽调制(PWM)生成方法
STM32的TIM定时器支持PWM(脉宽调制)信号的生成。PWM信号是一种模拟信号,通过改变高电平和低电平的时间比例来模拟不同的电压值。在STM32中,可以通过以下步骤来生成PWM信号
- 配置时钟源和预分频器
根据应用需求,选择合适的时钟源并设置预分频器的值,以确定PWM信号的频率。 - 设置自动重装载寄存器(ARR)
通过设置ARR的值,确定PWM信号的周期。 - 设置比较寄存器(CCR)
比较寄存器用于确定PWM信号的高电平时间。当计数器的值小于CCR的值时,PWM输出高电平;当计数器的值大于或等于CCR的值时,PWM输出低电平。通过改变CCR的值,可以控制PWM信号的占空比。 - 配置PWM输出模式和通道
根据需要选择适当的PWM输出模式(如中心对齐模式或边缘对齐模式),并配置相应的输出通道。 - 启动定时器
启动定时器后,它将根据配置的参数生成PWM信号。
二、使用定时器计数方式控制LED亮灭
使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin,连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。
1.新建HAL库工程
①新建项目 选择ACCESS TO MCU SELECTOR
②选择芯片STM32F103C8T6
③配置SYS
④配置RCC
⑤配置GPIO
⑥配置定时器2和3
配置定时器的时钟源为内部时钟;分频系数为71;向上计数模式,计数周期为5000,使能自动重载模式。
分频系数写的是71,但系统处理的时候会自动加上1,所以实际进行的是72分频。由于时钟我们一般会配置为72MHZ,所以72分频后得到1MHZ的时钟。1MHZ的时钟,计数5000次,得到时间5000/1000000=0.005秒。也就是每隔0.005秒定时器2会产生一次定时中断。
⑦配置NVIC
开启定时器2和定时器3的中断
生成定时器2和定时器3中断优先级配置代码
⑧配置USART1
选择Connectivity,点开USART1,Mode选择异步通信Asynchronous
⑨配置Clock Configuration
⑩配置Project Manager
2.KEIL代码配置
①main.c中添加启动定时器代码
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
②main.c中添加定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint32_t time_cnt =0;
static uint32_t time_cnt3 =0;
if(htim->Instance == TIM2)
{
if(++time_cnt >= 400)
{
time_cnt =0;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);
}
}
if(htim->Instance == TIM3)
{
if(++time_cnt3 >= 1000)
{
time_cnt3 =0;
HAL_UART_Transmit(&huart1,hello,20,100000);
}
}
}
③完整的main.c代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CO