FreeRTOS中的消息队列(基本)

队列

队列(Queue)是一种数据结构,用于存储和管理元素的线性集合。它遵循先进先出(FIFO,First-In-First-Out)的原则,即最先进入队列的元素将首先被移出队列。

队列通常具有两个基本操作:

  1. 入队(Enqueue):将元素添加到队列的末尾。新元素进入队列后成为新的队尾。
  2. 出队(Dequeue):从队列的头部移除并返回元素。被移除的元素为队列中存在时间最长的元素,即最先入队的元素。

队列的特性使其非常适合在任务间进行数据传递和通信。任务可以将数据或消息按顺序放入队列,并按照先入先出的原则进行处理。这种方式可以有效地实现任务间的解耦和异步通信。

队列可以具有固定大小或动态增长的能力,取决于具体的实现和需求。固定大小的队列在创建时需要指定最大容量,而动态队列可以根据需要进行扩展。

消息队列

顾名思义,消息队列就是存储消息的队列。遵循队列的规则。

在 FreeRTOS 中,消息队列(Message Queue)是一种用于任务间通信的机制,允许任务之间传递和共享数据。消息队列提供了一种异步的通信方式,发送任务可以将消息放入队列,接收任务则可以从队列中获取消息。

以下是 FreeRTOS 消息队列的一些关键概念:

  1. 队列大小(Queue Size):消息队列具有固定的容量,即可以容纳的消息数量。在创建队列时,需要指定队列的大小。
  2. 消息类型(Message Type):消息队列可以传递不同类型的消息,消息类型可以是任意数据结构,如整数、结构体、指针等。
  3. 发送任务(Sending Task):发送任务负责将消息发送到队列中。发送任务通过调用 xQueueSend() 或 xQueueSendFromISR() 函数将消息发送到队列。
  4. 接收任务(Receiving Task):接收任务负责从队列中获取消息。接收任务通过调用 xQueueReceive() 或 xQueueReceiveFromISR() 函数从队列中获取消息。
  5. 阻塞与非阻塞操作:发送任务和接收任务可以选择在操作队列时是阻塞还是非阻塞的。阻塞操作会使任务在队列操作无法立即执行时进入阻塞状态,而非阻塞操作则会立即返回,无论队列操作是否成功。

使用消息队列可以实现任务之间的数据传递和同步。发送任务可以将数据封装成消息,并将其发送到队列中,接收任务则可以从队列中获取消息并进行处理。消息队列可以用于解耦任务之间的通信,提高系统的灵活性和可维护性。

功能介绍

基础API如下

功能

描述

xQueueCreate

创建队列

xQueueSend

向队列中添加元素

xQueueReceive

从队列中取出元素

创建队列

xQueueCreate( uxQueueLength, uxItemSize )

向队列中放数据

参数一:队列名称

参数二:数据地址

参数三:等待时间

xQueueSend( xQueue, pvItemToQueue, xTicksToWait )

从队列中取数据

参数一:队列名称

参数二:给队列一个指针,把数据拷贝到这个指针里面

参数三:等待时间

void task1() {
	uint8_t cnt;
    while(1) {
		//从队列里面取数据
		printf("wait recv.. \r\n");
		xQueueReceive(queue,&cnt,portMAX_DELAY);
        printf("recv: cnt %x\r\n",cnt);
    }
    vTaskDelete(0);
}

全部代码

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "Usart0.h"
#include "semphr.h"


TaskHandle_t StartTask_Handler;
TaskHandle_t Task1_Handler;
TaskHandle_t Task2_Handler;
TaskHandle_t Task_key_Handler;

SemaphoreHandle_t semap_handler;

QueueHandle_t queue;

void Usart0_on_recv(uint8_t* data, uint32_t len) {

}

void task1() {
	uint8_t cnt;
    while(1) {
		//从队列里面取数据
		printf("wait recv.. \r\n");
		xQueueReceive(queue,&cnt,portMAX_DELAY);
        printf("recv: cnt %x\r\n",cnt);
    }
    vTaskDelete(0);
}


void task2() {
	
    while(1) {
        

    }
    vTaskDelete(0);
}

void task_key(void *pvParameters) {
    //PA0
    FlagStatus pre = RESET;
    uint8_t cnt = 0;
    while(1) {
        FlagStatus current = gpio_input_bit_get(GPIOA,GPIO_PIN_0);
        if(RESET == current && pre == SET) {
            //抬起
            pre = current;
			
        } else if(SET == current && pre == RESET) {
            //按下
            pre = current;
			//向队列中放数据 
			printf("send : cnt %x\r\n",cnt);
			xQueueSend(queue,&cnt,portMAX_DELAY);
			cnt++;
        }
        vTaskDelay(20);
    }
    vTaskDelay(0);
}

void start_task(void *pvParameters) {
    taskENTER_CRITICAL();
	
		//创建队列
	queue = xQueueCreate(10,sizeof(uint8_t));
	
	
	
    xTaskCreate((TaskFunction_t)task1,
                (const char*   )"task1",
                50,
                NULL,
                2,
                (TaskHandle_t*  )&Task1_Handler);

//    xTaskCreate((TaskFunction_t)task2,
//                (const char*   )"task2",
//                50,
//                NULL,
//                3,
//                (TaskHandle_t*  )&Task2_Handler);


    xTaskCreate((TaskFunction_t)task_key,
                (const char*   )"task_key",
                50,
                NULL,
                5,
                (TaskHandle_t*  )&Task_key_Handler);


    vTaskDelete(StartTask_Handler);
    taskEXIT_CRITICAL();
}

static void GPIO_config() {

    //唤醒按键
    // 时钟初始化
    rcu_periph_clock_enable(RCU_GPIOA);
    // 配置GPIO模式
    gpio_mode_set(GPIOA, GPIO_MODE_INPUT,GPIO_PUPD_PULLDOWN, GPIO_PIN_0);
}

int main(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
    systick_config();
    GPIO_config();
    Usart0_init();

    printf("mian ======= ...start\r\n");

    //1.创建任务
    //参数一:哪个任务
    //参数二:任务名字
    //参数三:栈的深度(宽度).
    //参数四:优先级
    //参数五:句柄,任务的引用


    xTaskCreate(start_task,"start_task",64,NULL,1,&StartTask_Handler);
    //开启调度器
    vTaskStartScheduler();

    while(1) {

    }
}

执行效果如下图

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值