RT-Thread之四种延时函数

2.5k words

在RT-Thread实时操作系统中,延时函数是实现任务调度的关键工具。它们允许任务在指定的时间间隔内挂起,释放CPU资源供其他任务运行,从而提高系统响应性和资源利用率。RT-Thread提供了四种主要的延时函数:

  • 绝对延时(精准延时)
1
rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
  • 相对延时(基于当前时间)
1
rt_err_t rt_thread_delay(rt_tick_t tick)
  • 毫秒级延时
1
rt_err_t rt_thread_mdelay(rt_int32_t ms)
  • 微秒级硬件延时(可基于基于DWT或定时器)
1
RT_WEAK void rt_hw_us_delay(rt_uint32_t us)

注意:前三个函数受系统tick影响,tick = (1 / RT_TICK_PER_SECOND)秒,其中RT_TICK_PER_SECOND默认为1000,即默认tick = 1ms。

一、rt_thread_delay_until()函数

此函数提供一个固定周期的精准延时,其特点是基于预计算的绝对时间,而不是从调用时刻开始计时。这意味着它可以避免累积误差,适用于需要严格定时周期性任务的场景(如PID控制、ADC采样等)。

注意:在对时域算法离散化时,dt步长尤为重要,它关乎系统的稳定和精度!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @brief 线程2入口函数
* @param 无
* @retval 无
*/
void thread_2_entry(void* param)
{
while(1)
{
rt_tick_t now_tick = rt_tick_get(); /* 获取当前时间,从此刻记时 */

sys_conrtol();

/* 再延时(ticks) = 1000 - sys_conrtol()执行时间 */
/* 保证sys_conrtol()执行周期为严格的1000个ticks */
rt_thread_delay_until(&now_tick, 1000);
}
}

关键点:

  • 必须&last_tick(指针)传输上次延时结束时的时间,以实现精准循环。
  • 适用于需要严格时间间隔的任务,如PWM控制、传感器采样等。
  • 长时间运行也不会出现累积误差。

二、rt_thread_delay()函数

该函数实现相对延时,即从当前时刻开始挂起线程 delay 个系统时钟节拍(tick)。它的特点是计算简单,但如果在任务中有其他耗时操作,可能导致周期不稳定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @brief 线程2入口函数
* @param 无
* @retval 无
*/
void thread_2_entry(void* param)
{
while(1)
{
sys_conrtol();

/* 再延时时间(ticks) = 1000 */
/* sys_conrtol()函数执行时间不确定,实际执行周期 > 1000 ticks*/
rt_thread_delay(1000);
}
}

关键点:

  • 适用于不要求严格周期的任务,如后台日志打印、网络轮询。
  • 如果任务本身的执行时间较长,会导致总周期不再是准确的 delay
  • RT-Thread的系统tick通常为1ms(默认配置),delay=1000 表示1000ms(1秒)。
  • 用户可通过修改RT_TICK_PER_SECOND调整tick分辨率,但需权衡系统性能。

三、rt_thread_mdelay()函数

由于 rt_thread_delay() 的延时单位是系统tick(默认1ms),而 rt_thread_mdelay() 直接指定毫秒(ms)单位,更方便开发者进行计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @brief 线程2入口函数
* @param 无
* @retval 无
*/
void thread_2_entry(void* param)
{
while(1)
{
sys_conrtol();

/* 再延时时间(ticks) = 1000 */
/* sys_conrtol()函数执行时间不确定,实际执行周期 > 1000 ms*/
rt_thread_mdelay(1000);
}
}

关键点:

  • 本质上仍然是 基于 rt_thread_delay 的封装,适用于需要直接使用毫秒单位的情况。
  • 常用于设备轮询、IO等待等场景。
  • 延时精度受限于tick分辨率。

四、rt_hw_us_delay()函数

这是基于CPU空循环实现的硬件级延时,精度远高于 rt_thread_delayrt_thread_mdelay,适用于短时间、高精度的任务(如SPI/I2C通信时序控制)。

注意:

  • 不会触发线程调度,适用于短延时,长时间延时应优先使用调度函数
  • 依赖于CPU频率,部分STM32/MCU可能需要调整delay_us的计算方式。
  • 部分芯片不支持需自己实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

......

/* 拉低CS片选信号 */
rt_pin_write(SPI_CS_PIN, PIN_LOW);

/* 10us延时(确保SPI设备就绪) */
rt_hw_us_delay(10);

/* SPI数据传输 */
rt_spi_send(spi_dev, &data, 1);

/* 拉高CS */
rt_pin_write(SPI_CS_PIN, PIN_HIGH);

......

关键点:

  • 适用于硬件驱动开发(如GPIO、SPI、I2C)。
  • 慎用在主线程,否则会阻塞其他任务运行

RT-Thread提供了四种不同的延时方式,适用于不同精度的任务调度需求。合理选择延时函数可以提高系统的实时性和稳定性。


欢迎关注本人微信公众号: