定时器非常常用,通过STM32CubeMX配置也非常简单,但对于刚入门的人,也许一脸懵逼
要解决的就是两个问题:
1. 定时器多少时间触发一次(中断)
2. 应用层如何开启定时器,如何编写定时执行代码
定时器多少时间触发一次?这个问题说复杂也不复杂,说简单,也有点意思
一个是clock,一个counter
clock本身跟MCU型号,自己的配置有关,还有一个分频prescaler的概念在里面
prescaler 是用来分频来自APBx的时钟频率,然后提供给定时器,作为定时器的心跳。
举个例子,我这边是这样定制时钟的:
由于定时器都是挂载在APB1 Timer clocks 或 APB2 Timer clocks
因此需要关注是APB1 APB2对应的clocks
另外,我的MCU有那么多的TIM可以用,我怎么知道该TIMx挂在哪个APB下面呢?
此时,需要打开datasheet,找到原理图:
以TIM11为例,可以看到是挂载在APB2下面,由前面的Clock Configuration 的配置,可以知道TIM11的输入频率为184MHz,请记住此值!
然后再来配置分频以及计数。以TIM11为例:
分频 Prescaler:20 含义:184MHz / (20+1) = 8MHz, 也就是说该定时器以每秒8M次脉冲触发,计数时间单位 = 1/8M = 0.125us
计数 Counter Period:99,也就是说计数到100为一个周期(即触发一次中断)
中断周期(时间)=0.125us*100=12.5us
如果还是觉得非常快,可配置 Prescaler、Counter Period 更大的值,当然也可以在应用层再计数(浪费点中断资源)
比如:Prescaler=183,Counter Period=999,此时就是1ms中断一次
对于一般应用任务1ms触发一次挺好的。
以上的值,也可以在代码里直接进行修改,关键是理解其意思。
/* USER CODE END TIM11_Init 1 */
htim11.Instance = TIM11;
htim11.Init.Prescaler = 20;
htim11.Init.CounterMode = TIM_COUNTERMODE_UP;
htim11.Init.Period = 99;
htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim11.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
2. 使用定时器,关键是实现callback
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//所有定时中断都进这里,所以要区分哪个定时器进来的
if(htim->Instance == htim11.Instance)
{
static uint16_t count = 0;
count++;
if(count > 20000)
{
//printf("tim 11 out info \r\n");
count = 0;
}
}
}
启动定时器的代码
HAL_TIM_Base_Start_IT(&htim11);
这句话也不可少,不然不会启动