9.STM32freeRTOS---计数型信号量

文章目录

  • 前言
  • 一、创建计数型信号量
  • 二、释放和获取计数型信号量
  • 三、计数型信号量操作实验
  • 实验遇到的问题


前言

计数型信号量又叫数值信号量,二值信号量相当于长度为1的队列,那么计数型信号量就是长度大于1 的队列。同二值信号量一样,用户不需要关心队列中存储了什么数据,只需要关心队列是否为空即可

计数型信号量运用场合:
事件计数,资源管理。

事件计数:
每次事件发生的时候就在事件处理函数中释放信号量(增加信号量的计数值),其他任务会获取信号量(信号量计数值减1,信号量值就是队列结构体成员变量uxMessageWaiting)来处理事件。在这种场合中创建的计数型信号量初始计数值为0.

资源管理:
在这个场合中,信号值代表当前资源的可用数量,比如停车场剩余的停车位数量。一个任务要想获得资源的使用权,首先必须获取信号量,信号量获取成功以后信号量就会减1。当信号量值为0就表示没有资源了,当一个任务使用完资源以后一定要释放信号量,释放信号量以后信号量值会加1。在这个场合中创建的计数型信号量初始值应该是资源的数量。比如停车场由199个车位,那么创建信号量的时候信号量值就是199.


一、创建计数型信号量

9.STM32freeRTOS---计数型信号量_第1张图片
在这里插入图片描述
9.STM32freeRTOS---计数型信号量_第2张图片
9.STM32freeRTOS---计数型信号量_第3张图片
注意:计数型信号也是在队列的基础上实现的,所以需要调用函数创建队列函数来创建一个队列,队列长度为uxMaxCount。

二、释放和获取计数型信号量

计数型信号量的释放和获取二值信号量相同。

三、计数型信号量操作实验

main.c

#include "sys.h"
#include "usart.h"
#include "led.h"
#include "delay.h"
#include "light.h"

#include "FreeRTOS.h"
#include "semphr.h"//信号量的头文件
#include "task.h"
/*
	本次实验:计数型信号量在事件计数中的使用方法。
	
	用光敏模块来给pc15引脚一个电平信号。用这个来模拟按键的功能(因为我的按键坏了)
	当检测到一个低电平后释放计数型信号量,另一个任务来获取信号量,获取成功后点亮led灯。

start_task:开始任务
task1:led闪烁,表示任务在运行

task2:检测光敏模块引脚的电平值,低电平就释放计数型信号量,
成功获取6个信号量值(也就是触发6次后)就点亮led	

task3:获取信号量,
*/
#define start_task_size 52
#define start_task_pro   1
TaskHandle_t startTask_handler;
void start_task(void *pram);

#define task1_size 100
#define task1_pro  2
TaskHandle_t Task1_handler;
void task1(void *pram);

#define task2_size 100
#define task2_pro  4
TaskHandle_t Task2_handler;
void task2(void *pram);

#define task3_size 100
#define task3_pro  3
TaskHandle_t Task3_handler;
void task3(void *pram);

//计数型信号量句柄
SemaphoreHandle_t countSemaphore;

int main(void)
{
	delay_init();									//延时函数初始化	  
	uart_init(115200);								//初始化串口
	LED_Init(); 									//初始化LED
	Light_GPIO_Init();
	
	xTaskCreate(
						(TaskFunction_t )start_task,
                        (const char * 		) "start_task",     
                        (uint16_t		)start_task_size ,
                        (void *  		)NULL,
                        (UBaseType_t	) start_task_pro,
                        (TaskHandle_t * )startTask_handler );

    vTaskStartScheduler();//开始任务调度
}
/*88888888888888888888888888888888888888888888888888888888888888888888*/
void start_task(void *pram)
{
	taskENTER_CRITICAL();
	//创建计数型信号量
	countSemaphore = xSemaphoreCreateCounting(20,0);
	//计数型信号量 计数值最大是20,所有计数型信号量的初始值为0。
	xTaskCreate(
						(TaskFunction_t ) task1,
                        (const char * 	) "task1",     
                        (uint16_t		) task1_size ,
                        (void *  		) NULL,
                        (UBaseType_t	) task1_pro,
                        (TaskHandle_t * ) Task1_handler);
												
	xTaskCreate(
						(TaskFunction_t ) task2,
                        (const char *	) "task2",     
                        (uint16_t		) task2_size,
                        (void *  		) NULL,
                        (UBaseType_t	) task2_pro,
                        (TaskHandle_t * ) Task2_handler);		
	xTaskCreate(
						(TaskFunction_t ) task3,
                        (const char *	) "task3",     
                        (uint16_t		) task3_size,
                        (void *  		) NULL,
                        (UBaseType_t	) task3_pro,
                        (TaskHandle_t * ) Task3_handler);
				
	vTaskDelete(NULL);
	taskEXIT_CRITICAL();
}
void task1(void *pram)
{
	while(1)
	{
		LED1 = !LED1;
		vTaskDelay(1000);	 
	}
}
void task2(void *pram)//检测引脚电平,释放计数型信号量
{
	BaseType_t err;
	//用来存储 获取数值信号量的个数
	uint8_t semavalue = 0;
	while(1)
	{
		if(countSemaphore != NULL)//创建计数型信号量 成功
		{
			if(  GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_15) == 1  )
			{
				err = xSemaphoreGive(countSemaphore);//释放计数型信号量
//				if(err == pdFALSE)
//				{
//					printf("semap give false\r\n");
//					
//				}
//				else if(err == pdTRUE)
//				{
//					printf("give sucess\r\n");
//				
//				}
			}
			semavalue = uxSemaphoreGetCount(countSemaphore);//获取数值信号量值(也就是得到由多少个数值信号量)
			if(semavalue == 6)
			{
				LED2_ON();	
			}
			printf("task2:get%d\n",semavalue);
		}
		 vTaskDelay(50);
	}
}
void task3(void *pram)
{	
	//用来存储 获取数值信号量的个数
	uint8_t semavalue = 0;
	while(1)
	{
		xSemaphoreTake(countSemaphore,portMAX_DELAY);//等待数值信号量(计数型信号量)
		semavalue = uxSemaphoreGetCount(countSemaphore);//获取数值信号量值
		printf("task3:%d\n",semavalue);
		vTaskDelay(1000);
	}
}

实验遇到的问题

(1)
9.STM32freeRTOS---计数型信号量_第4张图片
原因是:
在这里插入图片描述
创建一个计数型信号量后需要一个返回值(也就是信号句柄)接收。

(2)
9.STM32freeRTOS---计数型信号量_第5张图片
任务2和3 的打印信息交叠,原因是:任务2和3 的优先级一样了,把优先级改一下。

(3)我触碰一次光敏电阻后,确实可以成功释放一个信号量,但是这个信号量值没有累加。原因是:(1)因为我是光敏模块来模拟按键,所以本质上和按键的触发方式可能不太一样。(2)基于我知道了(1)点的不同,在经过我把延时改的尽量小的时候,还是隐隐约约的可以实现信号量值的累加。【每触碰一次光敏电阻,就释放一个信号量,然后就把这个缓冲延时改的小点,就可以实现】
9.STM32freeRTOS---计数型信号量_第6张图片
现象:
9.STM32freeRTOS---计数型信号量_第7张图片

你可能感兴趣的:(32freeRTOS,stm32,单片机,arm)