一、队列简介:队列也称为消息队列,是一种用于消息间进行通信的数据结构,队列可以用于任务与任务之间、中断与任务之间传递消息,队列通常采用先进先出(FIFO)的数据缓冲机制。
二、队列常见的API函数
1.创建队列
2.写队列
3.读队列
三、实验操作
需求:创建一个队列,按下KEY1向队列发送数据,按下KEY2向队列读取数据。
CubeMX配置信息:
创建队列,CubeMX已经封装好了,和原始的函数有点差别:
StartTaskSend函数:
void StartTaskSend(void const * argument)
{
uint16_t buf = 100;
BaseType_t status;
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
{
osDelay(20);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
{
status = xQueueSend(myQueue01Handle,&buf,0);
if(status == pdTRUE)
printf("写入队列成功,写入值%d\r\n",buf);
else
printf("写入队列失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
}
osDelay(1);
}
}
StartTaskRecive函数:
void StartTaskRecive(void const * argument)
{
uint16_t buf ;
BaseType_t status;
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
{
osDelay(20);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
{
status = xQueueReceive(myQueue01Handle,&buf,0);
if(status == pdTRUE)
printf("读取队列成功,读出值%d\r\n",buf);
else
printf("读取队列失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
}
osDelay(1);
}
}
实验结果:通过按键1按三次,写入值三次;按按键2三次,读出值3次,按第四次读取失败。
二值信号量
一、信号量(Semaphore)
三、二值信号量实验
需求:创建一个二值信号量,按下KEY1释放信号量,按下KEY2获取信号量
1.cubeMX配置:释放(give)和获取(get)二值信号量,生成代码
注意: cubeMX生成的myBinaryHanle需要注释掉,使用xSemaphoreCreateBinary();
2.释放二值信号量和获取二值信号量
void StartTaskGive(void const * argument)
{
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
{
osDelay(20);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
{
if(xSemaphoreGive(myBinaryHandle) == pdTRUE)
printf("二值信号量放入成功\r\n");
else
printf("二值信号量放入失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
}
osDelay(1);
}
}
void StartTaskTake(void const * argument)
{
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
{
osDelay(20);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
{
if(xSemaphoreTake(myBinaryHandle,portMAX_DELAY) == pdTRUE)//portMAX_DELAY表示卡死等待,0表示不超时
printf("二值信号量获取成功\r\n");
else
printf("二值信号量获取失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
}
osDelay(10);
}
}
实验结果:当为portMAX_DELAY(死等),可以先点击获取信号量在放入
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
当TickType_t xTicksToWait=0时,必须放一次信号量,拿一次信号量。
计数型信号量
一:定义:
二、相关API函数
配置cubeMX,需要将USE_COUNTING_SEMAPHORES打开成Enable,注释掉cubeMX生成的创建信号量函数,改用xSemaphoreCreateCounting()。
三、代码
void StartTaskGive(void const * argument)
{
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
{
osDelay(20);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
{
if(xSemaphoreGive(CountingSem01Handle) == pdTRUE)
printf("计数型信号量放入成功\r\n");
else
printf("计数型信号量放入失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
}
osDelay(1);
}
void StartTaskTake(void const * argument)
{
for(;;)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
{
osDelay(20);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
{
if(xSemaphoreTake(CountingSem01Handle,0) == pdTRUE)
printf("计数型信号量获取成功\r\n");
else
printf("计数型信号量获取失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
}
osDelay(10);
}
实验结果: