我对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()的输出频率看到它。
第二件有趣的事情是,xlastwoketime显示了完全不同的值,这些值实际上增加了2000它不应该存储类似于xTaskGetTickCount()返回的值吗?
最佳答案
在第一次迭代中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资源可用的时间,我认为这是您想要的。