消息队列:异步通信机制
1.当队列中的消息是空时,读取消息的任务将被阻塞
2.可以指定阻塞的任务时间 xTicksToWait(这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效)
3.等待期间如果队列有消息,会唤醒被阻塞的任务并处理消息
4.等待超时,即使队列没有数据也会让任务进入就绪状态
5.消息先进先出
6.允许不同长度(限定范围之内)
7.一个消息队列可以服务于一个或多个任务
6.队列使用结束后通过删除队列函数删除
消息队列基本要素
头指针 pcHead、尾指针 pcTail、消息大小 uxItemSize 以及队列长度 uxLength
消息队列与消息空间占用一段连续内存
一经创建不可改变
发送消息(任何任务或者中断函数都可以) 队列未满或者允许覆盖入队(消息安全性如何保证?),也可以是消息阻塞状态(那么发送消息的任务进入阻塞状态?是的)如果等待超时任务会进入就绪状态并会报错(errQUEUE_FULL)
普通消息加入队尾(先进先出),紧急消息加入队头。
发送到消息队列的数据是拷贝数据,不是引用数据
如果消息的长度过长可以将消息的地址作为消息发送(要保证数据不被多次擦写)
消息读取:
某任务试图读取消息时可以指定超时时间等待消息
保护机制:
阻塞机制:
读取阻塞:
任务A对队列L进行读操作的时候如果队列中没有消息:
1.任务直接放弃读取
2.任务A等待(进入阻塞状态)等待时间由软件定义
3.任务A一直等待,A进入阻塞状态直到消息队列有数据才会恢复为就绪状态
写入阻塞
任务B被允许对队列L写入时
1.如果队列已满,任务B可以等待阻塞超时时间,指定时间内如果不能完成写入操作返回错误吗errQUEUEFULL,然后进入就绪状态
2.中断中发送队列消息不允许有阻塞机制
3.如果有多个消息阻塞在队列操作中,这些任务将按照优先级进行排序
安全设计思想:
一个队列尽可能只对应一个任务可以写入和读取,生产者和消费者保证唯一性。
一个队列由多任务或中断写入是经常的事,但由多个任务读出倒是用的比较少。
实验:设计两个任务,一个按键检测任务Key,一个LED点亮任务Led
检测到Key(扫描方式)发送消息给到Led任务点亮Led
检测到Key(中断方式)发送消息给到Led任务点亮Led
下面贴部分代码,欢迎交流参考
* AutoChips Inc. (C) 2021. All rights reserved.
*
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
* RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
* ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
* INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
* SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
* RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
* AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
* CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
*
******************************************************************************
*/
/* --------------------------------- Includes -------------------------------*/
#include "main.h"
#include "ac780x_irq_cb.h"
#include "ac780x_uart.h"
#include "ac780x_uart_reg.h"
#include "ac780x_gpio.h"
/* USER CODE BEGIN Includes */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "croutine.h"
/* USER CODE END Includes */
/* --------------------------------- Typedefs -------------------------------*/
/* USER CODE BEGIN Typedefs */
static TaskHandle_t xHandleTaskLed = NULL;
static TaskHandle_t xTaskTaskKey = NULL;
QueueHandle_t Test_GpioQueue =NULL; //消息队列句柄
/* USER CODE END Typedefs */
/* --------------------------------- Defines --------------------------------*/
/* USER CODE BEGIN Defines */
/* USER CODE END Defines */
/* --------------------------------- Macros ---------------------------------*/
/* USER CODE BEGIN Macros */
/* USER CODE END Macros */
/* --------------------------------- Variables ------------------------------*/
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
/* --------------------------------- Function Prototypes --------------------*/
void SystemClock_Config(void);
static void ATC_GPIO_Init(void);
static void ATC_UART2_Init(void);
static void ATC_UART1_Init(void);
void MSP_Init(void);
void MSP_UART_Init(UART_Type* UARTx);
/* USER CODE BEGIN Function_Prototypes */
static void vTaskTaskLed(void* parameter)
{
BaseType_t xReturn = pdPASS;
uint8_t xRekeydata[2]={0x0};
while (1)
{
printf("Scan msg \r\n");
xReturn = xQueueReceive(Test_GpioQueue, xRekeydata, 500);
if(xReturn == errQUEUE_EMPTY)
{
printf("empty\r\n");
}
if(xReturn == pdTRUE)
{
printf("Get %d,%d\r\n",xRekeydata[0],xRekeydata[1]);
if(xRekeydata[0] == 0x01)
GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_LOW);
else
GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_HIGH);
}
else
{
}
/*
printf("Task Led 0\r\n");
GPIO_SetPinLevel(LED1_GPIO_Port,LED1_Pin,GPIO_LEVEL_LOW);
vTaskDelay(500);
printf("Task Led 1\r\n");
GPIO_SetPinLevel(LED1_GPIO_Port,LED1_Pin,GPIO_LEVEL_HIGH);
vTaskDelay(500);
*/
}
}
static void vTaskTaskKey(void* parameter)
{
BaseType_t xReturn = pdPASS;
uint8_t xkeydata[2]={0x0};
while (1)
{
//L enable
/* printf("Task Key\r\n");
if(GPIO_GetPinLevel(KEY2_GPIO_Port, KEY2_Pin) == 0)
{
// GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_LOW);
xkeydata[0] = 0x00;
xkeydata[1] = 0x00;
xReturn = xQueueSend( Test_GpioQueue, xkeydata,0);
}
else
{
// GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_HIGH);
xkeydata[0] = 0x01;
xkeydata[1] = 0x01;
xReturn = xQueueSend( Test_GpioQueue, xkeydata,0);
}
vTaskDelay(5000);
*/
}
}
/* USER CODE END Function_Prototypes */
/* USER CODE BEGIN 0 */
static void AppTaskCreate (void)
{
Test_GpioQueue = xQueueCreate(16, 2);
if(NULL != Test_GpioQueue)
{
printf("消息队列创建成功\r\n");
}
else
{
printf("消息队列创建失败\r\n");
}
xTaskCreate( vTaskTaskLed,
"vTaskLed",
512,
NULL,
1,
&xHandleTaskLed );
xTaskCreate( vTaskTaskKey,
"vTaskUserTRE",
512,
NULL,
1,
&xTaskTaskKey );
}
/*******************************************************************************
* Function Name :void ACC_IRQHandler(void *device, uint32_t wpara, uint32_t lpara)
* Description :ACC 引脚中断处理程序
* Output : None
* Return : None
*******************************************************************************/
void SocGpioACC_IRQHandler(void *device, uint32_t wpara, uint32_t lpara)
{
uint8_t xkeydata[2]={0x0};
//if(GPIO_GetPendingExtInterrupt() & KEY2_Pin)
{
GPIO_ClearPendingExtInterrupt(KEY2_Pin);
xkeydata[0] =GPIO_GetPinLevel(KEY2_GPIO_Port, KEY2_Pin);
xQueueSend( Test_GpioQueue, xkeydata,0);
}
}
/*******************************************************************************
* Function Name :void SocGpioEXITAccDet(void)
* Description :使能 ACC 中断
* Output : None
* Return : None
*******************************************************************************/
void SocGpioEXITKeyDet(void)
{
GPIO_SetPullup(KEY2_GPIO_Port,KEY2_Pin, ENABLE);
GPIO_EnableExtInterrupt(KEY2_GPIO_Port, KEY2_Pin, EXTI_TRIGGER_RISING_FALLING);
GPIO_SetCallback(KEY2_Pin, SocGpioACC_IRQHandler);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
*
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration------------------------------------------------------*/
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
ATC_GPIO_Init();
ATC_UART2_Init();
ATC_UART1_Init();
/* USER CODE BEGIN 2 */
SocGpioEXITKeyDet();
InitDebug();
AppTaskCreate();
vTaskStartScheduler();
/* USER CODE END 2 */
/* Infinite loop */
while(1)
{
/* USER CODE BEGIN WHILE */
/* USER CODE END WHILE */
}
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
SPM_EnableXOSC(ENABLE);
SPM_EnablePLL(ENABLE);
CKGEN_SetPLLReference(PLL_REF_INTERAL_OSC);
CKGEN_SetPllPrevDiv(PLL_PREDIV_1);
CKGEN_SetPllFeedbackDiv(96);
CKGEN_SetPllPostDiv(PLL_POSDIV_16);
CKGEN_SetSysclkDiv(SYSCLK_DIVIDER_1);
CKGEN_SetSysclkSrc(SYSCLK_SRC_PLL_OUTPUT);
CKGEN_SetAPBClockDivider(APBCLK_DIVIDER_2);
}
/* UART1 init function */
static void ATC_UART1_Init(void)
{
/* USER CODE BEGIN UART1_Init 0 */
/* USER CODE END UART1_Init 0 */
UART_ConfigType uartConfig;
memset(&uartConfig, 0, sizeof(uartConfig));
/* USER CODE BEGIN UART1_Init 1 */
/* USER CODE END UART1_Init 1 */
MSP_UART_Init(UART1);
uartConfig.baudrate = 115200;
uartConfig.dataBits = UART_WORD_LEN_8BIT;
uartConfig.stopBits = UART_STOP_1BIT;
uartConfig.parity = UART_PARI_NO;
uartConfig.fifoByteEn = DISABLE;
uartConfig.dmaEn = UART_DMA_TXRX_NONE;
uartConfig.sampleCnt = UART_SMP_CNT0;
UART_Init(UART1, &uartConfig);
/* USER CODE BEGIN UART1_Init 2 */
/* USER CODE END UART1_Init 2 */
}
/* UART2 init function */
static void ATC_UART2_Init(void)
{
/* USER CODE BEGIN UART2_Init 0 */
/* USER CODE END UART2_Init 0 */
UART_ConfigType uartConfig;
memset(&uartConfig, 0, sizeof(uartConfig));
/* USER CODE BEGIN UART2_Init 1 */
/* USER CODE END UART2_Init 1 */
MSP_UART_Init(UART2);
uartConfig.baudrate = 115200;
uartConfig.dataBits = UART_WORD_LEN_8BIT;
uartConfig.stopBits = UART_STOP_1BIT;
uartConfig.parity = UART_PARI_NO;
uartConfig.fifoByteEn = DISABLE;
uartConfig.dmaEn = UART_DMA_TXRX_NONE;
uartConfig.sampleCnt = UART_SMP_CNT0;
UART_Init(UART2, &uartConfig);
/* USER CODE BEGIN UART2_Init 2 */
/* USER CODE END UART2_Init 2 */
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void ATC_GPIO_Init(void)
{
GPIO_SetFunc(KEY2_GPIO_Port, KEY2_Pin, GPIO_FUN0);
GPIO_SetFunc(KEY1_GPIO_Port, KEY1_Pin, GPIO_FUN0);
GPIO_SetFunc(LED2_GPIO_Port, LED2_Pin, GPIO_FUN0);
GPIO_SetFunc(LED1_GPIO_Port, LED1_Pin, GPIO_FUN0);
GPIO_SetDir(KEY2_GPIO_Port, KEY2_Pin, GPIO_IN);
GPIO_SetDir(KEY1_GPIO_Port, KEY1_Pin, GPIO_IN);
GPIO_SetDir(LED2_GPIO_Port, LED2_Pin, GPIO_OUT);
GPIO_SetDir(LED1_GPIO_Port, LED1_Pin, GPIO_OUT);
GPIO_SetPinLevel(LED2_GPIO_Port, LED2_Pin, GPIO_LEVEL_LOW);
GPIO_SetPinLevel(LED1_GPIO_Port, LED1_Pin, GPIO_LEVEL_LOW);
GPIO_SetDrivingAbility(LED2_GPIO_Port, LED2_Pin, GPIO_DRIVING_4MA);
GPIO_SetDrivingAbility(LED1_GPIO_Port, LED1_Pin, GPIO_DRIVING_4MA);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @param file: The file name as string.
* @param line: The line in file as a number.
* @retval None
*/
void Error_Handler(char *file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to handle the driver error */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}
/************************ (C) COPYRIGHT AutoChips *****END OF FILE****/
09-16
1608
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
07-24
2277
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
08-02
2804
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)