任务通知—模拟二值信号量
描述:每一个任务都有一个32位的任务通知值,任务控制块中的成员变量ulnotifiedValue就是这个值。
任务通知时一个事件,某个任务因为等待接收事件而阻塞的话,则接收到任务通知之后则会解除阻塞。
**特点:**比普通二值信号量的解除阻塞时间快50%,减少了大量代码,减少了内存占用。
**缺点:**任务的接收通知只能是指定的一个任务接收,不能多个任务接收。
接收通知可以进入阻塞状态,发送通知不会进入阻塞状态。
**vTaskNotifyGiveFromISR();**发送通知 不带通知的值也不保留接收任务的通知值
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
例子:
extern TaskHandle_t BATTERYTask_Handler;//任务句柄
void USART2_IRQHandler(void) //串口2中断服务程序
{
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken=pdFALSE;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
RxBuffer2[RxCounter2++] = USART_ReceiveData(USART2);
if(RxCounter2>7||RxBuffer2[7]==0xff)//判断结束标志
if(BATTERYTask_Handler!=NULL)
{
vTaskNotifyGiveFromISR(BATTERYTask_Handler,&xHigherPriorityTaskWoken);//通知到电池任务
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
//USART2_data(RxBuffer2,8);
memset(RxBuffer2,0,8);
RxCounter2=0;
}
}
ulTaskNotifyTake() 任务通知接收
返回值:任务通知值减少或者清零之前的值,例如pdTRUE则清零之后为0,清零之前大于等于1,pdFALSE则为减1之前的值。
void battery_task(void *pvParameters)//计数型信号量的验证
{
u32 Notify_value=0;//任务通知
while(1)
{
Notify_value=ulTaskNotifyTake(pdTRUE,portMAX_DELAY);//读取任务通知的值,pdTRUE表示清零
if(Notify_value==1)//清零之前的值是否为1
{
//发送数据帧电量显示
TxBuffer2[0]='S';
TxBuffer2[1]=6;
if(Battery_Update())
{
adcdata = (float)Battery_AdcValue/65535.0f; //16位精度
adcdata *= 3.0f; //参考电压
adcdata *= 11; //电路放大倍数
adcdata *= 10; //发送放大倍数
temp = (u16)adcdata;
TxBuffer2[2] = temp/10;
TxBuffer2[3] = temp%10;
}
else
{
while (DMA_GetFlagStatus(DMA2_Stream4,DMA_FLAG_TCIF4) == RESET){}
tmp = AverageVal(ADC1ConvertedValue,5);
TxBuffer2[2] = tmp/nUNIT;//电量整数部分
TxBuffer2[3] = 10*(tmp%nUNIT)/nUNIT;//电量小数部分,精确到点后一位
}
CRC_check(TxBuffer2,5);//校验和(注:校验和本身之前的所有数据之和)
TxBuffer2[5]='E';
//vTaskList(InfoBuffer); //获取所有任务的信息
USART2_data(TxBuffer2,6);
}
else
vTaskDelay(180);
}
}
if(Notify_value==1)
{
}
//清零之前的值为发送通知的值,这个值会累加,例如串口发送的时间间隔为10ms,处理数据的时间为100ms,则任务通知的值会大于5小于10
模拟计数型信号量
模拟计数型信号量的特点与二值信号量两个函数一样,区别在于接收任务通知的时候只能用于一个函数,而且每次接收任务通知之后这个值减1.
直到这个值为0则进入阻塞状态。
Notify_value=ulTaskNotifyTake(pdFALSE,portMAX_DELAY);//读取任务通知的值,pdFALSE表示减1
vTaskNotifyGiveFromISR(BATTERYTask_Handler,&xHigherPriorityTaskWoken);//通知到电池任务 每次加1