基于STM32F4+FREERTOS进行结构体变量的传递

 

原始参考链接如下↓

Freertos 接收消息队列数据不对,是姿势不正确吗 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!

https://www.armbbs.cn/forum.php?mod=viewthread&tid=111900&highlight=%CF%FB%CF%A2%B6%D3%C1%D0


C 语言关于结构体做参数传递 | 菜鸟教程 https://www.runoob.com/w3cnote/c-the-structure-of-the-parameter.html


由于看到的FREERTOS的例程中关于消息队列的代码,大多数都是传递的一个字节的数值;

而在实际应用中,需要传递的数据类型可以是浮点数,也可以是数组,也可以是uint16数据,所以上述链接的传递结构体指针的思路很符合我的需求。

同时,使用RTOS+消息队列的处理方式,至少有以下两个优点:

1、便于开发,因为各个模块之间是通过消息队列进行数据交互,没有直接耦合,无需像裸机编程一样进行全局变量的引用

2、便于移植,代码复用率高,各个开发者之间沟通成本低

需要注意的点是:

1、将结构体作为指针传递时是4字节,指针传递时用到的局部变量会被释放。

2、printf函数打印float数据时需要使用%f格式字符



变量初始化

查看代码

typedef struct Msg {
    uint8_t ucMessageID;
    uint16_t usData[2];
    uint32_t ulData[2];
    float_t test_buf[3];
} MSG_T;

MSG_T g_tMsg; /* 定义一个结构体用于消息队列 */

发送消息队列的代码示例


static void vTaskTaskUserIF(void* pvParameters)
static void vTaskTaskUserIF(void* pvParameters)
{
    MSG_T* ptMsg;
    uint8_t ucCount = 0;
    uint8_t ucKeyCode;
    uint8_t pcWriteBuffer[500];

    /* 初始化结构体指针 */
    ptMsg = &g_tMsg;

    /* 初始化数组 */
    ptMsg->ucMessageID = 0;
    ptMsg->ulData[0] = 0;
    ptMsg->usData[0] = 0;
    ptMsg->test_buf[0] = 0;
    while (1) {
        ucKeyCode = bsp_GetKey();

        if (ucKeyCode != KEY_NONE) {
            switch (ucKeyCode) {
            /* K1键按下,向xQueue1发送数据 */
            case KEY_DOWN_K1:
                ptMsg->ucMessageID++;
                ptMsg->ulData[0]++;
                ptMsg->test_buf[0]++;

                /* 使用消息队列实现指针变量的传递 */
                if (xQueueSend(xQueue2, /* 消息队列句柄 */
                        (void*)&ptMsg, /* 发送结构体指针变量ptMsg的地址 */
                        (TickType_t)10)
                    != pdPASS) {
                    /* 发送失败,即使等待了10个时钟节拍 */
                    printf("K1键按下,向xQueue1发送数据失败,即使等待了10个时钟节拍\r\n");
                } else {
                    /* 发送成功 */
                    printf("K1键按下,向xQueue1发送数据成功\r\n");
                }
                break;
            /* K2键按下,向xQueue2发送数据 */
            case KEY_DOWN_K2:
                ptMsg->ucMessageID++;
                ptMsg->ulData[0]++;
                ptMsg->test_buf[0]++;

                /* 使用消息队列实现指针变量的传递 */
                if (xQueueSend(xQueue2, /* 消息队列句柄 */
                        (void*)&ptMsg, /* 发送结构体指针变量ptMsg的地址 */
                        (TickType_t)10)
                    != pdPASS) {
                    /* 发送失败,即使等待了10个时钟节拍 */
                    printf("K2键按下,向xQueue2发送数据失败,即使等待了10个时钟节拍\r\n");
                } else {
                    /* 发送成功 */
                    printf("K2键按下,向xQueue2发送数据成功\r\n");
                }
                break;
            /* 其他的键值不处理 */
            default:
                break;
            }
        }

        vTaskDelay(20);
    }
}

接收消息队列的代码


static void vTaskLED(void* pvParameters)

static void vTaskLED(void* pvParameters)
{
    MSG_T* ptMsg;
    BaseType_t xResult;
    const TickType_t xMaxBlockTime = pdMS_TO_TICKS(200); /* 设置最大等待时间为200ms */

    while (1) {
        xResult = xQueueReceive(xQueue2, /* 消息队列句柄 */
            (void*)&ptMsg, /* 这里获取的是结构体的地址 */
            (TickType_t)xMaxBlockTime); /* 设置阻塞时间 */

        if (xResult == pdPASS) {
            /* 成功接收,并通过串口将数据打印出来 */
            printf("接收到消息队列数据ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);
            printf("接收到消息队列数据ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);
            printf("接收到消息队列数据ptMsg->testbuf[0] = %f\r\n", ptMsg->test_buf[0]);
        } else {
            /* 超时 */
            bsp_LedToggle(2);
            bsp_LedToggle(3);
        }
    }
}
posted @   realiot  阅读(722)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示