我有一个问题,即vTaskDelayUntil()函数没有延迟但是立即完成。这是代码:
TickType_t xLastWakeTime = xTaskGetTickCount();
while(1){
if (xSemaphoreTake(xSemaphoreRS485, portMAX_DELAY) == pdTRUE) {
printf("S display data %d\n", xTaskGetTickCount());
sendDisplayData();
printf("E display data %d\n", xTaskGetTickCount());
xSemaphoreGive(xSemaphoreRS485);
printf("W display data %d\n", xLastWakeTime);
vTaskDelayUntil(&xLastWakeTime, 2000);
}
}
从此我得到以下输出:
S display data 29928
E display data 30534
W display data 3919
S display data 30534
E display data 31140
W display data 5919
S display data 31140
E display data 31746
W display data 7919
S display data 31746
E display data 32352
W display data 9919
函数sendDisplayData()执行大约需要670毫秒,而xTaskGetTickCount()会确认它。然后任务应该在1230毫秒左右等待,因此整个迭代可能需要2000毫秒。但vTaskDelayUntil()立即完成。第一次执行在30534结束,第二次执行也从30534开始。 xTaskGetTickCount()返回的值证明vTaskDelayUntil()没有引入延迟。我也可以通过sendDisplayData()的输出频率来看。
第二个有趣的事情是xLastWakeTime显示完全不同的值,并且这些值实际上增加了2000.它不应该存储xTaskGetTickCount()返回的类似值吗?
答案 0 :(得分:5)
在你的第一次迭代中,xLastWakeTime
的值为3919,你请求增加2000,所以延迟到5919,但是你在30534时调用它。
来自vTaskDelayUntil()
应该注意的是,如果vTaskDelayUntil()用于指定已经过去的唤醒时间,则会立即返回(不会阻塞)。
您的任务花费了26009个刻度(29928 - 3919)在初始信号量上被阻止。您的目标2000滴答增量早已过去。
我建议以下内容至少接近你的意图
for(;;)
{
if (xSemaphoreTake(xSemaphoreRS485, portMAX_DELAY) == pdTRUE) // Lock
{
TickType_t xLastWakeTime = xTaskGetTickCount();
sendDisplayData();
xSemaphoreGive(xSemaphoreRS485); // Unlock
vTaskDelayUntil(&xLastWakeTime, 2000);
}
这将使循环迭代总计需要2000个滴答,包括执行sendDisplayData()
加上等待RS485资源可用的时间所花费的时间,这就是我想你的意思意图。
答案 1 :(得分:1)
如上所述,如果指定的唤醒时间已经过去,则vTaskDelayUntil()将立即返回。建议改为使用vTaskDelay()。