基本概念
STM32中有三种定时器,高级定时器,通用定时器,基本定时器,具体如下图:
发生如下事件将产生中断/DMA
- 更新:计数器向上溢出/向下溢出,计数器初始化
- 触发事件:计数器启动、停止、初始化或者由内部/外部触发计数
- 输入捕获
- 输出比较
- 支持针对定位的增量(正交)编码器和霍尔传感器电路
- 触发事件作为外部时钟或者按周期的电流管理
计数器模式
- 向上计数:计数器从0计数到自动加载值ARR,然后重新冲0开始计数并且产生一个计数器溢出事件
- 向下计数模式:计数器从自动装入的值ARR开始向下计数到0,然后从自动装载值重新开始,并产生一个计数器向下溢出事件
- 终于对齐模式(向上/向下计数):计数器从0开始计数到自动装载值的值-1,产生一个计数器溢出事件,然后向下计数到1并产生一个计数器溢出事件,然后再从0开始重新计数
定时器中断实现步骤
- 使能定时器
__HAL_RCC_TIM3_CLK_ENABLE();
- 初始化定时器,配置ARR,PSC
HAL_TIM_Base_Init();
- 开启定时器中断
HAL_TIM_Base_Start();
HAL_TIM_Base_Start_IT();
- 设置中断优先级
HAL_NVIC_SetPriority();
HAL_NVIC_EnableIRQ();
- 编写中断服务函数
TIMx_IRQHandler();//中断服务函数
HAL_TIM_IRQHandler(); //HAL库定时器中断通用处理函数
HAL_TIM_PeriodElapsedCallback(); //定时器更新中断回调函数
具体代码
使用TIM3让LED1每500ms亮一次
- 使能定时器,我们放在第二步
- 初始化定时器,配置ARR,PSC
TIM_HandleTypeDef time_handler;
void time_init(void)
{time_handler.Instance = TIM3; //可以取TIM1-TIM14time_handler.Init.CounterMode = TIM_COUNTERMODE_UP; //计数模式,向上/下time_handler.Init.Period = 5000-1; //自动装载值,即ARR的值time_handler.Init.Prescaler = 9000-1;//预分配系数,即PSC的值 //定时时间=(Period+1)(Prescaler+1)/Tclk=90000000(9Mhz)//time_handler.Init.ClockDivision= 时钟分频因子:定时器时钟与数字滤波器分频比//time_handler.Init.RepetitionCounter= 重复计数次数:高级定时器使用HAL_TIM_Base_Init(&time_handler);
}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){__HAL_RCC_TIM3_CLK_ENABLE();HAL_NVIC_EnableIRQ(TIM3_IRQn);HAL_NVIC_SetPriority(TIM3_IRQn,3,3);HAL_TIM_Base_Start_IT(&time_handler); //开启定时器并更新中断,以后每次更新中断,都会调用TIM3_IRQHandler}}
HAL_TIM_Base_Init初始化定时器后,会调用HAL_TIM_Base_MspInit函数,我们可以在HAL_TIM_Base_MspInit中使能TIM3,HAL_TIM_Base_MspInit还开启TIM3中断以及设置中断优先级
对于Init参数
- Instance 可以取值TIM1到TIM14,表示使用哪个定时器
- CounterMode :计数模式,向上/下
- Period :自动装载值,即ARR的值
- Prescaler :预分配系数,即PSC的值
- ClockDivision: 时钟分频因子,定时器时钟与数字滤波器分频比
- RepetitionCounter:重复计数次数,高级定时器使用
定时时间=(Period+1)(Prescaler+1)/Tclk
Tclk:输入时钟频率,TIM3为90M,计算得出定时时间=0.5s
- 开启定时器中断,在步骤2中完成
- 设置中断优先级,在步骤2中完成
步骤1-4是配置TIM3定时器中断,步骤5是来处理TIM3定时器中断
- 编写中断服务函数
void TIM3_IRQHandler(void)
{HAL_TIM_IRQHandler(&time_handler); //HAL定时器中断通用函数
}//定时器通用更新中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){LED1 = !LED1;}}
当定时器TIM3时间到了时,会调用TIM3_IRQHandler函数,每个定时器都用一个中断服务处理函数,在TIM3_IRQHandler中,我们使用了HAL库定时器通用处理函数HAL_TIM_IRQHandler,HAL_TIM_IRQHandler内部会调用HAL_TIM_PeriodElapsedCallback更新回调函数,我们在HAL_TIM_PeriodElapsedCallback写逻辑处理就可以了
main函数调用time_init即可,具体代码
int main(void)
{//u8 press;HAL_Init();Stm32_Clock_Init(360,25,2,8);delay_init(180);Rcc_Init();LED_Init();KEY_Init();time_init();while(1){}}