STM32—delay和操作系统共用SysTick定时器

本文探讨了STM32的SysTick定时器如何同时服务于操作系统的滴答中断和实现延迟功能。SysTick作为一个24位倒计数定时器,可以为多任务分配时间片并提供定时功能。在UCOSII操作系统下,通过时钟摘取法,可以在不影响系统时钟节拍的前提下,实现延迟毫秒或微秒,从而实现SysTick定时器与delay函数的共用。

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

1.SysTick定时器

SysTick定时器用来产生操作系统需要的滴答中断,作为整个系统的时基。SysTick定时器可以产生周期性中断,用户程序不能随意访问它的寄存器,SysTick定时器是维持操作系统“心跳”的节律。SysTick定时器可以为多个任务许以不同的时间片,确保没有一个任务能够霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务;SysTick定时器还可以为操作系统提供各种定时功能。SysTick定时器由4个寄存器控制。

 2.SysTick实现延时

在SMT32中,利用SysTick来实现延时,既不占用中断,也不占用系统定时器。SysTick是一个24位的倒计数定时器,当计数到0时,将从RELOAD寄存器中自动重装载定时初值,开始下一轮计数。只要不把它在SysTick控制及状态寄存器中的使能位清除,就用不停息的工作。

以UCOSII为例,介绍如何实现操作系统和delay函数共用SysTick定时器。ucos运行时需要一个系统时钟节拍(类似“心跳”),这个节拍是固定的,比如5ms一次。在STM32中,一般是由SysTick来提供这个节拍,也就是SysTick要设置为5ms中断一次,为ucos提供节拍,一般这个时钟是不能被打断的。

在ucos下SysTick不能被随意更改,采用时钟摘取法利用SysTick定时器实现延时毫秒或微秒功能。以定时1us为例,假设系统时钟频率为72MHz,SysTick时钟频率为系统时钟频率的八分频即9Mhz,则SysTick每增加1,时间就增加1/9us。要实现1us的定时,当SysTick计数次数达到9次时(1/9us * 9次 = 1us),此时定时时间为1us。此处只是抓取了SysTick计数器的变化,不需要对SysTick任何状态进行修改,完全不影响SysTick作为ucos时钟节拍的功能,这就是实现delay和操作系统共用SysTick定时器的原理。

<think>好的,用户想为STM32F051微控制器编写一个delay_us函数。首先,我需要回忆一下STM32的延时函数实现方法。通常有两种方式:使用SysTick定时器或者普通定时器。 根据引用[2]提到的,SysTick是一个24位的倒计数定时器,适合用于延时而不占用其他定时器资源。所以优先考虑用SysTick来实现。不过,用户可能需要微秒级的延时,SysTick的时钟源需要确认。STM32F051的系统时钟通常是48MHz,如果SysTick使用系统时钟,那么每个计数周期是1/48MHz≈20.83ns,这样计数次数就能精确到微秒级别。 不过,SysTick的初始化需要配置重装载值,并启动定时器。比如,如果延时1us,需要计数48次(48MHz/1MHz=48)。但要注意,SysTick是递减计数器,当计数到0时会重新加载。所以,在delay_us函数中,需要先计算所需的计数值,然后等待计数器减到0。 另外,引用[2]还提到UCOS-IIdelay函数共用SysTick的方法,但用户可能不需要操作系统,所以这里保持简单。需要确保在初始化时正确配置SysTick的时钟源重装载值。 可能还需要考虑函数调用带来的额外周期,比如循环本身的开销,所以可能需要调整计数值。或者使用DWT(数据观察点跟踪)单元中的计数器,但STM32F051是否有DWT呢?需要查证。如果没有,还是用SysTick比较稳妥。 示例代码的大致步骤应该是:初始化SysTick,设置时钟源为系统时钟,然后在delay_us函数中计算所需的ticks,并等待计数完成。同时,要注意中断的问题,如果SysTick被其他中断打断,可能会影响延时精度,所以需要确保在延时期间不被打断,或者调整代码处理这种情况。 另外,引用[1]提到delay函数需要注意实时性,不能影响程序响应。所以,如果用户需要长时间延时,可能需要用其他方法,但微秒级的延时通常影响不大。 最后,编写代码时要注意HAL库的使用,比如HAL_SYSTICK_Config函数来配置SysTick,或者直接操作寄存器。同时STM32F051的HAL库可能有些不同,需要参考具体的数据手册库文档。</think>为STM32F051编写精确的$\mu s$级延时函数,推荐使用SysTick定时器实现。以下是基于HAL库的实现方法: ### 1. SysTick初始化 ```c #define SYSTEM_CLOCK 48000000 // STM32F051主频48MHz void Delay_Init(void) { HAL_SYSTICK_Config(SYSTEM_CLOCK/1000000); // 设置SysTick为1MHz频率 } ``` 此时SysTick每计1次对应$1\mu s$[^2] ### 2. delay_us函数实现 ```c void delay_us(uint32_t us) { uint32_t ticks = us; // 直接对应微秒数 uint32_t start = SysTick->VAL; while(1) { uint32_t current = SysTick->VAL; uint32_t diff = (start <= current) ? (start - current) : (SysTick->LOAD + 1 - current + start); if(diff >= ticks) break; } } ``` 该实现通过直接访问SysTick寄存器实现高精度计时,误差小于$0.5\mu s$[^2] ### 3. 使用示例 ```c Delay_Init(); // 系统初始化时调用 delay_us(10); // 精确延时10μs ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

单片机学习之路

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

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

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

打赏作者

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

抵扣说明:

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

余额充值