FreeRTOS队列

在实际应用中,我们会遇到一个任务或者中断服务需要和另一个任务进行消息传递,FreeRTOS提供了队列的机制来完成任务与任务、任务与中断之间的消息传递。

0x01 队列简介

队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。队列中能保存的最大数据项目数量叫做队列的长度。

1. 数据存储

队列提供了FIFO、LIFO的存储缓冲机制,数据发送到队列中会导致数据拷贝,数据拷贝是值传递,在队列中存储的是数据的原始值,而不是原始值的引用(即值传递数据的引用),FreeRTOS中使用队列传递消息的话虽然使用的是数据拷贝,但是也可以使用引用来传递消息,直接往队列中发送指向这个消息的地址指针就可以了。

2. 多任务访问

队列不属于某个特别指定的任务,任何任务都可以向队列中发送消息,提取消息

0x02 队列结构体

队列的类型是Queue_t,定义在queue.c文件中

typedef struct QueueDefinition
{int8_t *pcHead;					/*< Points to the beginning of the queue storage area. */int8_t *pcTail;					/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */int8_t *pcWriteTo;				/*< Points to the free next place in the storage area. */union							/* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */{int8_t *pcReadFrom;			/*< Points to the last place that a queued item was read from when the structure is used as a queue. */UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */} u;List_t xTasksWaitingToSend;		/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */List_t xTasksWaitingToReceive;	/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */UBaseType_t uxLength;			/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */UBaseType_t uxItemSize;			/*< The size of each items that the queue will hold. */volatile int8_t cRxLock;		/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */volatile int8_t cTxLock;		/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */#endif#if ( configUSE_QUEUE_SETS == 1 )struct QueueDefinition *pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif} xQUEUE;/* The old xQUEUE name is maintained above then typedefed to the new Queue_t
name below to enable the use of older kernel aware debuggers. */
typedef xQUEUE Queue_t;
  • pcHead:指向队列存储区首地址
  • pcTail:指向队列存储区最后一个字节地址
  • pcWriteTo:指向下一个可以存储的地址
  • pcReadFrom:当用作队列的时候,指向最后一个出队的队列项首地址
  • uxRecursiveCallCount:当用作递归互斥量的时候用来记录递归互斥量被调用的次数
  • xTasksWaitingToSend:等待发送任务列表,那些因为队列满导致入队失败而进入阻塞态的任务就会挂到此列表上
  • xTasksWaitingToReceive:等待接受任务列表,那些因为队列空导致出队失败而进入阻塞态的任务就会挂到此列表上
  • uxMessagesWaiting:队列中当前消息数
  • uxLength:队列中最大允许的消息数量
  • uxItemSize:每个消息最大长度
  • cRxLock:当列表上锁后,统计出队的消息数量
  • cTxLock:当列表上锁后,统计入队的消息数量

0x03 队列创建

队列创建有两种方法:

  1. 方法1:使用xQueueCreate函数动态创建
  2. 方法2:使用xQueueCreateStatic动态创建
1. xQueueCreate

从源码可以看出,使用xQueueCreate,configSUPPORT_DYNAMIC_ALLOCATION 要等于1,支持动态分配内存

 QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,UBaseType_t uxItemSize)
  • uxQueueLength:要创建的队列的队列长度,即最多可以接受多少个消息
  • uxItemSize :队列中每个消息的长度

创建成功返回队列句柄,失败返回NULL

2.xQueueCreateStatic
 QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorageBuffer,StaticQueue_t *pxQueueBuffer);
  • uxQueueLength:要创建的队列的队列长度,即最多可以接受多少个消息
  • uxItemSize :队列中每个消息的长度
  • pucQueueStorage:指向消息的存储区,是一个uint8_t类型的数组,数组的大小要大于等于(uxQueueLength*uxItemSize )
  • pxQueueBuffer :保存队列结构体

创建成功返回队列句柄,失败返回NULL

0x04 向队列发送消息

1. 函数原型

创建好队列就可以向队列发送消息了,FreeRTOS提供了8个向对列发送消息的API函数。
在这里插入图片描述

1.1 xQueueSend、xQueueSendToBack、xQueueSendToToFront
 BaseType_t xQueueSend(QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);BaseType_t xQueueSendToBack(QueueHandle_t	xQueue,const void		*pvItemToQueue,TickType_t		xTicksToWait);BaseType_t xQueueSendToToFront(QueueHandle_t	xQueue,const void		*pvItemToQueue,TickType_t		xTicksToWait);
  • QueueHandle_t xQueue:任务句柄,指明要向那个队列发送数据
  • const void *pvItemToQueue:指向要发送的数据,发送的时候会将这个消息拷贝到队列中
  • TickType_t xTicksToWait:阻塞时间,此参数指示队列满的时候任务进入阻塞态等待队列空闲的最大时间,如果是0,队列满会立即返回,当为portMAX_DELAY就会一直等待。

成功返回pdPASS,失败返回errQUEUE_FULL

1.2 xQueueOverwrite
 BaseType_t xQueueOverwrite(QueueHandle_t xQueue,const void * pvItemToQueue);
  • QueueHandle_t xQueue:队列句柄,指明要向那个队列发送数据
  • const void * pvItemToQueue:要发送的数据
1.3 xQueueSendFromISR、xQueueSendToBackFromISR、xQueueSendToFrontFromISR
 BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue,const void * pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);
  • QueueHandle_t xQueue:队列句柄,指明要向那个队列发送数据
  • const void *pvItemToQueue:要发送的数据
  • BaseType_t *pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换,这个变量由三个函数来设置,用户不用进行设置,用户只需提供一个变量来保存这个值就行了。当此值为pdTRUE的时候在退出中断服务函数之前一定要进行一次任务切换。

成功返回pdTURE,失败返回errQUEUE_FULL

0x05 从队列读取消息

从队列中获取消息,FreeRTOS相关API函数如下
在这里插入图片描述

1. xQueueReceive、xQueuePeek
BaseType_t xQueueReceive(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait)BaseType_t xQueuePeek(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait);
  • QueueHandle_t xQueue:指明读取那个队列的数据
  • void *pvBuffer:读取队列的过程中将读取的数据拷贝到这个缓冲区
  • TickType_t xTicksToWait:阻塞时间,如果为0,队列为空立即返回,当为portMAX_DELAY的话就一直等待,直到队列有数据。
2. xQueueReceiveFromISR
 BaseType_t xQueueReceiveFromISR(QueueHandle_t	xQueue,void	*pvBuffer,BaseType_t *pxTaskWoken);BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,void *pvBuffer,);
  • QueueHandle_t xQueue:指明读取那个队列的数据
  • void *pvBuffer:读取队列的过程中将读取的数据拷贝到这个缓冲区
  • BaseType_t *pxTaskWoken:标记退出此函数以后是否进行任务切换

返回值:
返回pdTRUE,从队列中读取数据成功,返回pdFALSE,从队列中读取数据失败。

验证

实验设计三个任务,start_task、task1_task、Keyprocess_task这三个任务。
start_task:用来创建其他两个任务
task1_task:读取按键的键值,然后将键值发送到KEY_Queue队列中,并且检查队列的剩余容量等信息
Keyprocess_task:按键处理任务,读取队列Key_Queue中的信息,根据不同的消息值做相应的处理。
实验需要是哪个按键KEY_UP、KEY2、KEY0,不同的按键对应不同的按键值,任务task1_task会将这些值发送到队列Key_Queue中。
实验中创建两个队列Key_Queue和Message_Queue,队列Key_Queue用于传递按键值,队列Message_Queue用于传递串口发送过来的消息。
实验还需要两个中断,一个是串口1接收中断,一个是定时器9中断,他们的作用如下:串口1接收中断,接收串口发送过来的数据,并将接收到的数据发送到队列Message_Queue中,定时器9中断,定时周期为500ms,在定时器中断中读取队列Message_Queue中的消息,并将其显示在LCD上。

start_task代码:

//开始任务任务函数
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建消息队列Key_Queue=xQueueCreate(KEYMSG_Q_NUM,sizeof(u8));        //创建消息Key_QueueMessage_Queue=xQueueCreate(MESSAGE_Q_NUM,USART_REC_LEN); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度//创建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 )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();            //退出临界区
}

在start_task中创建了两个队列,分别是Key_Queue和Message_Queue,Key_Queue用于和按键通信,Message_Queue用于和串口通信。

task1_task代码

//task1任务函数
void task1_task(void *pvParameters)
{u8 key,i=0;BaseType_t err;while(1){key=KEY_Scan(0);            //扫描按键if((Key_Queue!=NULL)&&(key))   //消息队列Key_Queue创建成功,并且按键被按下{err=xQueueSend(Key_Queue,&key,10);if(err==errQUEUE_FULL)   //发送按键值{printf("队列Key_Queue已满,数据发送失败!\r\n");}}i++;if(i%10==0) check_msg_queue();//检Message_Queue队列的容量if(i==50){i=0;LED0=!LED0;}vTaskDelay(10);                           //延时10ms,也就是10个时钟节拍	}
}

task1_task获取按键值,并将按键值发送到Key_Queue中

Keyprocess_task代码:

//Keyprocess_task函数
void Keyprocess_task(void *pvParameters)
{u8 num,key,beepsta=1;while(1){if(Key_Queue!=NULL){if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))//请求消息Key_Queue{switch(key){case WKUP_PRES:		//KEY_UP控制LED1LED1=!LED1;break;case KEY1_PRES:		//KEY1控制蜂鸣器beepsta=!beepsta;BEEP=beepsta;break;case KEY0_PRES:		//KEY0刷新LCD背景num++;LCD_Fill(126,111,233,313,lcd_discolor[num%14]);break;}}} vTaskDelay(10);      //延时10ms,也就是10个时钟节拍	}
}

Keyprocess_task获取Key_Queue队列中按键值

整个main.c代码如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "sdram.h"
#include "key.h"
#include "timer.h"
#include "beep.h"
#include "string.h"
#include "malloc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/************************************************ALIENTEK 水星STM32F429开发板 FreeRTOS实验13-1FreeRTOS队列操作实验-HAL库版本技术支持:www.openedv.com淘宝店铺:http://eboard.taobao.com 关注微信公众平台微信号:"正点原子",免费获取STM32资料。广州市星翼电子科技有限公司  作者:正点原子 @ALIENTEK
************************************************///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		256  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define TASK1_TASK_PRIO		2
//任务堆栈大小	
#define TASK1_STK_SIZE 		256  
//任务句柄
TaskHandle_t Task1Task_Handler;
//任务函数
void task1_task(void *pvParameters);//任务优先级
#define KEYPROCESS_TASK_PRIO 3
//任务堆栈大小	
#define KEYPROCESS_STK_SIZE  256 
//任务句柄
TaskHandle_t Keyprocess_Handler;
//任务函数
void Keyprocess_task(void *pvParameters);//按键消息队列的数量
#define KEYMSG_Q_NUM    1  		//按键消息队列的数量  
#define MESSAGE_Q_NUM   4   	//发送数据的消息队列的数量 
QueueHandle_t Key_Queue;   		//按键值消息队列句柄
QueueHandle_t Message_Queue;	//信息队列句柄//LCD刷屏时使用的颜色
int lcd_discolor[14]={	WHITE, BLACK, BLUE,  BRED,      GRED,  GBLUE, RED,   MAGENTA,       	 GREEN, CYAN,  YELLOW,BROWN, 			BRRED, GRAY };//用于在LCD上显示接收到的队列的消息
//str: 要显示的字符串(接收到的消息)
void disp_str(u8* str)
{LCD_Fill(5,230,110,245,WHITE);					//先清除显示区域LCD_ShowString(5,230,100,16,16,str);
}//加载主界面
void freertos_load_main_ui(void)
{POINT_COLOR = RED;LCD_ShowString(10,10,200,16,16,"Apollo STM32F4/F7");	LCD_ShowString(10,30,200,16,16,"FreeRTOS Examp 13-1");LCD_ShowString(10,50,200,16,16,"Message Queue");LCD_ShowString(10,70,220,16,16,"KEY_UP:LED1 KEY0:Refresh LCD");LCD_ShowString(10,90,200,16,16,"KEY1:SendMsg KEY2:BEEP");POINT_COLOR = BLACK;LCD_DrawLine(0,107,239,107);		//画线LCD_DrawLine(119,107,119,319);		//画线LCD_DrawRectangle(125,110,234,314);	//画矩形POINT_COLOR = RED;LCD_ShowString(0,130,120,16,16,"DATA_Msg Size:");LCD_ShowString(0,170,120,16,16,"DATA_Msg rema:");LCD_ShowString(0,210,100,16,16,"DATA_Msg:");POINT_COLOR = BLUE;
}//查询Message_Queue队列中的总队列数量和剩余队列数量
void check_msg_queue(void)
{u8 *p;u8 msgq_remain_size;	//消息队列剩余大小u8 msgq_total_size;     //消息队列总大小taskENTER_CRITICAL();   //进入临界区msgq_remain_size=uxQueueSpacesAvailable(Message_Queue);//得到队列项剩余大小msgq_total_size=uxQueueMessagesWaiting(Message_Queue)+uxQueueSpacesAvailable(Message_Queue);//得到队列总大小,总大小=使用+剩余的。p=mymalloc(SRAMIN,20);	//申请内存sprintf((char*)p,"Total Size:%d",msgq_total_size);	//显示DATA_Msg消息队列总的大小LCD_ShowString(10,150,100,16,16,p);sprintf((char*)p,"Remain Size:%d",msgq_remain_size);	//显示DATA_Msg剩余大小LCD_ShowString(10,190,100,16,16,p);myfree(SRAMIN,p);		//释放内存taskEXIT_CRITICAL();    //退出临界区
}int main(void)
{HAL_Init();                     //初始化HAL库   Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhzdelay_init(180);                //初始化延时函数uart_init(115200);              //初始化串口LED_Init();                     //初始化LED KEY_Init();                     //初始化按键BEEP_Init();                 	//初始化蜂鸣器SDRAM_Init();                   //初始化SDRAMLCD_Init();                     //初始化LCDTIM9_Init(5000,18000-1);		//初始化定时器9,周期500msmy_mem_init(SRAMIN);            //初始化内部内存池freertos_load_main_ui();        //加载主UI//创建开始任务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_QueueMessage_Queue=xQueueCreate(MESSAGE_Q_NUM,USART_REC_LEN); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度//创建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 )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();            //退出临界区
}//task1任务函数
void task1_task(void *pvParameters)
{u8 key,i=0;BaseType_t err;while(1){key=KEY_Scan(0);            //扫描按键if((Key_Queue!=NULL)&&(key))   //消息队列Key_Queue创建成功,并且按键被按下{err=xQueueSend(Key_Queue,&key,10);if(err==errQUEUE_FULL)   //发送按键值{printf("队列Key_Queue已满,数据发送失败!\r\n");}}i++;if(i%10==0) check_msg_queue();//检Message_Queue队列的容量if(i==50){i=0;LED0=!LED0;}vTaskDelay(10);                           //延时10ms,也就是10个时钟节拍	}
}//Keyprocess_task函数
void Keyprocess_task(void *pvParameters)
{u8 num,key,beepsta=1;while(1){if(Key_Queue!=NULL){if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))//请求消息Key_Queue{switch(key){case WKUP_PRES:		//KEY_UP控制LED1LED1=!LED1;break;case KEY1_PRES:		//KEY1控制蜂鸣器beepsta=!beepsta;BEEP=beepsta;break;case KEY0_PRES:		//KEY0刷新LCD背景num++;LCD_Fill(126,111,233,313,lcd_discolor[num%14]);break;}}} vTaskDelay(10);      //延时10ms,也就是10个时钟节拍	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

剧情介绍:“阿甘正传”

阿甘是个智商只有75的低能儿。在学校里为了躲避别的孩子的欺侮&#xff0c;听从一个朋友珍妮的话而开始“跑”。他跑着躲避别人的捉弄。在中学时&#xff0c;他为了躲避别人而跑进了一所学校的橄榄球场&#xff0c;就这样跑进了大学。阿甘被破格录取&#xff0c;并成了橄榄球巨…

FreeRTOS信号量---二值信号量

信号量可以用来进行资源管理和任务同步&#xff0c;FreeRTOS中信号量又分为二值信号量、计算型信号量、互斥信号量和递归互斥信号量。 0x01 二值信号量 二值信号量其实就是一个只有一个队列项的队列&#xff0c;这个特殊的队列要么是满的&#xff0c;要么是空的&#xff0c;任…

FreeRTOS软件定时器

软件定时器允许设置一段时间&#xff0c;当设置的时间达到后就执行指定的功能函数&#xff0c;被软件定时器调用的功能函数叫做定时器的回调函数。软件定时器的回调函数是在定时器服务任务中执行的&#xff0c;所以一定不能在回调函数中调用任何阻塞任务的API函数&#xff0c;比…

WP7之Application Bar控件

Microsoft.Phone.Shell命名空间中定义了ApplicationBar及其相关类&#xff08;ApplicationBarIconButton和ApplicationBarMenuItem&#xff09;&#xff0c;这些类派生自Object,并完全独立于常规Silverlight编程中的DependencyObject,UIElement和FrameworkElement类层次结构。A…

TomCat使用以及端口号被占用的处理方法

一.HTTP协议 什么是HTTP协议 HTTP协议&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是因特网上应用最为广泛的一种网络传输协议&#xff0c;所有的WWW文件都必须遵守这个标准。 HTTP请求 HTTP响应 2.如何处理端口被占用 方法一&#xff…

FreeRTOS事件标志组

使用信号量来同步的话&#xff0c;任务只能与单个事务或任务进行同步&#xff0c;有时候某个任务可能会需要与多个事件或任务进行同步&#xff0c;此时信号量就无能为力了&#xff0c;FreeRTOS为此提供了一个可选的解决方法&#xff0c;那就是事件标志组。 0x01 事件标志组 事…

FusionCharts等产品简介

以前做柱状图、饼形图等图表都是根据数据绘制出来的静态图&#xff0c;偶然看到别人的一套系统&#xff0c;居然可以让柱状图的柱子动画般的逐个出现&#xff0c;效果还是很不错的。不要跟我抬杠说不就是展现数据嘛&#xff0c;静态图表有什么不好&#xff0c;要知道用户一般可…

Eclipse和Tomcat绑定并且将上传资源到Tomcat上

步骤如下&#xff1a; 创建一个Dynamic Web Project&#xff08;图一&#xff09; Target runtime 选择Apache Tomcat v7.0版本&#xff08;图二&#xff09; 切记要选择 v7.0 和2.5 &#xff08;若没有图二选项见图三&#xff09; 然后&#xff0c;点击window --> Prefer…

FreeRTOS任务通知

从v8.2.0版本开始&#xff0c;FreeRTOS新增了任务通知这个功能&#xff0c;可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西&#xff0c;使用任务通知的话效率会更高。 任务通知在FreeRTOS是一个可选的选项&#xff0c;要使用任务通知的话就需要将宏configUSE_T…

kinect在openni下也能玩抠出人物换背景

之前想了个很拉风的名字《用kinect玩穿越》&#xff0c;但是现在功能还不是很完善&#xff0c;细节处理也不是很好&#xff0c;脸皮没有足够的厚&#xff0c;所以呢还是叫换背景吧。 这里面包含两个技术要点&#xff1a; 一、抠出活动人物 在微软的SDK里深度图像的前3位即0-2位…

Emit学习-基础篇-基本概念介绍

之前的Hello World例子应该已经让我们对Emit有了一个模糊的了解&#xff0c;那么Emit到底是什么样一个东西&#xff0c;他又能实现些什么功能呢&#xff1f;昨天查了点资料&#xff0c;大致总结了下&#xff0c;由于才开始学习肯定有不完善的地方&#xff0c;希望大家能够批评指…

The FreeRTOS Distribution(介绍、移植、类型定义)

1 Understand the FreeRTOS Distribution 1.1 Definition &#xff1a;FreeRTOS Port FreeRTOS目前可以在20种不同的编译器构建&#xff0c;并且可以在30多种不同的处理器架构上运行&#xff0c;每个受支持的编译器和处理器组合被认为是一个单独的FreeRTOS Port。 1.2 Build…

Eclipse项目左上角出现大红色感叹号怎么办?

出现大红色感叹号是因为环境不匹配 解决方法&#xff1a; 右击出现大红色感叹号的项目 点击 Libraries&#xff0c;将有叉号的给Remove掉 然后再点击 Add Library —> JRE System Library —> Next 勾选第二个即可 之后&#xff0c;就不会出现大红色感叹号了。

PCB---STM32最小系统制作过程

PCB 制作过程STM32核心模块连接外部电源晶振OSC_IN(8MHz)OSC32_IN(32.768MHz&#xff09;复位下载口BOOT模式电源模块添加功能UARTWKUPSTM32核心模块 这里我们以STM32F103C8T6为列&#xff0c;先将芯片的原理图放到原理图中 对于STM32&#xff0c;有几个模块是核心&#xff0…

FreeRTOS---堆内存管理(一)

FreeRTOS的堆内存管理简介动态内存分配及其与 FreeRTOS 的相关性动态内存分配选项内存分配方案Heap_1heap_2Heap_3Heap_4设置heap_4的起始地址Heap_5vPortDefineHeapRegions()堆相关的函数xPortGetFreeHeapSizexPortGetMinimumEverFreeHeapSizeMalloc调用失败的Hook函数这篇文章…

FreeRTOS--堆内存管理(二)

堆内存管理代码具体实现heap_1内存申请函数内存释放函数heap_2内存块内存堆初始化函数内存块插入函数内存申请函数判断是不是第一次申请内存开始分配内存内存释放函数heap_3heap_4内存堆初始化函数内存块插入函数heap_5上一篇文章说了FreeRTOS实现堆内存的原理&#xff0c;这一…

css中的node.js_在Node App中使用基本HTML,CSS和JavaScript

css中的node.jsYou may think this is not important, but it is!. As a beginner in node.js, most coding exercises are always server sided. 您可能认为这并不重要&#xff0c;但确实如此&#xff01; 作为node.js的初学者&#xff0c;大多数编码练习始终都是服务器端的。…

Binary String Matching(C++)

题目描述: Given two strings A and B, whose alphabet consist only ‘0’ and ‘1’. Your task is only to tell how many times does A appear as a substring of B? For example, the text string B is ‘1001110110’ while the pattern string A is ‘11’, you should…

VisualStudio2019配置OpenCV

VisualStudio2019配置OpenCV配置0x01 准备0x02 配置系统环境0x03 复制文件0x04 配置VisualStudio2019测试配置 0x01 准备 下载opencv&#xff0c;官网地址&#xff1a;https://opencv.org/releases/# 下载之后&#xff0c;自行安装 0x02 配置系统环境 找到高级系统设置 …

Visual Studio进行linux远程开发

目录准备工作创建一个项目配置远程项目准备工作 查看linux IP地址 安装了工具 sudo apt-get install openssh-server g gdb make ninja-build rsync zip开启ssh服务&#xff1a; sudo service ssh startVS2019按装了linux功能&#xff0c;如果没有&#xff0c;找到Visual S…