在FreeRTOS中实现sysTick延时

文章介绍了在FreeRTOS环境下,如何利用sysTick实现微秒级延时的两种方法:一是用完sysTick后归还,延时精准但会暂停系统;二是截取sysTick片段,不暂停系统但精度较低。这两种方法各有优劣,适用于不同的场景需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

在我之前做基于FreeRTOS的小车时,要用到微秒级的延时,最方便的就是用sysTick延时,发现了用sysTick系统就会卡死系统,没办法只能用软件延迟代替了。
原因是系统要用sysTick生成时间片,产生sysTick来切换任务。你用了,系统就没得用了,就会停止执行,解决方案两个,一是用sysTick是暂停系统,等sysTick用完后在归还给系统。二是在系统时间片的基础上截取要延时的时间段。


一、用完sysTick后归还

优点:延时较精准
缺点:系统被迫暂停

void Delay_us(uint32_t us)
{
	/*保存sysTick的状态*/
	uint32_t val_temp=SysTick->VAL;
	uint32_t load_temp=SysTick->LOAD;
	uint16_t ctrl_temp=SysTick->CTRL;

	/*SysTick状态重新设置,用于延时(系统暂停)*/
	SysTick->LOAD = 9 * us;		// 设置定时器重装值,72MHz 8分频后9HMz,即一微秒记9个数
	SysTick->VAL = 0x00;		// 清空当前计数值,清空后会自动装入重载值
	SysTick->CTRL = 0x00000001; // 位2设置为0,8分频,启动定时器
	while (!(SysTick->CTRL & 0x00010000));// 等待计数到0
	
	/*延时结束后恢复之前的状态,系统继续运行*/
	SysTick->LOAD = load_temp;
	SysTick->VAL = val_temp;
	SysTick->CTRL = ctrl_temp;
	//SysTick->CTRL = 0x00000000; // 关闭定时器
}

二、截取sysTick片段

优点:系统不用暂停,可以正常运行
缺点:两个时间片之间,系统运行需要时间,任务轮转执行也要时间,故不能做到精准延时
(对于这个缺点可以提高当前任务的优先级或者挂起其他的任务,保证下次轮询百分百论到该任务,如果轮到别的任务,至少一个时间片(1ms)后才能轮到该任务,对于微秒级的延时来说,这是致命的,延时完毕后恢复优先级或其他任务)

void Delay_us(uint32_t us)
{
	uint32_t val_temp=SysTick->VAL;//读取SysTick->VAL的值
	/*9MHz的时钟,所以us要乘9,如果当前时间片剩余的时间大于延时的时间*/
	if( val_temp > ( us * 9  ))    
	{
		while( SysTick -> VAL != ( val_temp - us * 9));//等待延时结束
	}else//如果当前时间片剩余的时间小于延时的时间
	{
		/*等待当前时间片计时完毕,不足的时间在下一个时间片延时*/
		while (!(SysTick->CTRL & 0x00010000));
		/*等待新的时间片把剩下的时间延迟完毕*/
		while( SysTick -> VAL != ( SysTick->LOAD - (us * 9-val_temp)));
	}
}

总结

两种方法各有优劣,第一种要暂停系统,优点是延时准确,第二种不会暂停系统,但是延时相对于第一种来说不够准确,
对于FreeRTOS中实现微秒级延时,最好的方法还是不要用和系统一样的时钟,比如说用定时器就很好。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱休息的kitty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值