我有一个问题,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()返回的类似值吗?
在您的第一次迭代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资源可用的时间,这就是我想你想要的.