freeRTOS实时操作系统移植
FreeRtos(1)-----任务创建与管理
FreeRtos(2)-----消息队列
FreeRtos(3)-----二值信号量
以上是历史FreeRtos博客。FreeRtos系列我会坚持更下去

计数信号量

计数信号量其实就二值信号量的进阶版本,只是二值只能设置信号量为1,也就是一次只能一个进程访问。计数信号量则可以设置一次多个进程访问。二值信号量在新版本创建信号量函数时候必须要先释放才能申请,而计数信号量不需要先释放。
计数信号量API
计数信号量API和二值信号量API除了创建函数以外别的一模一样。
计数信号量创建函数API

SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t 
uxMaxCount, UBaseType_t uxInitialCount);

参数:
	uxMaxCount :计数信号量的最大值,当达到这个值的时候,信号量不能再被释放。
	uxInitialCount:创建计数信号量的初始值。
返回值:
	如果创建成功则返回一个计数信号量句柄,用于访问创建的计数信号
	量。如果创建不 成功则返回NULL

示例

创建两个任务,任务一死循环,任务二输出1,2,3.计数信号量初始值为3

#include "stm32f10x.h"
#include "led.h"
#include "stdio.h"
#include "usart1.h"
#include "systick.h"
#include "delay.h"
#include "my_key.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

#define QUEUE_LEN 8
#define QUEUE_SIZE 8
static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */
static TaskHandle_t server_Task_Handle = NULL;/* server 任务句柄 */
static TaskHandle_t client_Task_Handle = NULL;/* client 任务句柄 */
static void AppTaskCreate(void);/* 用于创建任务 */
static void server_Task(void* pvParameters);
static void client_Task(void* pvParameters);

SemaphoreHandle_t BinarySem_Handle =NULL;//二值信号量句柄
int main(void)
{
 BaseType_t xReturn = pdPASS;//创建任务返回值
 NVIC_SetPriorityGrouping(3);
 usrat1_config();
 systick_config();
 key_init();
 led_config();
 printf("hello\r\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(); 
	}
	else 
	{
	return -1; 
	}
	 
 while (1); /* 正常不会执行到这里 */
}
static void AppTaskCreate(void)
{
 BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
 taskENTER_CRITICAL();
	BinarySem_Handle=xSemaphoreCreateCounting(3,3);
 xReturn = xTaskCreate((TaskFunction_t )server_Task,/* 任务入口函数 */
												(const char *)"server_Task",/* 任务名字 */
												(uint16_t )128,
												(void *)NULL,
												(UBaseType_t )2,
												(TaskHandle_t* )&server_Task_Handle);/* 任务控制块指针 */
 if(pdPASS == xReturn)
 {
	printf("任务创建成功\r\n");
 }
 
  xReturn = xTaskCreate((TaskFunction_t )client_Task,/* 任务入口函数 */
												(const char *)"client_Task",/* 任务名字 */
												(uint16_t )128,
												(void *)NULL,
												(UBaseType_t )2,
												(TaskHandle_t* )&client_Task_Handle);/* 任务控制块指针 */
 if(pdPASS == xReturn)
 {
	printf("任务创建成功\r\n");
 }
 
vTaskDelete(AppTaskCreate_Handle); //删除 AppTaskCreate 任务 
taskEXIT_CRITICAL();//退出临界区

}
//定义一个任务
static void server_Task(void* parameter)
{

 while(1)
 {
	xSemaphoreTake(BinarySem_Handle,portMAX_DELAY);//申请
	printf("1\r\n");
	printf("2\r\n");
	printf("3\r\n");
	
 }
}
static void client_Task(void* parameter)
{

 while(1)
 {

 }
 xSemaphoreGive(BinarySem_Handle);//释放
}

运行结果
在这里插入图片描述
可以看到我我设置的计数信号量最大值为3,没有先释放也能申请。申请3次后就阻塞了。

-END-

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐