FreeRTOS——队列及其实战

这篇具有很好参考价值的文章主要介绍了FreeRTOS——队列及其实战。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.队列概念

1)队列是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递)
2)队列类似数组,只能存储有限数量、相同类型的数据,在创建时需指定队列长度与队列项大小
3)出队入队阻塞:
若阻塞时间为0 :直接返回不会等待;
若阻塞时间为0~port_MAX_DELAY :等待设定的阻塞时间,若在该时间内还无法入队,超时后直接返回不再等待;
若阻塞时间为port_MAX_DELAY :死等,一直等到可以入队为止。出队阻塞与入队阻塞类似;
4)数据传递方式:FreeRTOS中队列采用实际值传递,即将数据拷贝到队列中进行传递, FreeRTOS采用拷贝数据传递,也可以传递指针,所以在传递较大的数据的时候采用指针传递
FreeRTOS——队列及其实战,单片机,stm32,嵌入式硬件

2.队列结构体

typedef struct QueueDefinition
{
int8_t * pcHead /* 存储区域的起始地址 /
int8_t * pcWriteTo; /
下一个写入的位置 /
union
{
QueuePointers_t xQueue;
SemaphoreData_t xSemaphore;
} u ;
List_t xTasksWaitingToSend; /
等待发送列表 /
List_t xTasksWaitingToReceive; /
等待接收列表 /
volatile UBaseType_t uxMessagesWaiting; /
非空闲队列项目的数量 /
UBaseType_t uxLength; /
队列长度 /
UBaseType_t uxItemSize; /
队列项目的大小 /
volatile int8_t cRxLock; /
读取上锁计数器 /
volatile int8_t cTxLock; /
写入上锁计数器 /
/
其他的一些条件编译 */
} xQUEUE;
FreeRTOS——队列及其实战,单片机,stm32,嵌入式硬件

3队列相关API函数介绍

3.1 创建队列

xQueueCreate() 动态创建
xQueueCreateStatic() 静态创建
实际调用xQueueGenericCreate()
#define xQueueCreate ( uxQueueLength, uxItemSize ) \
xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), (queueQUEUE_TYPE_BASE ))
返回值: NULL 创建失败
其他值 创建成功
注意队列类型6种:
#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) /* 队列 /
#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) /
队列集 /
#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) /
互斥信号量 /
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) /
计数型信号量 /
#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) /
二值信号量 /
#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) /
递归互斥信号量 */

3.2 队列写入消息API函数

FreeRTOS——队列及其实战,单片机,stm32,嵌入式硬件调用函数xQueueGenericSend( ),只是指定了不同的写入位置有三种位置如下:
#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) /* 写入队列尾部 /
#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) /
写入队列头部 /
#define queueOVERWRITE ( ( BaseType_t ) 2 ) /
覆写队列*/
xQueueGenericSend( QueueHandle_t xQueue, //待写入队列
const void * const //待写入消息
pvItemToQueue, //阻塞超时时间
TickType_t xTicksToWait, //写入位置
返回值: pdTRUE 队列写入成功
errQUEUE_FULL 队列写入失败

3.3 从队列读取消息API函数

FreeRTOS——队列及其实战,单片机,stm32,嵌入式硬件
BaseType_t xQueueReceive( QueueHandle_t xQueue, //带读取队列
void * const pvBuffer, //信息读取缓冲区
TickType_t xTicksToWait ) //阻塞超时时间
返回值: pdTRUE 读取成功
errQUEUE_FULL 读取失败

4 队列实战

FreeRTOS——队列及其实战,单片机,stm32,嵌入式硬件文章来源地址https://www.toymoban.com/news/detail-775173.html

4.1 freertos_demo.c

#include "freertos_demo.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"


//1任务 配置

//1.1START_TASK 任务 配置
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

//1.2TASK1 任务 配置
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

//1.3TASK2 任务 配置
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

#define TASK3_PRIO         4
#define TASK3_STK_SIZE   128
TaskHandle_t    task3_handler;
void task3( void * pvParameters );

//2 队列配置
QueueHandle_t key_queue;        /* 小数据句柄 */
QueueHandle_t big_date_queue;   /* 大数据句柄 */
char buff[100] = {"我是一个大数组,大大的数组 124214 uhsidhaksjhdklsadhsaklj"};
    
//2 freertos_demo函数中创建start_task1任务
void freertos_demo(void)
{
    xTaskCreate((TaskFunction_t )start_task,            /* 任务函数 */
                (const char*    )"start_task",          /* 任务名称 */
                (uint16_t       )START_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )START_TASK_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&StartTask_Handler);   /* 任务句柄 */
    vTaskStartScheduler();
}

//2 start_task函数中创建task1、task2任务
void start_task(void *pvParameters)
{
    //2.2进入临界区 
    taskENTER_CRITICAL();  
     /* 队列的创建 */
    key_queue = xQueueCreate( 2, sizeof(uint8_t) );
    if(key_queue != NULL)
    {
        printf("key_queue队列创建成功!!\r\n");
    }else printf("key_queue队列创建失败!!\r\n");
    
    big_date_queue = xQueueCreate( 1, sizeof(char *) );
    if(big_date_queue != NULL)
    {
        printf("big_date_queue队列创建成功!!\r\n");
    }else printf("big_date_queue队列创建失败!!\r\n");
    
    // 2.1创建任务1 
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    // 2.2创建任务2 
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    // 2.3创建任务3
    xTaskCreate((TaskFunction_t )task3,
                (const char*    )"task3",
                (uint16_t       )TASK3_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK3_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    vTaskDelete(StartTask_Handler);
    //退出临界区
    taskEXIT_CRITICAL();  
}

//3 task1实现入队
void task1(void *pvParameters)
{
    int8_t key = 0;
    char * buf;
    BaseType_t err =0;
    buf = &buff[0];
    
    while (1)
    {
        key = key_scan(0);
        
        if (key == KEY0_PRES || key == KEY1_PRES)
        {
            err = xQueueSend(key_queue, &key, portMAX_DELAY);    /* 将键值作为消息发送到队列中 */
            if(err != pdTRUE)
            {
                printf("key_queue发送失败\r\n");
            }
        }
        else if(key == WKUP_PRES)
        {
            err = xQueueSend(big_date_queue,&buf, portMAX_DELAY);    /* 将键值作为消息发送到队列中 */
            if(err != pdTRUE)
            {
                printf("big_date_queue发送失败\r\n");
            }  
        }
        
        vTaskDelay(10);
    }

}

//4 他上课小数据出队
void task2(void *pvParameters)
{
    uint8_t key = 0;                    //接收从队列中的读取值
    BaseType_t err = 0;
    while(1)
    {
        err=xQueueReceive(key_queue,&key,portMAX_DELAY);
        if(err != pdTRUE)
        {
             printf("key_queue读取失败\r\n");
        }
        else
        {
            printf("key_queue读取队列成功,数据:%d\r\n",key);
        }
    }
   
}

//5 大数据出队
void task3(void *pvParameters)
{
    char* buf = 0;                    //接收从队列中的读取值
    BaseType_t err = 0;
    while(1)
    {
        err=xQueueReceive(big_date_queue,&buf,portMAX_DELAY);
        if(err != pdTRUE)
        {
             printf("big_date_queue读取失败\r\n");
        }
        else
        {
            printf("数据:%s\r\n",buf);
        }
    }
   
}

到了这里,关于FreeRTOS——队列及其实战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32单片机(九)USART串口----第四节:USART串口实战练习(串口发送+接收)

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月10日
    浏览(58)
  • GD32单片机和STM32单片机的对比分析

    GD32单片机和STM32单片机都是基于Arm Cortex-M3/M4内核的32位通用微控制器,广泛应用于各种嵌入式系统和物联网领域。两者之间有很多相似之处,但也有一些不同之处,本文将从以下几个方面对比分析两者的特点、优势和开发成本。 GD32单片机采用的是二代的M3/M4内核,而STM32单片

    2024年02月16日
    浏览(63)
  • STM32单片机(一)STM32简介

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月10日
    浏览(60)
  • STM32单片机(二)STM32环境搭建

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月10日
    浏览(63)
  • STM32单片机开发-01 STM32介绍

    通过野火开发板学习单片机 从内核上分有Cortex-M0、M3、M4 和M7 F1 代表了基础型,基于Cortex-M3 内核,主频为72MHZ F4 代表了高性能,基于Cortex-M4 内核,主频180M。 数据手册:用于芯片选型和设计原理图 参考手册:用于编程时查阅 Icode总线 – 该总线讲M3内核的指令总线与闪存指令

    2024年01月21日
    浏览(63)
  • 【单片机】STM32单片机的各个定时器的定时中断程序,标准库,STM32F103

    高级定时器和普通定时器的区别(https://zhuanlan.zhihu.com/p/557896041): TIM1是高级定时器,使用的时钟总线是RCC_APB2Periph_TIM1,和普通定时器不一样。 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用

    2024年02月07日
    浏览(58)
  • 【STM32】STM32单片机结构及部件原理

    STM32是目前比较常见并且多功能的单片机,要想学习STM32,首先要去了解它的基本构成部分以及各部分的原理。 单片机型号:正点原子STM32F103ZET6 目录 STM32内部结构总览图: 2.内部结构解析         1.内核 :STM32F103ZET6采用的是 ARM Cortex-M3 处理器,内核可以理解为单片机 处

    2023年04月08日
    浏览(51)
  • STM32单片机学习3--STM32控制键盘

    单片机型号:STM32F103C8T6 开发环境:Keil5 4种输入模式 上拉输入模式:在默认状态下(GPIO引脚无输入),读取得的GPIO引脚数据为1,高电平(与Vdd相连的为上拉电阻); 下拉输入模式:在默认状态下(GPIO引脚无输入),读取得的GPIO引脚数据为0,低电平(与Vss相连的为下拉电

    2024年02月10日
    浏览(60)
  • 【单片机】STM32单片机,定时器的输入捕获,基于捕获的频率计,STM32F103

    下面的定时器都具有输入捕获能力: 查看另一篇文章:https://qq742971636.blog.csdn.net/article/details/131471539 外部计数频率计的缺点:需要两个定时器配合,最高能测量的频率是否有限制我没具体尝试。 基于捕获的频率计的缺点:最高能测量的频率有限制。 TIM3_CH1 PWM PA6 10KHZ。 输入

    2024年02月14日
    浏览(58)
  • stm32系列单片机介绍

        stm32是基于ARM® Cortex®  内核的 32位微控制器和微处理器。常见的内核有:     Cortex-M0,代表型号STM32F0、STM32L0;     Cortex-M0+,代表型号STM32C0(23年新推出,主要针对低成本);     Cortex-M3,代表型号STM32F1、STM32F2、STM32L1;     Cortex-M4,代表型号STM32F3(混合信号)、

    2024年02月06日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包