通过 Freertos 中的队列发送字符串

Posted

技术标签:

【中文标题】通过 Freertos 中的队列发送字符串【英文标题】:Sending string through queue in Freertos 【发布时间】:2021-02-19 05:05:37 【问题描述】:

我想创建一个带有按钮的任务,该任务将一个字符串发送到一个队列并创建另一个任务(这也可以是具有较低优先级的单独任务),如果其变量与队列中的字符串。否则系统应保持空闲模式。我对 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();;

【问题讨论】:

你在用什么,CC++。编辑帖子以仅保留您正在使用的标签。您是否编译并看到警告或错误?如果是这样,请发布它们以显示它们出现在代码中的位置。 【参考方案1】:

什么都没有发生,因为程序可能执行得太快而无法正常工作。当您的程序启动时,它会在几分之一秒内初始化所有内容,如果未按下按钮,则不会发生任何事情。然后你的主循环什么都不做。至少,您应该将按钮监视放在一个任务中,并且该任务应该有一个不会结束的 whilefor 循环。

首先创建一个更简单的系统 - 例如,两个任务、一个按钮阅读器和一个发光器。按钮阅读器任务只是检查按钮是否被按下并将一个项目插入队列。发光器检查队列中是否有东西。

还应该注意,所有 RTOS 都不喜欢一直创建和结束任务。如果你打算这样做,你应该阅读如何创建和销毁任务。 (https://www.freertos.org/a00125.html) 让任务脱离上下文并不会自动清理它,您需要使用 vTaskDelete - 使用您当前的功能,您需要使用您的 QSender 任务清理 QReceiver ,这违反了 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 中,您正在比较myRxBuffzyRxBuff 的地址,而您应该进行字符串比较

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);
    

【讨论】:

"什么都没有发生,因为程序可能执行得太快而无法正常工作。当您的程序启动时,它会在几分之一秒内初始化所有内容,如果没有按下按钮,则什么也不会发生"通常这就是我想要的。这两个任务应该完成它们的任务,然后系统返回空闲模式。它们的执行时间会改变,但不会处于无限循环中。也许我可以创建一个新任务来控制这两个任务作为它的子任务在一个while循环中。 当我调试当前代码时,我看到创建了两个任务但它没有进入 if 语句,这似乎是 xQueueReceive 中的错误,因为滥用了指针/地址约会。 到你的第一点——除非你在板子上电时按住按钮,否则不会出现if语句,也不会创建第一个任务。第二点 - 尝试在QReceiver 中使用strcmp(a,b)=0 而不是==。您正在比较两个字符串的地址,而不是两个字符串的实际内容。 是的,它在闪烁 :)

以上是关于通过 Freertos 中的队列发送字符串的主要内容,如果未能解决你的问题,请参考以下文章

在 FreeRTOS 中使用字符串队列

在 freertos API 中使用队列

FreeRTOS队列

FreeRTOS消息队列 & ESP32使用

FreeRTOS队列

基于STM32与FreeRTOS的消息传递详解(HAL库)