FreeRTOS之消息队列

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);	
  }
}

结束

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值