队列与二值信号量、计数型信号量

一、队列简介:队列也称为消息队列,是一种用于消息间进行通信的数据结构,队列可以用于任务与任务之间、中断与任务之间传递消息,队列通常采用先进先出(FIFO)的数据缓冲机制。

二、队列常见的API函数

1.创建队列

队列与二值信号量、计数型信号量_第1张图片

2.写队列

队列与二值信号量、计数型信号量_第2张图片

 3.读队列

队列与二值信号量、计数型信号量_第3张图片

 三、实验操作

需求:创建一个队列,按下KEY1向队列发送数据,按下KEY2向队列读取数据。

CubeMX配置信息:

队列与二值信号量、计数型信号量_第4张图片

队列与二值信号量、计数型信号量_第5张图片

 创建队列,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次,按第四次读取失败。

队列与二值信号量、计数型信号量_第6张图片

二值信号量

一、信号量(Semaphore

是在多任务环境下使用的一种机制,是可以用来保证两个或多个关键代码段不被并发调用。 信号量这个名字,我们可以把它拆分来看,信号可以起到通知信号的作用,然后我们的量还可以 用来表示资源的数量,当我们的量只有 0 1 的时候,它就可以被称作二值信号量,只有两个状 态,当我们的那个量没有限制的时候,它就可以被称作为计数型信号量。 信号量也是队列的一种。
二值信号量:二值信号量是一个长度为1,大小为0的队列,只有0和1两种状态,通常情况下,用来就行互斥访问或任务同步。互斥访问:比如获取了门钥匙,只有获取了钥匙才能开门。
二、二值信号量相关API函数
队列与二值信号量、计数型信号量_第7张图片

 队列与二值信号量、计数型信号量_第8张图片

 队列与二值信号量、计数型信号量_第9张图片

 队列与二值信号量、计数型信号量_第10张图片

三、二值信号量实验

需求:创建一个二值信号量,按下KEY1释放信号量,按下KEY2获取信号量

1.cubeMX配置:释放(give)和获取(get)二值信号量,生成代码

队列与二值信号量、计数型信号量_第11张图片

 队列与二值信号量、计数型信号量_第12张图片

注意: 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(死等),可以先点击获取信号量在放入

队列与二值信号量、计数型信号量_第13张图片

 BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );

TickType_t xTicksToWait=0时,必须放一次信号量,拿一次信号量。

队列与二值信号量、计数型信号量_第14张图片

 

计数型信号量

一:定义:

计数型信号量相当于队列长度大于 1 的队列,因此计数型信号量能够容纳多个资源,这在计数型
信号量被创建的时候确定的。

二、相关API函数

队列与二值信号量、计数型信号量_第15张图片

 配置cubeMX,需要将USE_COUNTING_SEMAPHORES打开成Enable,注释掉cubeMX生成的创建信号量函数,改用xSemaphoreCreateCounting()。

队列与二值信号量、计数型信号量_第16张图片

 

 

三、代码

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



实验结果:

队列与二值信号量、计数型信号量_第17张图片

你可能感兴趣的:(单片机,嵌入式硬件)