2016-08-07 2 views
0

저는 Arduino UNO 프로젝트에서 멀티 태스킹을 위해 freertos를 사용하고 있습니다. 두 작업이 있습니다. 1-TaskLedBlink.2-TaskSerialP6008. 첫 번째 작업은 주어진 시간 간격으로 두 번 LED를 깜박이는 데 사용되며 두 번째 것은 직렬 포트에서 프레임을 수신 한 다음 다시 보내는 데 사용됩니다. 프레임은 0x02으로 시작하고 0x0D으로 끝나야합니다. 0x02이 수신되면 ASCII 프레임이라는 배열에 들어오는 바이트를 추가하기 시작합니다. 0x0D이 수신 된 후 홀 프레임을 다시 전송합니다. 그 순간까지는 프로그램이 잘 작동했습니다.. 그런 다음 asciiFrame의 디코딩을 담당하는 코드 블록을 추가하기로 결정한 결과는 binaryFrame이라는 배열에 저장됩니다. 여기 프로그램이 이상하게 작동하기 시작했습니다. led가 깜박임을 멈추고 때로는 꺼져있는 경우 직렬 데이터가 손실됩니다 (수신되지 않음). 최악의 경우 arduino를 재부팅 할 때까지 프로그램이 더 이상 응답하지 않습니다. 제가있는 문제를 해결하기 위해 주위를 찾고 시작 때 이런 광고 binaryFrame [m] = (asciiFrame [K] & 15) + ((asciiFrame [K + 1] & 15) < < 4)를 제거 할 때,이 프로그램이 정상적으로 작동합니다. 이 문제를 해결 도와 줘요 ... 여기에 내가 문제가 글로벌로 변수를 선언 한 생각 코드Arduino uno freertos 작업 실행이 중지되었습니다.

#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 
    } 
} 

답변

1

, 내가 작업 내부를 선언 한 그것은 꽤 좋은 일하고있다.

1

은 ... 당신이 RAM의 한계 근처에있어
을 보인다거나 m 신속하게보고함으로써 binaryFrame 제한 ...

을 초과, 나는 K의 약 절반 인 해요 추정 당신은

정의 메모리를 스푸핑 할 때 지역 변수와
byte asciiFrame[18]; 
byte binaryFrame[8]; 

더 0x0d로 존재하지 않는 경우, 당신은 m를 재설정하지 않습니다 ...

당신은 다른 동작을 얻을.

+0

자세히 살펴보면 ** m ** ** ** 0x0D **가 수신 될 때까지 작업을 시작하지 않으므로 ** m **은 항상 재설정됩니다. 그러나 그것은 문제가 아닙니다. – Madon

+0

나는 리셋하지 않을 것이라고 생각합니다. ** m ** 작업이 전환되거나 멈추는 것을 방지합니다. RAM에 대해 말하면, Arduino IDE로 스케치를 컴파일 할 때 Sketch는 프로그램 저장 공간의 10,080 바이트 (31 %)를 사용한다고 말합니다. 최대 값은 32,256 바이트입니다. 전역 변수는 422 바이트 (20 %)의 동적 메모리를 사용하며 로컬 변수에는 1,626 바이트를 남겨 둡니다. 최대 값은 2,048 바이트입니다. – Madon

+0

좀 더 가까이서 보면, 나는 동의한다 ...;)
Arduino_FreeRTOS가 외부 메모리를 사용하고 있기를 바랍니다. 몇 가지 독립적 인 깜박임만으로도 정교한 멀티 태스킹 작업이 필요 없다는 것을 확실히 알고 계실 것입니다. 하지만 단순히 BlinkWithoutDelay입니다. – datafiddler