9.FreeRTOS_信号量

信号量概述

信号量的本质也是一个队列

信号量中传输的是一个数值,因此信号量只能表示资源可用的数量,而不能传输数据。具体的信号量模型如下图:

信号量有两种:计数型信号量、二进制信号量,它们之间的区别在于计数值的范围

  • 计数型信号量可以取值0~任意值,在创建时可以设置当前的计数值
  • 二进制信号量取值只能为0、1,在创建时自动设置为0

使用信号量的方法就如模型一样,只有3个步骤:

  • 创建信号量
  • 存入信号量,这就是让计数值+1
  • 获取信号量,这就是让计数值-1

相关配置

在使用信号量之前,需要打开宏开关,具体的步骤如下:

信号量相关函数

创建计数型信号量

函数声明如下:

/* 这是一个宏,创建计数型信号量 */
xSemaphoreCreateCounting( uxMaxCount, uxInitialCount )

/* 宏定义 */
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount )  \              
        xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )

/* 实际调用函数 */
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
                                             const UBaseType_t uxInitialCount )

返回值:信号量句柄

uxMaxCount:计数值的最大值

uxInitialCount :计数值的初始值

创建二进制信号量

函数声明如下:

/* 这是一个宏,创建二进制信号量 */
xSemaphoreCreateBinary();

/* 宏定义 */
#define xSemaphoreCreateBinary() \   
        xQueueGenericCreate( ( UBaseType_t ) 1, 
                             semSEMAPHORE_QUEUE_ITEM_LENGTH,
                             queueQUEUE_TYPE_BINARY_SEMAPHORE )

/* 实际调用函数 */
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
                                   const UBaseType_t uxItemSize,
                                   const uint8_t ucQueueType )

返回值:信号量句柄

存入(释放)信号量

函数声明如下:

/* 这是一个宏,存入(释放)信号量 */
xSemaphoreGive( xSemaphore )

/* 宏定义 */
#define xSemaphoreGive( xSemaphore )   \ 
        xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ),
                             NULL, 
                             semGIVE_BLOCK_TIME, 
                             queueSEND_TO_BACK )

/* 实际调用函数 */
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
                              const void * const pvItemToQueue,
                              TickType_t xTicksToWait,
                              const BaseType_t xCopyPosition )

返回值:成功返回pdPASS,在当前计数值=最大计数值时,会存入失败

xSemaphore :信号量句柄

获取信号量

函数声明如下:

/* 这是一个宏,获取信号量 */
xSemaphoreTake( xSemaphore, xBlockTime )

/* 宏定义 */
#define xSemaphoreTake( xSemaphore, xBlockTime )  \
        xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )

/* 实际调用函数 */
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
                                TickType_t xTicksToWait )

xSemaphore :信号量句柄

xBlockTime :阻塞等待时间,portMAX_DELAY为死等

验证实验

使用二进制信号量来确保串口的输出不被打断。

具体代码如下:

QueueHandle_t SemaphoreHandleTest;/* 信号量句柄 */
void PrintFunction(void *param){
	
	while(1){
		xSemaphoreTake(SemaphoreHandleTest,portMAX_DELAY);/* 获取串口资源 */
		
        printf("%s",(char*)param);

		xSemaphoreGive(SemaphoreHandleTest);/* 释放串口资源 */
		vTaskDelay(10);/* 必须释放CPU资源 */
	}
}

int main( void )
{
	
	TaskHandle_t xHandleTask1;
	TaskHandle_t xHandleTask2;
	
	prvSetupHardware();
	SerialPortInit();
	printf("UART TEST\r\n");
	
	/* 创建二进制信号量,初始值为0*/
	SemaphoreHandleTest = xSemaphoreCreateBinary();
	/* 让信号量为1,代表串口资源可用 */
	xSemaphoreGive(SemaphoreHandleTest);
	
	xTaskCreate(PrintFunction,"Task1",100,(void*)"this is task1\r\n",1,&xHandleTask1);
	xTaskCreate(PrintFunction,"Task2",100,(void*)"this is task2\r\n",1,&xHandleTask2);

	vTaskStartScheduler();
	
	return 0;
}

运行结果如下:

可以看到,这两句话都进行完整的打印,并没有出现打印到一半就被调度器切换到其他任务的情况。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值