FreeRTOS之消息队列

2023-05-16

FreeRTOS之消息队列

声明:本人按照正点原子的FreeRTOS例程进行学习的,欢迎各位大佬指责和批评,谢谢!

消息队列的定义

  • 消息队列其实是两个任务之间的数据传递的过程在没有操作系统之前,使用的是全局变量使用了FreeRTOS操作系统,就要使用“队列”的机制来完成任务与任务之间、任务与中断之间的数据传递。
  • 下面是实验举例:Task1任务获取到键值,使用消息队列发送函数;KeyProcess任务中接收到消息队列,使用消息队列接收函数:
  1. 创建消息队列
//按键消息队列的数量																	
#define KEYMSG_Q_NUM    1  				//按键消息队列的数量  													
#define MESSAGE_Q_NUM   4   				//发送数据的消息队列的数量 													
QueueHandle_t Key_Queue;   				//按键值消息队列句柄													
QueueHandle_t Message_Queue;				//信息队列句柄													
void start_task(void *pvParameters)																	
{																	
    taskENTER_CRITICAL();           //进入临界区																	
																	
	//创建消息队列																
    Key_Queue=xQueueCreate(KEYMSG_Q_NUM,sizeof(u8));        //创建消息Key_Queue																	
    Message_Queue=xQueueCreate(MESSAGE_Q_NUM,USART_REC_LEN); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度																	
																	
    //创建TASK1任务								注意:在主函数中需要初始化内部内存池									
    xTaskCreate((TaskFunction_t )task1_task,             								my_mem_init(SRAMIN)				此函数在#include"malloc.h"					
                (const char*    )"task1_task",           								队列中需要申请内存									
                (uint16_t       )TASK1_STK_SIZE,        																	
                (void*          )NULL,                  																	
                (UBaseType_t    )TASK1_TASK_PRIO,        																	
                (TaskHandle_t*  )&Task1Task_Handler);   																	
    //创建TASK2任务																	
    xTaskCreate((TaskFunction_t )Keyprocess_task,     																	
                (const char*    )"keyprocess_task",   																	
                (uint16_t       )KEYPROCESS_STK_SIZE,																	
                (void*          )NULL,																	
                (UBaseType_t    )KEYPROCESS_TASK_PRIO,																	
                (TaskHandle_t*  )&Keyprocess_Handler); 																	
    vTaskDelete(StartTask_Handler); //删除开始任务																	
    taskEXIT_CRITICAL();            //退出临界区																	
}
  1. 发送消息----队列
void task1_task(void *pvParameters)																	
{																	
	u8 key,i;																
	BaseType_t err;																
	while(1)																
	{																
		key = KEY_Scan(0);															
		if((Key_Queue != NULL)&&(key))															
		{															
			err=xQueueSend(Key_Queue,&key,10);														
			if(err==errQUEUE_FULL)   	//发送按键值													
			{														
					printf("队列Key_Queue已满,数据发送失败!\r\n");												
			}														
		}															
		i++;															
		if(i==100)															
		{															
			i=0;														
			LED1=!LED1;														
		}															
		vTaskDelay(10);															
	}																
}
  1. 接收消息----队列
void keyprocess_task(void *pvParameters)																	
{																	
	u8 key;																
	while(1)																
	{																
		if(Key_Queue != NULL)															
		{															
			if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))														
			{														
				switch(key)													
				{													
					case WKUP_PRES:LED0=!LED0;break;												
					case KEY2_PRES:BEEP=!BEEP;break;												
					case KEY0_PRES:printf("已经接收到\r\n");break;												
																	
				}													
			}														
		}															
		vTaskDelay(10);															
	}																
}
  1. 下面是主函数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "lcd.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
#include "beep.h"
#include "queue.h"
#include "malloc.h"

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

#define LED_TASK_PRIO     		        2    //任务优先级
#define LED_STK_SIZE 	                        128  //任务堆栈大小
TaskHandle_t LedTask_Handler;			     //任务句柄
void led_task(void *pvParameters);		     //任务函数

#define TASK1_TASK_PRIO				3    //任务优先级
#define TASK1_STK_SIZE 				256  //任务堆栈大小
TaskHandle_t Task1Task_Handler;			     //任务句柄
void task1_task(void *pvParameters);		     //任务函数

#define TASK2_TASK_PRIO				4	//任务优先级
#define TASK2_STK_SIZE 				128  	//任务堆栈大小
TaskHandle_t Task2Task_Handler;			        //任务句柄
void task2_task(void *pvParameters);			//任务函数
//将字符串中的字母,小写转换为大写
//str:字符串
//len:字符串长度
void LowerToCap(u8 *str,u8 len)
{
	u8 i;
	for(i=0;i<len;i++)
	{
		if((96<str[i]) && (str[i]<123))
		{
			str[i] = str[i] - 32;
		}
	}
}
//LCD显示接收到的队列消息
void disp_str(u8* str)
{
  LCD_Fill(5,230,110,245,WHITE);
  LCD_ShowString(5,230,100,16,16,str);
}
#define KEYMSG_Q_NUM    1     //按键消息队列的数量
#define MESSAGE_Q_NUM   4     //发送数据的消息队列的数量 
QueueHandle_t Key_Queue;      //按键值消息队列句柄
QueueHandle_t Message_Queue;  //信息队列句柄
u8 test;
//LCD刷屏时使用的颜色
int lcd_discolor[14]={	WHITE, BLACK, BLUE,  BRED,      
						GRED,  GBLUE, RED,   MAGENTA,       	 
						GREEN, CYAN,  YELLOW,BROWN, 			
						BRRED, GRAY };
char InfoBuffer[1000];				//保存信息的数组
						
int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	delay_init(168);					//初始化延时函数
	uart_init(115200);     				//初始化串口
  
	LED_Init();		        			//初始化LED端口
	KEY_Init();
	BEEP_Init();
	LCD_Init();							//初始化LCD
  my_mem_init(SRAMIN);     //初始化内存池
  
  
	POINT_COLOR = RED;
	LCD_ShowString(30,10,200,16,16,"ATK STM32F407");	
	LCD_ShowString(30,30,200,16,16,"FreeRTOS 测试");
	LCD_ShowString(30,50,200,16,16,"任务状态查询");
	
	//创建开始任务
    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();          //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
	
    Key_Queue=xQueueCreate(KEYMSG_Q_NUM,sizeof(u8));        //创建消息Key_Queue
    Message_Queue=xQueueCreate(MESSAGE_Q_NUM,USART_REC_LEN); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度

    //创建LED任务
    xTaskCreate((TaskFunction_t )led_task,             
                (const char*    )"keyprocess_task",           
                (uint16_t       )LED_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )LED_TASK_PRIO,        
                (TaskHandle_t*  )&LedTask_Handler);   
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,     
                (const char*    )"task1_task",   
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_TASK_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler); 
    //创建TASK2任务
    xTaskCreate((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler); 
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//task1任务函数
void task1_task(void *pvParameters)
{
	u8 key,i;									
  BaseType_t err;									
  while(1)									
  {	
    
    key = KEY_Scan(1);	//key0返回为1							
    if((Key_Queue != NULL)&&(key))
    {
      vTaskDelay(100);
      if(key == KEY0_PRES)
      {
        test ++;
      }  
      err=xQueueSend(Key_Queue,&test,10);		
      if(err==errQUEUE_FULL)   	//发送按键值						
      {							
          printf("队列Key_Queue已满,数据发送失败!\r\n");					
      } 
    }
    i++;								
    if(i==100)								
    {								
      i=0;							
      LED1=!LED1;							
    }								
    vTaskDelay(10);								
  }									

}

//led0任务函数
void led_task(void *pvParameters)
{	
  while(1)									
  {									
    if(Key_Queue != NULL)								
    {								
      if(xQueueReceive(Key_Queue,&test,portMAX_DELAY))							
      {
        printf("key0 : %d\r\n",test);
      }							
    }	
       
    vTaskDelay(10);								
  }									
}

void task2_task(void *pvParameters)
{
  u8 i;
  while(1)
  {
     i++;								
    if(i==100)								
    {								
      i=0;							
      LED0=!LED0;							
    }	 
    
    vTaskDelay(10);	
  }
}

结束

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS之消息队列 的相关文章

  • 详解FreeRTOS中的软件定时器

    软件定时器用于让某个任务定时执行 或者周期性执行 比如设定某个时间后执行某个函数 或者每隔一段时间执行某个函数 由软件定时器执行的函数称为软件定时器的回调函数 参考资料 Mastering the FreeRTOS Real Time Ke
  • 解决错误“ #error “include FreeRTOS.h“ must appear in source files before “include event_groups.““例子分享

    今天来给大家分享一下 关于之前自己在学习FreeRTOS过程中遇到的一个错误提示 话不多说 我们直接来看 错误分析 首先 我们看一下错误的提示 error 35 error directive include FreeRTOS h must
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • Freertos中vTaskDelay()是怎么用的

    1 常见的使用场景 void vLED Task void pvParameters while 1 Heartbeat LED vTaskDelay 1000 portTICK RATE MS 说明 上面这段代码的意思是 led翻转后经过
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能
  • FreeRTOS+CubeMX系列第一篇——初识FreeRTOS

    文章目录 一 关于FreeRTOS 二 FreeRTOS的特点 三 如何在CubeMX上配置FreeRTOS 四 FreeRTOS文档资料 五 同系列博客 一 关于FreeRTOS 1 什么是FreeRTOS FreeRTOS是一个迷你的实
  • FreeRTOS临界区

    FreeRTOS临界区是指那些必须完整运行 不能被打断的代码段 比如有的外设的初始化需要严格的时序 初始化过程中不能被打断 FreeRTOS 在进入临界区代码的时候需要关闭中断 当处理完临界区代码以后再打开中断 FreeRTOS 系统本身就
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • FreeRTOS_中断

    传送门 博客汇总帖 传送门 Cortex M3 中断 异常 传送门 Cortex M3笔记 基础 笔记内容参考 正点原子的FreeRTOS开发手册 cortex m3权威指南 Cortex M3和Cortex M4权威指南等 文中stm32
  • FreeRTOS临界段和开关中断

    http blog sina com cn s blog 98ee3a930102wg5u html 本章教程为大家讲解两个重要的概念 FreeRTOS的临界段和开关中断 本章教程配套的例子含Cortex M3内核的STM32F103和Co
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS学习(三)开关中断

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 背景知识 Cotex M3的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽 NMI 1个Systick 滴答定时器 Cortex M处理
  • 啊哈C的简单使用

    打开啊哈C 新建一个程序输出hello world include
  • Arduino IDE将FreeRTOS用于STM32

    介绍 适用于STM32F103C8的FreeRTOS STM32F103C是一种能够使用FreeRTOS的ARM Cortex M3处理器 我们直接在Arduino IDE中开始使用STM32F103C8的FreeRTOS 我们也可以使用K
  • RT-Thread记录(五、RT-Thread 临界区保护与FreeRTOS的比较)

    本文聊聊临界区 以及RT Thread对临界区的处理 通过源码分析一下 RT Thread 对临界区保护的实现以及与 FreeRTOS 处理的不同 目录 前言 一 临界区 1 1 什么是临界区 1 2 RTOS中的临界区 二 RT Thre
  • FreeRTOS实时操作系统(三)任务挂起与恢复

    系列文章 FreeRTOS实时操作系统 一 RTOS的基本概念 FreeRTOS实时操作系统 二 任务创建与任务删除 HAL库 FreeRTOS实时操作系统 三 任务挂起与恢复 FreeRTOS实时操作系统 四 中断任务管理 FreeRTO
  • FreeRTOS多任务调度器基础

    Cortex M4中SysTick调度器核心 Cortex M4中的中断管理 Cortex M4中影子栈指针 Cortex M4中SVC和PendSV异常 1 Cortex M4中SysTick调度器核心 systick每一次中断都会触发内
  • 使用 GCC 编译器的 ARM 内核的堆栈回溯(当存在 MSP 到 PSP 切换时)

    核心 ARM Cortex M4 编译器 GCC 5 3 0 ARM EABI 操作系统 免费 RTOS 我正在使用 gcc 库函数 Unwind Reason Code Unwind Backtrace Unwind Trace Fn v
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d

随机推荐

  • 使用c++模板的优点和缺点

    作为C 43 43 语言的新组成部分 xff0c 模板引入了基于通用编程的概念 通用编程是一种无须考虑特定对象的描述和发展算法的方法 xff0c 因此它与具体数据结构无关 但在决定使用C 43 43 模板之前 xff0c 让我们分析一下使用
  • kalibr 进行相机单目、双目标定全流程

    一 部署kalibr环境 docker 步骤 xff1a 参考链接 xff1a Installation ethz asl kalibr Wiki GitHub Docker操作知识 xff1a Docker攻略 xff1a 从安装到入门到
  • kalibr源码阅读参考

    Kalibr简介 xff1a Kalibr是一个用于标定多相机系统和IMU xff08 惯性测量单元 xff09 的开源工具包 xff0c 旨在提供一套完整的 易于使用的标定工具 它是ETH Zurich自主飞行系统实验室的一个项目 xff
  • QT5.11.1下的DirectShowPlayerService::doRender: Unresolved error code 0x80040266 ()报错)

    64 TOC QT5 11 1下的DirectShowPlayerService doRender Unresolved error code 0x80040266 报错 1 实验环境 实验环境 xff1a xff08 1 xff09 QT
  • GPS定位中的卡尔曼滤波算法

    卡尔曼滤波 xff1a 卡尔曼滤波由预测和校正两部分组成 预测部份又称时间更新过程 xff0c 是在上一个历元 k 1 状态估计值的基础上 xff0c 利用系统的状态方程来预测当前历元 k 的状态值 校正部分又叫测量更新过程 xff0c 它
  • 古月居ROS21讲入门(10)发布者Publisher的编程实现(源代码详解)

    发布者Publisher的编程实现 源代码详解 一 话题模型二 创建learning topic功能包三 实现一个发布者1 初始化ROS节点2 注册节点信息3 创建消息数据 四 配置CMakeLists txt中的编译规则五 编译并运行发布
  • STM32自学笔记串口DMA发送/接收 FIFO 突发模式

    参考博文 串口发送TXPA9DMA2 Stream7通道4正常模式串口发送RXPA10DMA2 Stream5通道4循环模式 串口波特率115200 PA9 PA10复用输出 注意点 串口接受数据dma方式不能开启串口接受中断 Dma双缓冲
  • 【STM32】标准库-自定义BootLoader

    Bootloader bootloader其实就是一段启动程序 xff0c 它在芯片启动的时候最先被执行 xff0c 可以用来做一些硬件的初始化或者用作固件热更新 xff0c 当初始化完成之后跳转到对应的应用程序中去 bootloader程
  • 【数据结构】使用结构体指针时需要使用malloc

    如果定义一个结构体类型的普通变量 xff0c 可以不malloc动态申请内存 xff0c CPU会为这个结构体变量分配内存 如果定义的是一个结构体的指针 xff0c CPU会为这个指针开辟内存 xff0c 但是此时这个大小是4 xff08
  • fwrite乱码问题

    我们这里数据格式为 201911606 liu 1 1 1 2 99 201911607 wang 1 2 1 3 98 fwrite写入文件是二进制代码形式 xff0c 所以用文本打开为乱码 xff0c 这时候我们可以用fprintf代替
  • ubuntu下使用kazam录屏与视频解码(亲测视频在windows可用)

    Ubuntu中难免会使用录屏软件记录试验过程 xff0c 本博客采用kazam软件录屏 xff0c 并将录屏软件解码 xff0c 解码文件可以复制到windows使用 1 kazam安装 安装命令 xff1a span class toke
  • 高通MSM8998芯片数据资料参考

    高通MSM8998芯片数据资料参考 今日分享是高通MSM8998芯片的基础知识 xff0c 现在分享是比较基础的资料 xff0c 还有其他的项目案例和参考资料找个时间再分享出来 xff0c 资料都在闯客网技术论坛上 xff0c 也是可以免费
  • 深度学习中epoch,batch的概念--笔记

    深度学习中epoch xff0c batch的概念 batch epoch和iteration是深度学习中几个常见的超参数 1 batch size 每批数据量的大小 DL通常用SGD的优化算法进行训练 xff0c 也就是一次 1 个ite
  • 基于Ubuntu的嵌入式开发练习(十)FreeRTOS的移植和设计一个基本的多任务程序

    如有错误 xff0c 欢迎指正 xff0c 谢谢 xff01 目录 一 FreeRTOS的移植二 建立一个基本的多任务程序1 实验要求2 代码设计3 执行效果 一 FreeRTOS的移植 教程 视频 xff1a 野火 FreeRTOS视频教
  • 嵌入式软件工程师总结(1)

    1 说说进程和线程的区别 答 xff1a 简单的来说 一个程序至少有一个进程 一个进程至少有一个线程 第一点 进程有自己的独立地址空间 xff0c 每启动一个进程 xff0c 系统就会为它分配地址空间 xff0c 建立数据表来维护代码段 堆
  • Centos下Django部署到Apache

    Centos 43 Django 43 Apache部署 版本 xff1a python3 6 Centos7 6 Django3 2 Apache2 4 1 安装python3 默认3 6 yum install python3 pyth
  • 云服务器Docker运行ROS,并通过VNC连接

    云服务器Docker运行ROS xff0c 并通过VNC连接 使用华为云服务器系统Ubuntu18VNC为x11vnc 安装图形界面 选择Xubuntu界面 xff0c 占用资源较少 xff0c 参考链接ubuntu安装gui 直接安装即可
  • 切换系统的概述

    切换系统的概述 切换系统 switched system 是一类混合系统 xff0c 即一类混杂系统 切换系统是由若干个切换子系统和以一条 贯穿 所有子系统的切换规则组成的 组成切换子系统可能只是一个结构简单 动态特性简单的基础控制系统 x
  • 更改Win10与Ubuntu双系统的默认进入系统为Windows

    一 每次开机 xff0c 不进行系统选择 xff0c 就会直接进入到第一个系统 xff0c 即Ubuntu系统 xff0c 想让他自动进入Win10系统 原因 xff1a Ubuntu系统位于第一位 解决方法 xff1a 1 开机或者重启
  • FreeRTOS之消息队列

    FreeRTOS之消息队列 声明 xff1a 本人按照正点原子的FreeRTOS例程进行学习的 xff0c 欢迎各位大佬指责和批评 xff0c 谢谢 xff01 消息队列的定义 消息队列其实是两个任务之间的数据传递的过程 xff0c 在没有