电影免费在线观看,网站推广优化趋势,东莞seo建站优化公司,保定 网站制作 招聘简单来说
消息队列是一种数据结构
任务操作队列的基本描述
1.如果队列未满或者允许覆盖入队,FreeRTOS会将任务需要发送的消息添加到队列尾。 2.如果队列满,任务会阻塞(等待)。 3.用户可以指定等待时间。 4.当其它任务从其等待的队列中读取入了数据#xff08;这时候队列未满…简单来说
消息队列是一种数据结构
任务操作队列的基本描述
1.如果队列未满或者允许覆盖入队,FreeRTOS会将任务需要发送的消息添加到队列尾。 2.如果队列满,任务会阻塞(等待)。 3.用户可以指定等待时间。 4.当其它任务从其等待的队列中读取入了数据这时候队列未满了 5.该任务(等待发送数据到队列的任务)将自动由阻塞态转移为就绪态。 6.超过了等待时间即使队列还不允许访问任务也会自动从阻塞态转移为就绪态此时发送消息的任务或者中断程序会收到一个错误码 errQUEUE_FULL。
消息队列使用注意事项
1、发送接收消息前需要定义一个消息队列并根据队列句柄进行操作 2、队列读取采用的是先进先出FIFO模式会先读取先存储在队列中的据。当然也 FreeRTOS 也支持后进先出LIFO模式。 3、读取数据前需要定义读取buffer。 4、无论是发送或者是接收消息都是以拷贝的方式进行如果消息过于庞大可以将消息的地址作为消息进行发送、接收。 5、 队列是具有自己独立权限的内核对象并不属于任何任务。所有任务都可以向同 一队列写入和读出。一个队列由多任务或中断写入是经常的事但由多个任务读 出倒是用的比较少。
消息队列创建函数 xQueueCreate()
1.xQueueCreate函数是基于xQueueGenericCreate进行创建 2.使用xQueueCreate()创建队列时使用的是动态内存分配所以要想使用该函数必须在FreeRTOSConfig.h 中把 configSUPPORT_DYNAMIC_ALLOCATION 定义为 1 来使能。FreeRTOSConfig.h 中这个宏定义默认1. 3.消息量API函数也是基于xQueueGenericCreate进行创建的 #if( configSUPPORT_DYNAMIC_ALLOCATION 1 )#define xQueueCreate( uxQueueLength, uxItemSize ) \ xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) #endif函数原型
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength,UBaseType_t uxItemSize );参数 uxQueueLength队列能够存储的最大消息单元数目即队列长度。 uxItemSize队列中消息单元的大小以字节为单位 返回一个句柄句柄是一个指向队列数据结构类型的指针RTOS中对函数以及数据结构的操作都是通过句柄。
使用示例 QueueHandle_t Test_Queue NULL;//队列句柄#define QUEUE_LEN 4 /* 队列的长度最大可包含多少个消息 */
#define QUEUE_SIZE 4 /* 队列中每个消息大小字节 */BaseType_t xReturn pdPASS;/* 定义一个创建信息返回值默认为 pdPASS */taskENTER_CRITICAL(); //进入临界区/* 创建 Test_Queue */
Test_Queue xQueueCreate((UBaseType_t ) QUEUE_LEN,/* 消息队列的长度 */ (UBaseType_t ) QUEUE_SIZE);/* 消息的大小 */ if (NULL ! Test_Queue) printf(创建 Test_Queue 消息队列成功!\r\n);taskEXIT_CRITICAL(); //退出临界区消息队列静态创建函数 xQueueCreateStatic()
与静态创建任务一样静态创建消息队列也需要自定义一块内存
函数原型
QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorageBuffer,StaticQueue_t *pxQueueBuffer );参数 uxQueueLength:队列能够存储的最大单元数目即队列深度 uxItemSize:队列中数据单元的长度以字节为单位。 pucQueueStorageBuffer:指针指向一个 uint8_t 类型的数组数组的大小至少有uxQueueLength* uxItemSize 个字节。当 uxItemSize 为 0 时pucQueueStorageBuffer 可以为 NULL。 pxQueueBuffer:指针指向 StaticQueue_t 类型的变量该变量用于存储队列的数据结构。
如果创建成功则返回一个队列句柄用于访问创建的队列。如果创建不成功则返回NULL可能原因是创建队列需要的 RAM 无法分配成功。
使用示例
/* 创建一个可以最多可以存储 10 个 64 位变量的队列 */
#define QUEUE_LENGTH 10
#define ITEM_SIZE sizeof(uint64_t)/* 该变量用于存储队列的数据结构 */
static StaticQueue_t xStaticQueue;/* 该数组作为队列的存储区域大小至少有 uxQueueLength * uxItemSize 个字节 */
uint8_t ucQueueStorageArea[ QUEUE_LENGTH * ITEM_SIZE ]; void vATask( void *pvParameters ){QueueHandle_t xQueue;/* 创建一个队列 */ xQueue xQueueCreateStatic( QUEUE_LENGTH, /* 队列深度 */ ITEM_SIZE, /* 队列数据单元的单位 */ ucQueueStorageArea,/* 队列的存储区域 */ xStaticQueue ); /* 队列的数据结构 */ /* 剩下的其他代码 */}消息队列删除函数 vQueueDelete()
传入形参是消息队列的队柄
使用示例
#define QUEUE_LENGTH 5
#define QUEUE_ITEM_SIZE 4int main( void )
{QueueHandle_t xQueue;/* 创建消息队列 */xQueue xQueueCreate( QUEUE_LENGTH, QUEUE_ITEM_SIZE );if ( xQueue NULL ) {/* 消息队列创建失败 */} else {/* 删除已创建的消息队列 */ vQueueDelete( xQueue ); }}向消息队列发送消息函数
任务或者中断服务程序都可以给消息队列发送消息.
所有的发送消息函数都是基于xQueueGenericSend.
xQueueSend()与 xQueueSendToBack() 用于非中断程序
函数原型
BaseType_t xQueueSend(QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);参数 xQueue:目标队列句柄 pvItemToQueue:指针指向要发送到队列尾部的队列消息 xTicksToWait:队列满时等待队列空闲的最大超时时间。如果队列满并 且xTicksToWait 被设置成 0函数立刻返回。超时时间的单位为系统节拍周期常量 portTICK_PERIOD_MS 用于辅助计算真实的时间单位为 ms。如果 INCLUDE_vTaskSuspend 设置成 1并且指定延时为 portMAX_DELAY 将导致任务挂起没有超时。 返回值消息发送成功成功返回 pdTRUE否则返回 errQUEUE_FULL。
宏定义 #define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), \( xTicksToWait ), queueSEND_TO_BACK )可以看出来xQueueSend()是一个宏,宏展开是调用函数 xQueueGenericSend(). #define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), \( xTicksToWait ), queueSEND_TO_BACK )可以看出来xQueueSendToBack宏展开是调用函数 xQueueGenericSend().
xQueueSend() 等同于xQueueSendToBack()。
xQueueSend()用于向队列尾部发送一个队列消息。消息以拷贝的形式入队而不是以引用的形式。该函数绝对不能在中断服务程序里面被调用中断中必须使用带有中断保护功能的 xQueueSendFromISR()来代替。
使用实例
Send_Task作为一个任务函数功能是检测到按键之后发送消息到队列 这个实际任务也是任务的一个形参。 任务创建
static void Send_Task(void* parameter)
{BaseType_t xReturn pdPASS;/* 定义一个创建信息返回值默认为 pdPASS */uint32_t send_data1 1;uint32_t send_data2 2;while (1) {if ( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) KEY_ON ) {/* K1 被按下 */printf(发送消息 send_data1\n); xReturn xQueueSend( Test_Queue, /* 消息队列的句柄 */ send_data1,/* 发送的消息内容 */ 0 ); /* 等待时间 0 */ if (pdPASS xReturn) printf(消息 send_data1 发送成功!\n\n); }if ( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) KEY_ON ) {/* K2 被按下 */printf(发送消息 send_data2\n); xReturn xQueueSend( Test_Queue, /* 消息队列的句柄 */ send_data2,/* 发送的消息内容 */ 0 ); /* 等待时间 0 */ if (pdPASS xReturn) printf(消息 send_data2 发送成功!\n\n); }vTaskDelay(20);/* 延时 20 个 tick */}}xQueueSendFromISR()与 xQueueSendToBackFromISR() 中断服务函数中发送消息
函数原型
BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);参数 xQueue:目标队列句柄 pvItemToQueue:指针指向要发送到队列尾部的消息 pxHigherPriorityTaskWoken:如果入队导致一个任务解锁并且解锁的任务优先级高于当前被中断的任务则将*pxHigherPriorityTaskWoken设置成 pdTRUE然后在中断退出前需要进行一次上下文切换 去执行被唤醒的优先级更高的任务 。从FreeRTOS V7.3.0 起pxHigherPriorityTaskWoken 作为一个可选参数可以设置为 NULL。
返回值: 消息发送成功返回 pdTRUE否则返回 errQUEUE_FULL。
与xQueueSend函数相同xQueueSendFromISR()与 xQueueSendToBackFromISR()也是宏定义。 xQueueSendFromISR() #define xQueueSendToFrontFromISR(xQueue,pvItemToQueue,pxHigherPriorityTaskWoken) \xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ),\( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )xQueueSendToBackFromISR 等同于 xQueueSendFromISR ()。 xQueueSendToBackFromISR()
#define xQueueSendToBackFromISR(xQueue,pvItemToQueue,pxHigherPriorityTaskWoken) \xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), \( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )使用实例
void vBufferISR( void )
{char cIn;BaseType_t xHigherPriorityTaskWoken; /* 在 ISR 开始的时候我们并没有唤醒任务 */xHigherPriorityTaskWoken pdFALSE; /* 直到缓冲区为空 */do {/* 从缓冲区获取一个字节的数据 */cIn portINPUT_BYTE( RX_REGISTER_ADDRESS );/* 发送这个数据 */ xQueueSendFromISR( xRxQueue, cIn, xHigherPriorityTaskWoken ); } while ( portINPUT_BYTE( BUFFER_COUNT ) );/* 这时候 buffer 已经为空如果需要则进行上下文切换 */ if ( xHigherPriorityTaskWoken ) { /* 上下文切换这是一个宏不同的处理器具体的方法不一样 */ taskYIELD_FROM_ISR (); } }我如何知道中断服务函数中有没有唤醒任务
向队列首发送消息
xQueueSendToFront()
用法与xQueueSend()一致。用于task中断中使用有中断保护的xQueueSendToFrontFromISR ()类似的xQueueSendToFrontFromISR也是宏定义基于xQueueGenericSendFromISR。
函数原型
BaseType_t xQueueSendToFront( QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait );参数 xQueue队列句柄 pvItemToQueue指针指向要发送到队首的消息。 xTicksToWait队列满时等待队列空闲的最大超时时间。如果队列满并 且xTicksToWait 被设置成 0函数立刻返回。超时时间的单位为系统节拍周期常量 portTICK_PERIOD_MS 用于辅助计算真实的时间单位为 ms。如果 INCLUDE_vTaskSuspend 设置成 1并且指定延时为 portMAX_DELAY 将导致任务无限阻塞没有超时.
xQueueSendToFrontFromISR()
函数原型
BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);参数 xQueue队列句柄 pvItemToQueue指针指向要发送到队首的消息 pxHigherPriorityTaskWoken如果入队导致一个任务解锁并且解锁的任务优先高于当前被中断的任务则将*pxHigherPriorityTaskWoken设置成 pdTRUE然后在中断退出前需要进行一次上下文切换 去执行被唤醒的优先级更高的任务 。从FreeRTOS V7.3.0 起pxHigherPriorityTaskWoken 作为一个可选参数可以设置为 NULL。 返回值队列项投递成功返回 pdTRUE否则返回 errQUEUE_FULL。
从消息队列读取消息函数
xQueueReceive() 接收并从消息队列里删除数据
xQueueReceive() 是一个宏 宏展开是调用函数xQueueGenericReceive() 。xQueueReceive()用于从一个队列中接收消息并把消息从队列中删除。 接收的消息是以拷贝的形式进行的所以我们必须提供一个足够大空间的缓冲区。 类似发送消息到队列这个函数用于普通Task中断服务函数中使用带有中断保护功能的 xQueueReceiveFromISR。
函数原型
BaseType_t xQueueReceive(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait);参数 xQueue:队列句柄 pvBuffer:指针指向接收到要保存的数据 xTicksToWait:队列空时阻塞超时的最大时间。如果该参数设置为 0函数立刻返回。超时时间的单位为系统节拍周期常量 portTICK_PERIOD_MS 用于辅助计算真实的时间单位为 ms。如果 INCLUDE_vTaskSuspend 设置成 1并且指定延时为 portMAX_DELAY 将导致任务无限阻塞没有超时。 返回值队列项接收成功返回 pdTRUE否则返回 pdFALSE。
xQueueReceive函数使用实例
Receive_Task是一个任务函数。
static void Receive_Task(void* parameter)
{BaseType_t xReturn pdTRUE;/* 定义一个创建信息返回值默认为 pdPASS */uint32_t r_queue; /* 定义一个接收消息的变量 */while (1) {xReturn xQueueReceive( Test_Queue, /* 消息队列的句柄 */ r_queue, /* 接受的数据 */ portMAX_DELAY); /* 等待时间 一直等 */ if (pdTRUE xReturn) printf(本次接收到的数据是%d\n\n,r_queue); else printf(数据接收出错,错误代码: 0x%lx\n,xReturn); }}xQueuePeek() 接收但不从消息队列里删除数据
xQueuePeek使用方法与xQueueReceive一致但是不会从消息队列里删除数据。
xQueueReceiveFromISR()与 xQueuePeekFromISR()中断服务函数的接收消息版本
从队列中获取消息的中断服务函数版本。 xQueueReceiveFromISR函数原型
BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue,void *pvBuffer,BaseType_t *pxHigherPriorityTaskWoken);参数 xQueue:队列句柄 pvBuffer:指针指向存放接收到的数据buffer pxHigherPriorityTaskWoken:任务在往队列投递信息时如果队列满则任务将阻塞在该队列上。如果 xQueueReceiveFromISR引起了一个TASK被唤醒则将 *pxHigherPriorityTaskWoken 设置为pdTRUE //--------------------------------------------------------------------------------------------------- pxHigherPriorityTaskWoken对于这个参数的理解联系xQueueReceiveFromISR()与 xQueuePeekFromISR()函数的区别一个函数是可以从队列中删除数据一个函数是不可以从队列中删除数据。删除了队列中的数据可能导致一个task被唤醒中断服务函数在Task中中断执行的如果引起了一个别的TASK那么下一步如何执行这两个TASK呢 //--------------------------------------------------------------------------------------------------- xQueuePeekFromISR函数原型
BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,void *pvBuffer);参数 xQueue队列句柄。 pvBuffer指针指向接收到要保存的数据。
xQueueReceiveFromISR使用范例
QueueHandle_t xQueue;/* 创建一个队列并往队列里面发送一些数据 */
void vAFunction( void *pvParameters )
{char cValueToPost;const TickType_t xTicksToWait ( TickType_t )0xff;/* 创建一个可以容纳 10 个字符的队列 */xQueue xQueueCreate( 10, sizeof( char ) );if ( xQueue 0 ) {/* 队列创建失败 */}/* ... 任务其他代码 *//* 往队列里面发送两个字符 如果队列满了则等待 xTicksToWait 个系统节拍周期*/cValueToPost a;xQueueSend( xQueue, ( void * ) cValueToPost, xTicksToWait );cValueToPost b;xQueueSend( xQueue, ( void * ) cValueToPost, xTicksToWait );/* 继续往队列里面发送字符当队列满的时候该任务将被阻塞*/cValueToPost c;xQueueSend( xQueue, ( void * ) cValueToPost, xTicksToWait );}/* 中断服务程序输出所有从队列中接收到的字符 */void vISR_Routine( void ){BaseType_t xTaskWokenByReceive pdFALSE;char cRxedChar;while ( xQueueReceiveFromISR( xQueue, ( void * ) cRxedChar, xTaskWokenByReceive) ){ /* 接收到一个字符然后输出这个字符 */vOutputCharacter( cRxedChar );/* 如果从队列移除一个字符串后唤醒了向此队列投递字符的任务那么参数 xTaskWokenByReceive 将会设置成 pdTRUE这个循环无论重复 多少次仅会有一个任务被唤醒 */}if ( xTaskWokenByReceive ! pdFALSE ) { /* 我们应该进行一次上下文切换当 ISR 返回的时候则执行另外一个任务 */ /* 这是一个上下文切换的宏不同的处理器具体处理的方式不一样 */ taskYIELD (); } }消息队列实例 /* ************************************************************************** 包含的头文件**************************************************************************//* FreeRTOS 头文件 */#include FreeRTOS.h#include task.h#include queue.h/* 开发板硬件 bsp 头文件 */#include bsp_led.h#include bsp_usart.h#include bsp_key.h/**************************** 任务句柄 ********************************//** 任务句柄是一个指针用于指向一个任务当任务创建好之后它就具有了一个任务句柄* 以后我们要想操作这个任务都需要通过这个任务句柄如果是自身的任务操作自己那么* 这个句柄可以为 NULL。*/static TaskHandle_t AppTaskCreate_Handle NULL;/* 创建任务句柄 */static TaskHandle_t Receive_Task_Handle NULL;/* LED 任务句柄 */static TaskHandle_t Send_Task_Handle NULL;/* KEY 任务句柄 *//***************************** 内核对象句柄 *****************************//** 信号量消息队列事件标志组软件定时器这些都属于内核的对象要想使用这些内核* 对象必须先创建创建成功之后会返回一个相应的句柄。实际上就是一个指针后续我* 们就可以通过这个句柄操作这些内核对象。** * 内核对象说白了就是一种全局的数据结构通过这些数据结构我们可以实现任务间的通信* 任务间的事件同步等各种功能。至于这些功能的实现我们是通过调用这些内核对象的函数* 来完成的**/QueueHandle_t Test_Queue NULL;/*************************** 全局变量声明 *******************************//** 当我们在写应用程序的时候可能需要用到一些全局变量。*//*************************** 宏定义 ************************************//** 当我们在写应用程序的时候可能需要用到一些宏定义。*/#define QUEUE_LEN 4 /* 队列的长度最大可包含多少个消息 */ #define QUEUE_SIZE 4 /* 队列中每个消息大小字节 */ /*************************************************************************** 函数声明**************************************************************************/static void AppTaskCreate(void);/* 用于创建任务 */static void Receive_Task(void* pvParameters);/* Receive_Task 任务实现 */static void Send_Task(void* pvParameters);/* Send_Task 任务实现 */static void BSP_Init(void);/* 用于初始化板载相关资源 *//****************************************************************** brief 主函数* param 无* retval 无* note 第一步开发板硬件初始化第二步创建 APP 应用任务第三步启动 FreeRTOS开始多任务调度****************************************************************/int main(void){BaseType_t xReturn pdPASS;/* 定义一个创建信息返回值默认为 pdPASS *//* 开发板硬件初始化 */BSP_Init();printf(按下 KEY1 或者 KEY2 发送队列消息\n);printf(Receive 任务接收到消息在串口回显\n\n);/* 创建 AppTaskCreate 任务 */xReturn xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */(const char* )AppTaskCreate,/* 任务名字 */(uint16_t )512, /* 任务栈大小 */(void* )NULL,/* 任务入口函数参数 */(UBaseType_t )1, /* 任务的优先级 */(TaskHandle_t* )AppTaskCreate_Handle);/* 任务控制块指*//* 启动任务调度 */if (pdPASS xReturn)vTaskStartScheduler(); /* 启动任务开启调度 */elsereturn -1;
while (1); /* 正常不会执行到这里 */}/************************************************************************ 函数名 AppTaskCreate* 功能说明 为了方便管理所有的任务创建函数都放在这个函数里面* 参数 无* 返回值 无********************************************************************/static void AppTaskCreate(void){BaseType_t xReturn pdPASS;/* 定义一个创建信息返回值默认为 pdPASS */taskENTER_CRITICAL(); //进入临界区/* 创建 Test_Queue */ Test_Queue xQueueCreate((UBaseType_t ) QUEUE_LEN,/* 消息队列的长度 */ (UBaseType_t ) QUEUE_SIZE);/* 消息的大小 */ if (NULL ! Test_Queue) printf(创建 Test_Queue 消息队列成功!\r\n); /* 创建 Receive_Task 任务 */xReturn xTaskCreate((TaskFunction_t )Receive_Task,/* 任务入口函数 */(const char* )Receive_Task,/* 任务名字 */(uint16_t )512, /* 任务栈大小 */(void* )NULL, /* 任务入口函数参数 */(UBaseType_t )2, /* 任务的优先级 */(TaskHandle_t* )Receive_Task_Handle);/*任务控制块指针*/if (pdPASS xReturn)printf(创建 Receive_Task 任务成功!\r\n);/* 创建 Send_Task 任务 */xReturn xTaskCreate((TaskFunction_t )Send_Task, /* 任务入口函数 */(const char* )Send_Task,/* 任务名字 */(uint16_t )512, /* 任务栈大小 */(void* )NULL,/* 任务入口函数参数 */(UBaseType_t )3, /* 任务的优先级 */(TaskHandle_t* )Send_Task_Handle);/*任务控制块指针 */if (pdPASS xReturn)printf(创建 Send_Task 任务成功!\n\n);vTaskDelete(AppTaskCreate_Handle); //删除 AppTaskCreate 任务 taskEXIT_CRITICAL(); //退出临界区}/*********************************************************************** 函数名 Receive_Task* 功能说明 Receive_Task 任务主体* 参数 * 返回值 无********************************************************************/static void Receive_Task(void* parameter) { BaseType_t xReturn pdTRUE;/* 定义一个创建信息返回值默认为 pdTRUE */ uint32_t r_queue; /* 定义一个接收消息的变量 */ while (1) { xReturn xQueueReceive( Test_Queue, /* 消息队列的句柄 */ r_queue, /* 发送的消息内容 */ portMAX_DELAY); /* 等待时间 一直等 */ if (pdTRUE xReturn) printf(本次接收到的数据是%d\n\n,r_queue); else printf(数据接收出错,错误代码: 0x%lx\n,xReturn); } } /*********************************************************************** 函数名 Send_Task* 功能说明 Send_Task 任务主体* 参数 * 返回值 无********************************************************************/static void Send_Task(void* parameter) { BaseType_t xReturn pdPASS;/* 定义一个创建信息返回值默认为 pdPASS */ uint32_t send_data1 1; uint32_t send_data2 2; while (1) { if ( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) KEY_ON ) { /* KEY1 被按下 */ printf(发送消息 send_data1\n); xReturn xQueueSend( Test_Queue, /* 消息队列的句柄 */ send_data1,/* 发送的消息内容 */ 0 ); /* 等待时间 0 */ if (pdPASS xReturn) printf(消息 send_data1 发送成功!\n\n); } if ( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) KEY_ON ) { /* KEY2 被按下 */ printf(发送消息 send_data2\n); xReturn xQueueSend( Test_Queue, /* 消息队列的句柄 */ send_data2,/* 发送的消息内容 */ 0 ); /* 等待时间 0 */ if (pdPASS xReturn) printf(消息 send_data2 发送成功!\n\n); } vTaskDelay(20);/* 延时 20 个 tick */ } } /************************************************************************ 函数名 BSP_Init* 功能说明 板级外设初始化所有板子上的初始化均可放在这个函数里面* 参数 * 返回值 无*********************************************************************/static void BSP_Init(void){/** STM32 中断优先级分组为 4即 4bit 都用来表示抢占优先级范围为0~15* 优先级分组只需要分组一次即可以后如果有其他的任务需要用到中断* 都统一用这个优先级分组千万不要再分组切忌。*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/* LED 初始化 */LED_GPIO_Config();/* 串口初始化 */USART_Config();/* 按键初始化 */Key_GPIO_Config();}/*******************************END OF FILE****************************/