在 Freertos 中通过队列发送字符串
Sending string through queue in Freertos
我想创建一个带按钮的任务,该任务将一个字符串发送到队列并创建另一个任务(这也可以是具有较低优先级的单独任务),如果其变量相同,则读取队列并闪烁 led与队列中的字符串。否则系统应该停留在空闲模式。我对 freertos 很陌生,即使没有编译错误,Led 也不会随着以下代码闪烁。如果可能的话,我还想将数据类型从 char 替换为 string。 (select和zyRxBuff出处不同,为简单起见,写成下面)
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
处理人员;
QueueHandle_t myQueue = NULL;
TaskHandle_t QTASK1 = NULL;
TaskHandle_t QTASK2 = NULL;
原型;
void Qsender(void* p);
void Qreceiver(void* p);
主区块;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET)
{
xTaskCreate(Qsender, "SendingTask", 200, NULL, 1, &QTASK1);
vTaskStartScheduler();
}
while (1) {};
}
发件人功能;
void Qsender(void* p)
{
char select[10]= "BlinkLed";
myQueue = xQueueCreate(1, sizeof(select));
xQueueSend(myQueue, (void*) &select, (TickType_t)10);
if (myQueue != 0)
{
xTaskCreate(Qreceiver, "ReceivingTask", 200, NULL, 1, &QTASK2);
}
}
接收函数;
void Qreceiver(void* p)
{
char myRxBuff[10];
char zyRxBuff[10]="BlinkLed";
xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
if ( myRxBuff == zyRxBuff)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(500);
}
}
空闲函数;
void vApplicationIdleHook(void){__WFI();};
没有发生任何事情,因为程序可能执行得太快以至于无法正常工作。当您的程序启动时,它会在几分之一秒内初始化所有内容,如果没有按下按钮,则什么也不会发生。然后你的主循环什么都不做。至少,您应该将监视按钮放在任务中,并且该任务应该有一个不会结束的 while
或 for
循环。
首先创建一个更简单的系统 - 例如,两个任务,一个 button-reader 和一个 light-emitter。 button-reader 任务只是检查按钮是否被按下并将一个项目插入队列。 light-emitter 检查队列中是否有内容。
还应该注意的是,所有的实时操作系统真的不喜欢一直创建和结束任务。如果你打算这样做,你应该阅读如何创建和销毁任务。 (https://www.freertos.org/a00125.html) 让任务脱离上下文不会自动清理它,您需要使用 vTaskDelete
- 使用您当前的功能,您需要清理 QReceiver
与您的 QSender
任务,这违反了 SOLID 原则。此外,您的 QReceiver
将需要发回已完成的消息。如果你能先让它们静态工作,以后让它们动态工作会容易得多。
我还注意到您是按地址而不是按内容比较字符串。
Qsender
正在发送 BlinkLed
void Qsender(void* p){
char select[10]= "BlinkLed";
myQueue = xQueueCreate(1, sizeof(select));
xQueueSend(myQueue, (void*) &select, (TickType_t)10);
if (myQueue){
xTaskCreate(Qreceiver, "ReceivingTask", 200, NULL, 1, &QTASK2);
}
}
然而,在 Qreceiver
中,您正在比较 myRxBuff
和 zyRxBuff
的地址,而您应该执行 string-compare
void Qreceiver(void* p){
char myRxBuff[10];
char zyRxBuff[10]="BlinkLed";
xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
if ( myRxBuff == zyRxBuff){ // Offending Line
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(500);
}
}
void Qreceiver(void* p){
char myRxBuff[10];
char zyRxBuff[10]="BlinkLed";
xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
if ( strcmp(myRxBuff, zyRxBuff) == 0){ // Should compare content now
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(500);
}
}
我想创建一个带按钮的任务,该任务将一个字符串发送到队列并创建另一个任务(这也可以是具有较低优先级的单独任务),如果其变量相同,则读取队列并闪烁 led与队列中的字符串。否则系统应该停留在空闲模式。我对 freertos 很陌生,即使没有编译错误,Led 也不会随着以下代码闪烁。如果可能的话,我还想将数据类型从 char 替换为 string。 (select和zyRxBuff出处不同,为简单起见,写成下面)
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
处理人员;
QueueHandle_t myQueue = NULL;
TaskHandle_t QTASK1 = NULL;
TaskHandle_t QTASK2 = NULL;
原型;
void Qsender(void* p);
void Qreceiver(void* p);
主区块;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET)
{
xTaskCreate(Qsender, "SendingTask", 200, NULL, 1, &QTASK1);
vTaskStartScheduler();
}
while (1) {};
}
发件人功能;
void Qsender(void* p)
{
char select[10]= "BlinkLed";
myQueue = xQueueCreate(1, sizeof(select));
xQueueSend(myQueue, (void*) &select, (TickType_t)10);
if (myQueue != 0)
{
xTaskCreate(Qreceiver, "ReceivingTask", 200, NULL, 1, &QTASK2);
}
}
接收函数;
void Qreceiver(void* p)
{
char myRxBuff[10];
char zyRxBuff[10]="BlinkLed";
xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
if ( myRxBuff == zyRxBuff)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(500);
}
}
空闲函数;
void vApplicationIdleHook(void){__WFI();};
没有发生任何事情,因为程序可能执行得太快以至于无法正常工作。当您的程序启动时,它会在几分之一秒内初始化所有内容,如果没有按下按钮,则什么也不会发生。然后你的主循环什么都不做。至少,您应该将监视按钮放在任务中,并且该任务应该有一个不会结束的 while
或 for
循环。
首先创建一个更简单的系统 - 例如,两个任务,一个 button-reader 和一个 light-emitter。 button-reader 任务只是检查按钮是否被按下并将一个项目插入队列。 light-emitter 检查队列中是否有内容。
还应该注意的是,所有的实时操作系统真的不喜欢一直创建和结束任务。如果你打算这样做,你应该阅读如何创建和销毁任务。 (https://www.freertos.org/a00125.html) 让任务脱离上下文不会自动清理它,您需要使用 vTaskDelete
- 使用您当前的功能,您需要清理 QReceiver
与您的 QSender
任务,这违反了 SOLID 原则。此外,您的 QReceiver
将需要发回已完成的消息。如果你能先让它们静态工作,以后让它们动态工作会容易得多。
我还注意到您是按地址而不是按内容比较字符串。
Qsender
正在发送 BlinkLed
void Qsender(void* p){
char select[10]= "BlinkLed";
myQueue = xQueueCreate(1, sizeof(select));
xQueueSend(myQueue, (void*) &select, (TickType_t)10);
if (myQueue){
xTaskCreate(Qreceiver, "ReceivingTask", 200, NULL, 1, &QTASK2);
}
}
然而,在 Qreceiver
中,您正在比较 myRxBuff
和 zyRxBuff
的地址,而您应该执行 string-compare
void Qreceiver(void* p){
char myRxBuff[10];
char zyRxBuff[10]="BlinkLed";
xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
if ( myRxBuff == zyRxBuff){ // Offending Line
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(500);
}
}
void Qreceiver(void* p){
char myRxBuff[10];
char zyRxBuff[10]="BlinkLed";
xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
if ( strcmp(myRxBuff, zyRxBuff) == 0){ // Should compare content now
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(500);
}
}