STM32-笔记11-手写带操作系统的延时函数
1、为什么带操作系统的延时函数,和笔记10上的延时函数不能使用同一种?
因为笔记10的延时函数在每次调用的时候,会一直开关定时器,而在FreeRTOS操作系统中,SysTick定时器当作时基使用。
时基是一个时间显示的基本单位。时基即时间基准,在电子线路中主要用来表示数字电路中的基准时钟。
FreeRTOS的时基(Timebase)是指系统时钟的基础节拍,用于控制任务调度和定时功能。在FreeRTOS中,时基是通过系统时钟节拍(System Tick)来实现的。
2、分析滴答定时器的倒数情况
流程如下:给滴答定时器一个重装载值:reload,当滴答定时器开始计时,从重装载值开始倒数(从16777215倒数到0),然后自动重载再倒数...... ,ticks是一共需要计多少数,获取刚进入while循环时计数器时VAL的值(tnow)和进入while循环时,当前VAL的值作为told,然后,不断的累加told和tnow的差值(tcnt),不断的判断tcnt是否大于等于ticks,当是的时候,证明已达到需要的数值,故可以退出循环。
差值tcnt有三种情况
情况1、
第一次查询SysTick->VAL的值时told 和 第二次查询SysTick->VAL的值时tnow,正好在一次数数内。
情况2、
第一次查询SysTick->VAL的值时told 和 第二次查询SysTick->VAL的值时tnow,不在一次数数内。
情况3、
第一次查询SysTick->VAL的值时told 和 第二次查询SysTick->VAL的值时tnow,正好在同一个位置。(先不对其做出讨论,只把它当作条件)
流程图如下:
问题1:为什么直接给reload赋值SysTick->LOAD,SysTick->LOAD在赋值之前也没有手动赋值重装载值。原因是什么?
回答:这里利用的是SysTick的自动重载功能,没有给SysTick->LOAD(重装载数值)手动赋值就会自动的重装载初始值,重装载初始值(SysTick是24位计数器)是2^24-1(数到0停止,不是数到1停止)。即从16777215倒数到0,所以这里直接给reload赋值SysTick->LOAD。
问题2:为什么在这里不需要手动开启SysTick的使能位(ENABLE)?
回答:在这里确实没有显式地开启 SysTick 定时器的使能位。这是因为该函数的设计是基于一个前提:SysTick 定时器已经在系统的其他部分(如系统初始化或操作系统内核启动代码中)被配置并启用了。
注意:SysTick的LOAD寄存器在没有外界赋值的情况下会自动重载值。SysTick定时器是一个24位的自动重载递减计数器,当计数器从初始值(即LOAD寄存器的值)递减到0时,会自动重新装载这个初始值,并继续递减,形成一个循环。这个过程是由硬件自动完成的,不需要外界手动赋值
3、代码
实现的代码如下所示:
复制03-流水灯项目文件,在delay.c文件中重写delay_us();函数如下
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t tcnt = 0, told, tnow;
uint32_t reload = SysTick->LOAD; //重装载值
ticks = nus * 72; //需要计的节拍数
told = SysTick->VAL; //刚进入while循环时计数器的值
while(1)
{
tnow = SysTick->VAL;
if(tnow != told)
{
if(tnow < told)
tcnt += told - tnow;
else
tcnt += reload - (tnow -told);
told = tnow; //下次进入while循环时,当前VAL的值作为told
if(tcnt >= ticks) //已计的数超过/等于需要计的数时,退出循环
break;
}
}
}
4、验证实现
先点击魔术棒
配置完记得点击确定
运行程序,连接好开发板
对比两张图片的时间可以看出来,经历了0.5s也就是500ms
证明以上实验完成