LK 博客
关于非阻塞式延时-定时器实现非阻塞
嵌入式
约 1 分钟阅读 2 赞 0 条评论 鸿蒙黑体

关于非阻塞式延时-定时器实现非阻塞

lord Fool
lord Fool @lord Fool
累计点赞 2 登录后每个账号只能点一次
内容长度 0 正文词元数
正文
目录会跟随阅读位置移动。
阅读进度

非阻塞式延时应用广泛,当前以定时器TIM2实现非阻塞式程序为例。

TIM2定时器实现非阻塞式延时(STM32F103)

一、原理说明

非阻塞式延时的核心:用定时器中断生成时间基准,主循环通过时间戳判断是否到点,不阻塞CPU运行。

定时器实现非阻塞式是非阻塞延时的一种典型实现(但二者并不等价),接下来以定时器TIM2为例。

1.1 核心思路

  • 配置TIM2定时器,1ms产生一次中断
  • 中断中维护一个毫秒计数器 tick()
  • 主循环正常执行其他任务,延时期间CPU不空闲

1.2 定时器配置参数表

参数 配置值 说明
定时器时钟 72MHz APB1总线时钟倍频后
预分频值 (PSC) 71 72MHz / (71+1) = 1MHz
自动重装载值 (ARR) 999 1MHz / (999+1) = 1kHz → 1ms中断
中断优先级 2

1.2_ TIM2的初始化代码

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period =1000-1;
	TIM_TimeBaseInitStructure.TIM_Prescaler =72-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//ITConfig开启中断

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//优先级分配
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;
	NVIC_Init(&NVIC_InitStructure);

	TIM_Cmd(TIM2,ENABLE);
}

1.3中断函数

该中断函数应用于定时任务的执行:定时器溢出中断,用于实现周期性任务,比如定时翻转LED、生成PWM波、任务调度。

1.3_中断函数代码

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) ==SET)
	{
           /*Tick时间戳:此处放入基于Tick的定时任务,如:
           Key_Tick();
	  LED_Tick();*/
           TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

Tick时间戳说明

  • 中断内每1ms执行一次Key_Tick()/LED_Tick(),完成Tick计数累加
  • 通过Tick计数判断延时是否到达,实现非阻塞延时,彻底替代delay()死等。 比如可以在Key_Tick()中进行累计计数,每当数到20ms时会进行一次事件检测,去查看按键的状态,而相对于delay(),只是站在主程序(它)旁边,不干涉它的前进,等监测到想要的结果,就告知它,等它做完了,就退开,等待下一次的监测结果;而不是堵着主干道,一定得等到结果才允许通行,导致使用任务都被卡死。
  • 主循环全程不阻塞,可并行处理多个任务

结尾总结

在该篇中,通过定时器实现非阻塞式程序,一般需要配置定时器和中断服务函数,并且还需要通过Tick()来具体实现各个模块的周期性监测(?还有其他功能吧)

作者名片

lord Fool
lord Fool
@lord Fool

这个作者暂时还没有填写个人简介。

评论区
文章作者和管理员都可以管理这里的评论。
0 条评论
登录后即可参与评论。 去登录
还没有评论,欢迎留下第一条交流内容。