使用FreeRTOS任务通知作计数信号量

关于任务通知特点、优缺点:FreeRTOS任务通知

关于计数信号量的特点、本质:FreeRTOS计数信号量使用

ulTaskNotifyTake()          替代   xSemaphoreTake()

其中参数xClearOnExit需要设置为pdFALSE,读取任务通知值后任务通知值每次减1

xTaskNotifyGive()           替代    xSemaphoreGive()

vTaskNotifyFromISR      替代    xSemaphoreGiveFromISR()

 API说明

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
//发送任务通知,返回值永远是pdTRUE参数xTaskToNotify是任务句柄,既要发向的任务
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
//同上,用于中断中
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
//获取任务通知,返回值是任务通知值,参数xClearCountOnExit为pdTRUE表示用作二值信号量,为pdFALSE表示用作计数信号量

测试程序

总体设计:2个任务,1个中断。

printcounttask:仅仅打印当前计数;

serialtask:获取计数信号量,并打印获取之后的计数信号量的值;

串口中断:接收到串口数据后,给一个信号量。

创建任务

#define PRINT_COUNT_TASK_PRIO		      1	   //任务优先级
#define PRINT_COUNT_TASK_STK_SIZE 	     80    //任务堆栈大小
TaskHandle_t PrintCountTaskHandler;                //任务句柄
void PrintCountFunc(void *pvParameters);           //任务函数

#define SERIAL_TASK_PRIO		      4	   //任务优先级
#define SERIAL_TASK_STK_SIZE 		     80    //任务堆栈大小
TaskHandle_t SerialTaskHandler;                    //任务句柄
void SerialTaskFunc(void *pvParameters);          //任务函数


void OtherTest(void )
{
    BaseType_t ret;
	
    BoardInitMcu();
    BoardInitPeriph();
	
    ret=xTaskCreate((TaskFunction_t )PrintCountFunc,     	
		    (const char*    )"printcount",   	
		    (uint16_t       )PRINT_COUNT_TASK_STK_SIZE, 
		    (void*          )NULL,				
		    (UBaseType_t    )PRINT_COUNT_TASK_PRIO,	
		    (TaskHandle_t*  )&PrintCountFunc); 
	 				
    ret=xTaskCreate((TaskFunction_t )SerialTaskFunc,     
		    (const char*    )"serialtask",   
		    (uint16_t       )SERIAL_TASK_STK_SIZE, 
		    (void*          )NULL,
		    (UBaseType_t    )SERIAL_TASK_PRIO,
		    (TaskHandle_t*  )&SerialTaskHandler); 
				
    vTaskStartScheduler(); 
}

各个任务

void  PrintCountFunc(void *pvParameters)
{
    char  string[21] = {0};
    static uint8_t i=0;

    for(;;)
    {
        i++;
		
	sprintf(string, "%03d ", i);
	printf(" %d\r\n",i);
		
	dis_string(1,0,(uint8_t *)string,1);

        vTaskDelay(500);                
    }
}

void SerialTaskFunc(void *pvParameters)
{
    uint32_t tasknotifyvalue ;
	
    for(;;)
    {
	tasknotifyvalue= ulTaskNotifyTake( pdFALSE, 100);
		
	if(tasknotifyvalue)
	{
	    printf("semaphore counting =%d\r\n",(tasknotifyvalue-1));
	    vTaskDelay(1000);              //延时1000ms,也就是1000个时钟节拍	
	}
	else
	{
	    vTaskDelay(10);                          
	}
    }
}

串口中断

void USART1_IRQHandler( void )
{
    BaseType_t pxHigherPriorityTaskWoken=pdFALSE;
	
    //幅度有限,省略部分代码,仅列出主要代码
 
    if(RESET != __HAL_UART_GET_FLAG(&UartHandle,UART_FLAG_IDLE))
    {                   
	__HAL_UART_CLEAR_IDLEFLAG(&UartHandle);
 
        /*任务通知用作二值信号量*/		
        vTaskNotifyGiveFromISR( SerialTaskHandler, &pxHigherPriorityTaskWoken  );
	portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
    }
}

运行结果

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

freemote

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值