计数型信号量
描述:计数型信号量相当于队列项目大于1的队列,不用设置队列的存储内容,只管队列的计数值大小。
用处:
1.事件计数型信号量
一个任务或者中断可以释放该计数信号量,即写入信号量。初始值为0,写入一次加1.设置信号量的最大值为MAX,MAX一般为最大255.
写入的值不能大于该MAX,大于该MAX则写入失败。
其它单个任务包含多个任务都可以获取该计数信号量,可以等待该计数信号量的值,获取成功则执行该任务,获取失败则处于阻塞状态,多个任务同事阻塞,则优先级高的任务优先获取计数型信号量,获取之后数值减1.
2、资源管理计数
例如多个任务执行次数管理,初始化计数为VAL,多个任务可以获取该计数来执行该任务,获取一次则计数减一,中断函数可以通过中断来释放信号量即写入信号量,此时计数加1. 当计数读取为0时则任务阻塞。多个任务则无法执行,等待计数加1.
创建计数型信号量
#include "semphr.h" //头文件
SemaphoreHandle_t CountSemaphore;//任务句柄
CountSemaphore=xSemaphoreCreateCounting(255,0);//创建一个计数信号量
释放计数型信号量
xSemaphoreGiveFromISR(CountSemaphore); //普通任务释放计数型信号量
extern SemaphoreHandle_t CountSemaphore;
void TIM5_IRQHandler(void)
{
u8 Phore_Count=0;//计数信号量值的大小
BaseType_t err;
BaseType_t pxHigherPriorityTaskWoken;
pxHigherPriorityTaskWoken=pdFALSE;
if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //溢出中断
{
if(CountSemaphore!=NULL)
{
err=xSemaphoreGiveFromISR(CountSemaphore,&pxHigherPriorityTaskWoken);
Phore_Count=uxSemaphoreGetCount(CountSemaphore);//获取信号量的值的大小
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行任务切换
}
}
TIM_ClearITPendingBit(TIM5,TIM_IT_Update); //清除中断标志位
}
获取二值信号量
void battery_task(void *pvParameters)
{
u8 Phore_Countsave=0;
float adcdata;
u16 tmp,temp;
u16 nUNIT=4096/(3.3*11);//每伏电压对应的ADC数值
while(1)
{
xSemaphoreTake(CountSemaphore,portMAX_DELAY);//获取计数型信号量
Phore_Countsave=uxSemaphoreGetCount(CountSemaphore);//得到计数型信号量的值
//发送数据帧电量显示
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);
vTaskDelay(10);
}
}