FreeRTOS学习--36讲 队列管理

队列

定义:任务与任务,任务与中断数据交流的一种机制(用于传递信息)

特点:先进先出,也可以设置为先进后出,出队入队可能遇到阻塞,所以设置阻塞时间,自带临界区不能被打断,与全局变量相比更安全

队列的创建

动态创建  xQueueCreate( uxQueueLength,uxItemSize )

参数:队列长度,队列子项的大小                    返回值:NULL失败,非NULL成功

静态创建 xQueueCreateStatic(uxQueueLength,uxItemSize,pucQueueStorage,pxQueueBuffer)

参数:队列长度,队列子项大小,队列存储区域起始地址,静态队列结构体    返回值 :同上

队列的写入

portBASE_TYPE xQueueSend( xQueueHandle         xQueue, 
                                                        const void *         pvItemToQueue, 
                                                        portTickType         xTicksToWait );
参数:目标队列的句柄,指向发送数据 的指针,阻塞超时时间(目标队列已满,就等待)
返回值:pdPASS表示写入成功    errQUEUE_FULL表示写入不成功
xTicksToWait如果设为portMAX_DELAY,并且在FreeRTOSConig.h 中设定 INCLUDE_vTaskSuspend为 
1,那么阻塞等待将没有超时限制。
上面俩API不能在中断服务例程中调用
xQueueSendToFrontFromISR()与xQueueSendToBackFromISR()用于在中断服务中实现相同的功能。

队列的读取

xQueueReceive()与 xQueuePeek()API函数
xQueueReceive()用于从队列中接收(读取)数据单元,接收到的单元同时会从队列中删除。
xQueuePeek()也是从队列中接收数据单元,但不会在队列中删除接收到的单元。
portBASE_TYPE xQueueReceive( xQueueHandle          xQueue, 
                                                        const void *                pvBuffer, 
                                                        portTickType              xTicksToWait );
portBASE_TYPE xQueuePeek( xQueueHandle         xQueue, 
                                                    const void *             pvBuffer, 
                                                    portTickType           xTicksToWait );
参数:被读队列的句柄,指向接收数据缓存区的指针,阻塞超时时间
返回值:pdPASS表示读取成功    errQUEUE_FULL表示读取不成功
xTicksToWait如果设为portMAX_DELAY,并且在FreeRTOSConig.h 中设定 INCLUDE_vTaskSuspend为 1,那么阻塞等待将没有超时限制。
上面俩API不能在中断服务例程中调用
xQueueReceiveFromISR()用于在中断服务中实现相同的功能

队列的查询

uxQueueMessagesWaiting()API函数
unsigned portBASE_TYPE uxQueueMessagesWaiting(xQueueHandle xQueue);
参数:被查询队列的句柄     返回值:保存有数据的单元个数,0则队列为空

临界区保护

taskENATER_CRITICAL(); 进入临界区
taskEXIT_CRITICAL(); 退出临界区
作用:保护那些不想被打断的程序段

队列实验

freertos_demo

//freertos_demo.c

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
#include "./MALLOC/malloc.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO      1
#define START_TASK_STACK_SIZE 128
TaskHandle_t  start_task_handler;
void start_task(void * pvParameters);

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
  */
  
#define TASK1_PRIO      2
#define TASK1_STACK_SIZE 128
TaskHandle_t  task1_handler;
 void task1(void* pv);
 
 /* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
  */
  
#define TASK2_PRIO      2
#define TASK2_STACK_SIZE 128
TaskHandle_t  task2_handler;
 void task2(void* pv);
 
  /* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
  */
  
#define TASK3_PRIO      4
#define TASK3_STACK_SIZE 128
TaskHandle_t  task3_handler;
 void task3(void* pv);
/******************************************************************************************************/

QueueHandle_t key_queue;        //小数据句柄
QueueHandle_t big_data_queue;   //大数据句柄

char buff[200] = {"世界终结前,抓住那最后的闪电,心灵在颤抖,又一次轮回十万年,再来是千年的千年"};
/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    key_queue = xQueueCreate( 2, sizeof(uint8_t) );         //创建小数据队列
    if(key_queue != NULL)
    {
        printf("key_queue创建成功!!!\r\n");
    }else printf("key_queue创建失败!!!\r\n");
    
    big_data_queue = xQueueCreate( 1, sizeof(char *) );         //创建大数据队列
    if(big_data_queue != NULL)
    {
        printf("big_data_queue创建成功!!!\r\n");
    }else printf("big_data_queue创建失败!!!\r\n");
    
    
    xTaskCreate((TaskFunction_t    )    start_task,         //创建开始任务
                (char*             )    "start_task", 
                (unsigned portSHORT)    START_TASK_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    START_TASK_PRIO, 
                (TaskHandle_t*     )    &start_task_handler );
    vTaskStartScheduler();
}

void start_task(void* pvPara)
{
    taskENTER_CRITICAL();         //进入临界区
    xTaskCreate((TaskFunction_t    )    task1,              //创建任务一
                (char*             )    "task1", 
                (unsigned portSHORT)    TASK1_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    TASK1_PRIO, 
                (TaskHandle_t*     )    &task1_handler );
                
    xTaskCreate((TaskFunction_t    )    task2,              //创建任务二
                (char*             )    "task2", 
                (unsigned portSHORT)    TASK2_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    TASK2_PRIO, 
                (TaskHandle_t*     )    &task2_handler );
                
    xTaskCreate((TaskFunction_t    )    task3,              //创建任务二
                (char*             )    "task3", 
                (unsigned portSHORT)    TASK3_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    TASK3_PRIO, 
                (TaskHandle_t*     )    &task3_handler );
    vTaskDelete(NULL);              //删除start_task任务
    taskEXIT_CRITICAL();            //退出临界区
}


//任务一 实现入队
void task1(void* pv)
{
    uint8_t key = 0;
    char* buf;
    BaseType_t err = 0;
    buf = buff;   //buf等于buff[200]的首地址
    while(1)
    {
        key = key_scan(0);
        if(key == KEY0_PRES || key == KEY1_PRES)            //key1还是key0按下
        {
            err = xQueueSend(key_queue,&key,portMAX_DELAY); //发送key值到小数据队列中
            if(err != pdTRUE)                               //判断是否发送成功
            {
                printf("key_queue队列发送失败!!!\r\n");
            }
        }else if(key == WKUP_PRES)                          //key_up按键按下
        {
            err = xQueueSend(big_data_queue,&buf,portMAX_DELAY); //发送buff[200]的首地址到大数据队列中
            if(err != pdTRUE)
            {
                printf("big_data_queue队列发送失败!!!\r\n");
            }
        }
        vTaskDelay(500);
    }
}



//任务二 小数据出队
void task2(void* pv)
{
    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);
        }
    }
}


//任务三 大数据出队
void task3(void* pv)
{
    char * buf;
    BaseType_t err = 0;
    while(1)
    {
        err = xQueueReceive(big_data_queue,&buf,portMAX_DELAY);         //队列读取大数据
        if(err != pdTRUE)
        {
            printf("big_data_queue队列读取失败\r\n");
        }else
        {
            printf("big_data_queue队列读取成功,数据:%s\r\n",buf);
        }
    }
}


//freertos_demo.h

#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H

void freertos_demo(void);

#endif

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SRAM/sram.h"
#include "./MALLOC/malloc.h"
#include "freertos_demo.h"
#include "./BSP/TIMER/btim.h"


int main(void)
{

    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
    delay_init(168);                    /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    led_init();                         /* 初始化LED */
    lcd_init();                         /* 初始化LCD */
    key_init();                         /* 初始化按键 */
    sram_init();                        /* SRAM初始化 */
    
    my_mem_init(SRAMIN);                /* 初始化内部SRAM内存池 */
    my_mem_init(SRAMEX);                /* 初始化外部SRAM内存池 */
    my_mem_init(SRAMCCM);               /* 初始化内部CCM内存池 */
    
    
    delay_ms(10000);                //串口反应迟钝,延时一段时间再发送信息,方便观察结果
    freertos_demo();

}

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值