0

我想为类的每个实例创建一个具有延迟的函数。如果发生某种情况,将创建一个任务,并且延迟只会发生在这个实例上。

 /* Task to be created. */
void vTaskCode( void * pvParameters ){
   const TickType_t xDelay = 1000 / portTICK_PERIOD_MS;
   //Do some logic...       
   vTaskDelay(xDelay);

   //indicate the task has finished
   configASSERT(1);
}
BaseType_t xReturned;
TaskHandle_t xHandle = NULL;

class foo {
void afunc(){
  //Create a task of vTaskCode if it doesnt exist
  if (xHandle == NULL){
  xReturned = xTaskCreate(
                    vTaskCode,       /* Function that implements the task. */
                    "Auxiliary",          /* Text name for the task. */
                    STACK_SIZE,      /* Stack size in words, not bytes. */
                    NULL,    /* Parameter passed into the task. */
                    tskIDLE_PRIORITY,/* Priority at which the task is created. */
                    &xHandle );


}}

 //Should be called after the task is complete.    
 if( xReturned == pdPASS )
 {
     vTaskDelete( xHandle );
 }


}

//main loop
  void MainLOOP( void * pvParameters ){
  for (;;){
     const TickType_t xDelay = 5 / portTICK_PERIOD_MS;
     for (std::list<foo>::iterator itr = foolist.begin(); itr != foolist.end(); ++itr)
     {
         itr->afunc();
     }
   }}


void setup(){
std::list<foo> foolist;

///...SOME CODE TO POPULATE FOOLIST

xTaskCreate(
                    MainLOOP,       /* Function that implements the task. */
                    "MAIN",          /* Text name for the task. */
                    STACK_SIZE,      /* Stack size in words, not bytes. */
                    NULL,    /* Parameter passed into the task. */
                    tskIDLE_PRIORITY,/* Priority at which the task is created. */
                    NULL);


}

每次延迟都会起作用吗?或者在每次迭代中都会运行一个新任务?for 循环会被阻塞,所以每次迭代都会停止还是异步工作?

整个想法是避免使用 millis() 函数并且不阻塞列表的每个迭代。另一个限制是速度,因为这个循环以 5ms 工作,我想使用核心 0。

编辑:@HS2 提出更好的方法应该是使用 FreeRTOS 计时器

4

1 回答 1

0

正如 HS2 所说,动态创建任务不是一个好方法。如果您的定时操作由于计时器队列而必须运行许多函数和对象,则使用 FreeRTOS 计时器效果不佳。解决方案是为列表中的每个对象创建一个任务,而不是列表的主要任务:

列表中每个对象的 TASK

void Djtri::analisa(void *pvParameters) {
    //Serial.printf("\n ABT: %x FCH: %x BI: %x", totAbt, totFch, *bi);
Djtri *djpnt = (Djtri*) pvParameters;
const TickType_t tmpAb = djpnt->tmpAbt / portTICK_PERIOD_MS;
const TickType_t tmpFc = djpnt->tmpFch / portTICK_PERIOD_MS;
const TickType_t looptime = 5 / portTICK_PERIOD_MS;
for (;;){
    if ((djpnt->biAbt & io[0]) && (djpnt->estado != ABERTO)) {
        Serial.printf("\nOrdem de abertura do DJ %X ", djpnt->id);

        vTaskDelay(tmpAb);
        djpnt->abrir();

    } else if ((djpnt->biFch & io[0]) && (djpnt->estado != FECHADO)) {
        Serial.printf("\nOrdem de fechamento do DJ %X", djpnt->id);
        vTaskDelay(tmpFc);
        djpnt->fechar();
    }
    vTaskDelay(looptime);
}
}

在设置 ESP32 时为每个项目创建一个任务

    for (auto itr = djtrilst.begin(); itr != djtrilst.end(); ++itr){
    Serial.printf("\n Criando task para DJ tri: %x", itr->id);
    xTaskCreatePinnedToCore(
            Djtri::analisa,   /* Function to implement the task */
            "Djtri", /* Name of the task */
            8000,      /* Stack size in words */
            (void*) &*itr,       /* Task input parameter */
            0,          /* Priority of the task */
            nullptr,       /* Task handle. */
            0);  /* Core where the task should run */
}

请注意,我使用任务输入参数来传递对象的指针,因为任务函数必须是静态的。

于 2021-07-26T14:02:27.843 回答