我对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资源可用的时间,我认为这是您想要的。

10-07 15:33