繁体   English   中英

Arduino Uno Freertos任务停止运行

[英]Arduino uno freertos tasks stopped running

我正在与arduino UNO进行一个项目,我正在使用freertos进行多任务处理,我有两个任务: 1-TaskLedBlink。 2-TaskSerialP6008。 第一个任务用于在给定的时间段内两次刷新LED,第二个任务用于从串行端口接收帧,然后将其发送回去。 框架应以0x02开头,以0x0D结束。 当接收到0x02时,我开始将传入的字节添加到称为asciiFrame的数组中,直到接收到0x0D ,之后我将帧发送回去。 在那一刻之前,程序运行良好 然后我决定添加一个代码块,该代码块负责解码asciiFrame,结果保存在一个名为binaryFrame的数组中。 在这里,程序开始表现得很奇怪。 LED停止闪烁,有时亮,有时灭,串行数据丢失(未接收)。 在最坏的情况下,直到我重新启动arduino为止,程序才不再响应。 当我开始四处张望以解决问题时,我发现当我删除这一行时, binaryFrame [m] =(asciiFrame [k]&15)+(((asciiFrame [k + 1]&15)<< 4); 该程序工作正常。 帮助请解决这个问题...这里是代码

#include <Arduino_FreeRTOS.h>
#include <semphr.h>  // add the FreeRTOS functions for Semaphores (or Flags).

byte inByte = 0;                    // incoming serial byte
bool startByte = false;
byte asciiFrame[18];                //array to save ascci frame p6008 02 xx xx....0d max 18 bytes including 0x02 and 0x0D
byte binaryFrame[8];                //array to save binary frame p6008 (max 7 bytes + CHECKSUM)
byte i=0;                           //index used to select case in array
byte j=0;                             //index used to select byte in array to send it over serial

byte k=0;                             //index used to convert from ascii to binary
byte m=0;                             //to save data in binary frame
bool asciiFrameComplete = false;    //to indicate that a complete frame(ascii mode) hs been recieved
bool binaryFrameComplete = false;
bool asciiP6008Enabled = true;      //true(ascii mode) false(binary mode)

// Declare a mutex Semaphore Handle which we will use to manage the Serial Port.
// It will be used to ensure only only one Task is accessing this resource at any time.
SemaphoreHandle_t xSerialSemaphore;

// define two Tasks for DigitalRead & AnalogRead
void TaskLedBlink( void *pvParameters );
void TaskSerialP6008( void *pvParameters );

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 9600 bits per second:
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  // Semaphores are useful to stop a Task proceeding, where it should be paused to wait,
  // because it is sharing a resource, such as the Serial port.
  // Semaphores should only be used whilst the scheduler is running, but we can set it up here.
  if ( xSerialSemaphore == NULL )  // Check to confirm that the Serial Semaphore has not already been created.
  {
    xSerialSemaphore = xSemaphoreCreateMutex();  // Create a mutex semaphore we will use to manage the Serial Port
    if ( ( xSerialSemaphore ) != NULL )
      xSemaphoreGive( ( xSerialSemaphore ) );  // Make the Serial Port available for use, by "Giving" the Semaphore.
  }

  // Now set up two Tasks to run independently.
  xTaskCreate(
    TaskLedBlink
    ,  (const portCHAR *)"LedBlink"  // A name just for humans
    ,  128  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  2  // Priority, with 1 being the highest, and 4 being the lowest.
    ,  NULL );

  xTaskCreate(
    TaskSerialP6008
    ,  (const portCHAR *) "AnalogRead"
    ,  256  // Stack size
    ,  NULL
    ,  1  // Priority
    ,  NULL );

  // Now the Task scheduler, which takes over control of scheduling individual Tasks, is automatically started.
  //vTaskStartScheduler();
}

void loop(){
  // Empty. Things are done in Tasks.
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void TaskLedBlink( void *pvParameters __attribute__((unused)) )  // This is a Task.
{
  for (;;) // A Task shall never return or exit.
  {
      digitalWrite(13, HIGH);
      vTaskDelay(1);
      digitalWrite(13, LOW);
      vTaskDelay(6);
      digitalWrite(13, HIGH);
      vTaskDelay(1);
      digitalWrite(13, LOW);
      vTaskDelay(17);
   }
}


void TaskSerialP6008( void *pvParameters __attribute__((unused)) )  // This is a Task.
{
  for (;;)
  {
    // read the input on analog pin 0:
    //int sensorValue = analogRead(A0);
    if (Serial.available()>0)
    {
      inByte = Serial.read();
      if ((inByte == 2 || startByte)&&asciiP6008Enabled)                     //if 2 was received or already has been(startByte), and ascii mode is enabled
      {
        startByte = true;                               //start byte came
        asciiFrame[i] = inByte;                           //save bytes in frame array
        i++;                                            //increment to the next case in frame array
        if (inByte == 13)                               //end byte came
        {
          asciiFrameComplete = true;
          startByte = false;
          i=0;
          if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
          {
            for (j=0;j<18&&asciiFrame[j]!=0;j++)                  //send frame back
              Serial.write(asciiFrame[j]);
            memset(asciiFrame, 0, sizeof(asciiFrame));            //then clear it
          }
          xSemaphoreGive( xSerialSemaphore );                     // Now free or "Give" the Serial Port for others.
          for(k=1 ; k<sizeof(asciiFrame) ; k++)
          {
            if(asciiFrame[k]==13)
            {
              binaryFrameComplete=true;
              m=0;
              break;
            } 
            if(k%2!=0)
            {
              binaryFrame[m]=(asciiFrame[k]&15)+((asciiFrame[k+1]&15)<<4);
              m++;
            }             
          }
//          if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
//          {
//            for (j=0;j<8;j++)                  //send frame back
//              Serial.write(binaryFrame[j]);
//            memset(asciiFrame, 0, sizeof(asciiFrame));            //then clear it
//            memset(binaryFrame, 0, sizeof(asciiFrame));            //then clear it
//          }
//          xSemaphoreGive( xSerialSemaphore );                     // Now free or "Give" the Serial Port for others.
        }
        if (i==sizeof(asciiFrame))                                                 //if array is full ecrase received data, frame length should not exceed 18 bytes
        {
          memset(asciiFrame, 0, sizeof(asciiFrame));              //clear array
          i=0;                                                    //init i
          startByte = false;
        }
      }
      else if(!asciiP6008Enabled)                                 //binary enabled
      {
        Serial.println("binary enabled");
      }
    }
    //vTaskDelay(1);  // one tick delay (15ms) in between reads for stability
  }
}

我认为问题在于将变量声明为全局变量,我已经在任务中声明了它们,并且效果很好。

看来您已接近RAM限制...
或者您的m超出了binaryFrame限制...

通过快速查看,我估计m约为k的一半,您定义了

byte asciiFrame[18];  
byte binaryFrame[8]; 

如果没有0x0D,则不会重置m ...

使用局部变量,在欺骗内存时会得到不同的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM