FreeRTOS(CMSIS)-(7)-延时函数

目录

一、延时函数分类:

1.相对延时:vTaskDelay

2.绝对延时:vTaskDelayUntil

二、vTaskDelay 与 HAL_Delay 的区别:

vTaskDelay(FreeRTOS):

HAL_Delay(HAL库):


一、延时函数分类:

相对延时: vTaskDelay
绝对延时: vTaskDelayUntil

1.相对延时:vTaskDelay

vTaskDelay函数实现的是相对延时,即从当前时刻开始计算延时时间。这个函数会将任务挂起指定的系统时钟节拍数(ticks),直到指定的时间过去后,任务才会被重新调度执行。

vTaskDelay( xTicksToDelay );
  • xTicksToDelay:这是要延时的系统时钟节拍数。可以通过pdMS_TO_TICKS宏将毫秒数转换为系统时钟节拍数。
vTaskDelay( pdMS_TO_TICKS(100) );

   这会导致任务挂起,直到100毫秒后。

2.绝对延时:vTaskDelayUntil

vTaskDelayUntil函数实现的是绝对延时,即从某个特定的未来时刻开始计算延时时间。这个函数会将任务挂起,直到从上一次调用vTaskDelayUntil后经过了指定的时间间隔。

vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement );
  • pxPreviousWakeTime:这是一个指针,指向一个变量,该变量保存了任务上一次被唤醒的时间(以系统时钟节拍为单位)。每次调用vTaskDelayUntil时,都应该传入同一个变量的地址。
  • xTimeIncrement:这是要延时的系统时钟节拍数。

例如,如果你想让任务每隔100毫秒执行一次,可以这样调用:

const TickType_t xDelay = pdMS_TO_TICKS(100);
TickType_t xLastWakeTime;

// 初始化xLastWakeTime
xLastWakeTime = xTaskGetTickCount();

while(1)
{
    // 任务代码...

    // 延时直到下一个100毫秒
    vTaskDelayUntil( &xLastWakeTime, xDelay );
}

在这个循环中,xLastWakeTime会在每次调用vTaskDelayUntil时更新,以确保任务每隔100毫秒被唤醒一次。

总结来说,vTaskDelay是基于当前时间的相对延时,而vTaskDelayUntil是基于上一次唤醒时间的绝对延时。使用vTaskDelayUntil可以更容易地实现周期性的任务调度。

二、vTaskDelay HAL_Delay 的区别:

vTaskDelayHAL_Delay是两个完全不同的函数,它们分别属于不同的系统和库,用于不同的上下文和目的。下面是它们的主要区别:

  1. vTaskDelay(FreeRTOS):

    • vTaskDelay是FreeRTOS实时操作系统(RTOS)中的一个函数。
    • 它用于实现任务的延时,使当前任务挂起指定的系统时钟节拍数(ticks),让出CPU给其他任务运行。
    • vTaskDelay是协作式的,它不会立即阻塞CPU,而是让任务进入阻塞状态,直到指定的延时时间过去。
    • 它允许任务在延时期间被操作系统的其他部分(如中断服务例程)打断。
    • vTaskDelay的参数是系统时钟节拍数,可以通过pdMS_TO_TICKS宏将毫秒数转换为系统时钟节拍数。
  2. HAL_Delay(HAL库)

    • HAL_Delay是硬件抽象层(HAL)库中的一个函数,通常用于STM32等微控制器。
    • 它用于实现一个简单的延时,通常是通过阻塞CPU来实现的,即在延时期间CPU不做其他事情,只是等待。
    • HAL_Delay是非协作式的,它会阻塞CPU,直到指定的毫秒数过去。
    • 它不允许在延时期间被中断打断,因此可能会影响系统的实时性。
    • HAL_Delay的参数是毫秒数。
void vTaskDelay( const TickType_t xTicksToDelay )
{
	BaseType_t xAlreadyYielded = pdFALSE;

	/* A delay time of zero just forces a reschedule. */
	if( xTicksToDelay > ( TickType_t ) 0U )
	{
		configASSERT( uxSchedulerSuspended == 0 );
		vTaskSuspendAll();
		{
			traceTASK_DELAY();

			/* A task that is removed from the event list while the
			scheduler is suspended will not get placed in the ready
			list or removed from the blocked list until the scheduler
			is resumed.

			This task cannot be in an event list as it is the currently
			executing task. */
			prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
		}
		xAlreadyYielded = xTaskResumeAll();
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}

	/* Force a reschedule if xTaskResumeAll has not already done so, we may
	have put ourselves to sleep. */
	if( xAlreadyYielded == pdFALSE )
	{
		portYIELD_WITHIN_API();
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}
__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}

vTaskDelay 作用是让任务阻塞,任务阻塞后,RTOS系统调用其它处于就绪状态的优先级最高的任务来执行。

HAL_Delay 一直不停的调用获取系统时间的函数,直到指定的时间流逝然后退出,故其占用了全部CPU时间。

在实际应用中,选择使用哪个函数取决于你的系统需求和上下文:

  • 如果你在使用FreeRTOS,并且需要实现任务间的协作和调度,那么应该使用vTaskDelay
  • 如果你在使用STM32 HAL库,并且需要一个简单的CPU阻塞延时,那么可以使用HAL_Delay

需要注意的是,HAL_Delay可能会影响RTOS的调度,因为它会阻塞CPU,所以在使用RTOS的情况下,通常推荐使用vTaskDelay或其他RTOS提供的延时函数。此外,HAL_Delay通常依赖于系统的时钟配置,而vTaskDelay则依赖于FreeRTOS的时钟节拍配置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值