一、定时器
- 在 STM32 中,定时器(Timer) 是一种硬件外设,常用于生成精确的时间延迟、测量时间间隔、PWM(脉宽调制)输出、捕获输入信号的时间、生成定时中断等。
- STM32 的定时器类型通常包括基础定时器(如 TIM6 和 TIM7)、通用定时器(如 TIM2到TIM5)、高级定时器(如TIM1和TIM8)等。
- 输入捕获
定时器可以捕获外部信号的变化并记录其发生时间,常用于测量信号的频率或周期,如脉冲计数、测速等。
- RCC(Reset and Clock Control,复位与时钟控制)是 STM32 微控制器中的一个重要模块,它负责管理和控制系统的时钟和复位功能。
- 选择时钟源:定时器的时钟源可以来自APB总线时钟或外部时钟。
- 设置预分频器(Prescaler):预分频器用于降低计数器的计数频率。通过设定预分频器值,可以让定时器的时钟频率为系统时钟的1/N,其中N为预分频值+1。
- 设定自动重装载寄存器(ARR):ARR决定了计数器从0计数到ARR的周期。定时器到达ARR值时会触发更新事件,可以通过中断响应或自动重置计数器。
- 据此2,3,可以算出多少时间产生溢出事件T = (Prescaler+1)* (Period +1)/TIMClk
设APB1 时钟(定时器 TIM5 的时钟)频率为 64 MHz,现在我们来看看为什么选择了这两个值:
Prescaler = 64000 - 1(STM32 的定时器会从 0 开始,故减1)
这个设置的意思是将 64 MHz 的时钟频率预分频 64000 次。
预分频后的定时器时钟频率为:
定时器时钟频率=64MHz/64000=1kHz
也就是说,现在定时器每秒计数 1000 次,每次计数的时间间隔为 1 毫秒。
Counter Period = 1000 - 1(定时器会从 0 计数到这个值)
计数周期设置为 1000,也就是说,定时器会从 0 计数到 999(总共 1000 个计数),然后产生一次溢出事件。
由于定时器时钟频率现在为 1 kHz,每次计数的时间间隔是 1 毫秒,因此计数 1000 次的总时间为:
1000×1ms=1秒
这意味着,定时器每经过 1 秒会产生一次溢出中断。
- 使用方法(TIM5)
1). 使用TIM5的内部时钟源。(选择通道的话,就是要有确定的GPIO配置)
2). 并设置Prescaler 为64000-1和Counter Period为1000-1
3). 在NIVC Interrupt Table中允许TIM5 global Interrupt 中断使能
4).RCC的High-Speed Clock的模式选择Crystal/Ceramic pesaonator,可以提供比内部振荡器更精确、稳定的时钟信号。
5. 并时钟配置如下图

6. 配置LED的管脚
7. 在main函数中启动定时器HAL_TIM_Base_Start_IT(&htim5);
8. 然后在HAL_TIM_PeriodElapsedCallback处理你想要做的事情。
- 代码示例
控制灯一闪一闪的
#include "main.h"
TIM_HandleTypeDef htim5;
void SystemClock_Config(void);
static void MX_TIM5_Init(void);
static void MX_GPIO_Init(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_6|GPIO_PIN_7);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_TIM5_Init();
MX_GPIO_Init();
HAL_TIM_Base_Start_IT(&htim5);
while (1)
{
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {
0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {
0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct