我正在与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
}
}
答案 0 :(得分:1)
我认为问题在于将变量声明为全局变量,我已在任务中声明它们并且它的工作非常好。
答案 1 :(得分:1)
您似乎已接近RAM限制...
或者你的m超过binaryFrame限制...
通过快速查看,我估计m大约是k的一半,你定义了
byte asciiFrame[18];
byte binaryFrame[8];
如果没有0x0D,你就不会重置m ...
使用局部变量时,在欺骗内存时会出现不同的行为。