Arduino uno freertos任务停止运行

时间:2016-08-07 17:29:28

标签: c arduino freertos

我正在与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
  }
}

2 个答案:

答案 0 :(得分:1)

我认为问题在于将变量声明为全局变量,我已在任务中声明它们并且它的工作非常好。

答案 1 :(得分:1)

您似乎已接近RAM限制...
或者你的m超过binaryFrame限制...

通过快速查看,我估计m大约是k的一半,你定义了

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

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

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