目的
有些情况下会遇到单片机的定时器位数不够用,这时候可以使用低定时器级联的方式来处理,这里将对此做个示例说明。
基础说明
这里说的定时器级联是指一个定时器正常计数工作,然后在发生溢出时发送一个时钟信号,这个时钟信号作为另一个定时器的时钟源。这样相当前一个定时器可以表达低数据,后一个定时器可以表达高数据。
定时器之间级联是有一定限制的,不是随便哪个定时器之间都可以随便触发的。对于哪个TIM可以被哪个TIM触发,ITRx是多少可以参考芯片参考手册的 TIMx internal trigger connection (TIMx 内部触发连接) 表格:
在下面演示中将使用TIM2作为主定时器,使用TIM4作为从定时器。
关键配置与代码
除了配置生成的代码,需要手动添加的代码就几行(LL库):
int main(void)
{
LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),15, 0));
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM4_Init();
LL_TIM_EnableCounter(TIM4); // 使能TIM4开始计数(高数据)
LL_TIM_EnableCounter(TIM2); // 使能TIM2开始计数(低数据)
// TIM2设置1us计数一次,TIM2计数溢出时TIM4计数一次
uint64_t pred = 0;
while (1)
{
uint64_t d; // 用于保存当前时间
uint32_t du = LL_TIM_GetCounter(TIM4); // 读取时间高数据
uint32_t dl = LL_TIM_GetCounter(TIM2); // 读取时间低数据
if (du == LL_TIM_GetCounter(TIM4)) // 和前次读取高数据相同, 表明低数据并未发生溢出
{
d = ((uint64_t)du * 4096) + dl;
}
else // 和前次读取高数据不同, 表明低数据发生溢出
{
d = ((uint64_t)LL_TIM_GetCounter(TIM4) * 4096) + LL_TIM_GetCounter(TIM2);
}
// 每1000us翻转一次IO输出用作验证
if ((d - pred) > 1000)
{
pred = d; // 保存当前时间
LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_4); // 翻转IO口
}
}
}
示例链接
仓库地址: https://github.com/NaisuXu/STM32_MCU_Examples
本示例为仓库中 TIM_Concatenation_LL_H750
。