滴滴网站建设流程,定兴县住房和城乡建设局网站,网上做网站广告投放,银行网站建设公司信号量可以用来进行资源管理和任务同步#xff0c;FreeRTOS中信号量又分为二值信号量、计算型信号量、互斥信号量和递归互斥信号量。
0x01 二值信号量
二值信号量其实就是一个只有一个队列项的队列#xff0c;这个特殊的队列要么是满的#xff0c;要么是空的#xff0c;任…信号量可以用来进行资源管理和任务同步FreeRTOS中信号量又分为二值信号量、计算型信号量、互斥信号量和递归互斥信号量。
0x01 二值信号量
二值信号量其实就是一个只有一个队列项的队列这个特殊的队列要么是满的要么是空的任务和中断不用在乎队列中存的是什么消息只需要知道这个队列是满的还是空的可以利用这个机制完成任务与中断之间的同步。
1. 创建二值信号量 vSemaphoreCreateBinary
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )xSemaphore 保存创建成功的二值信号量 此函数是老版本FreeRTOS创建二值信号量函数新版本已经不再使用。
xSemaphoreCreateBinary
SemaphoreHandle_t xSemaphoreCreateBinary( void )此函数是新版本FreeRTOS中统一使用此函数来创建二值信号量使用此函数创建二值信号量的话信号量所需要的内存是有FreeRTOS的内存管理部分动态分配的此函数创建好的二值信号量默认是空的也就是说创建好的二值信号量使用函数xSemaphoreTask是获取不到的。
xSemaphoreCreateBinaryStatic
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )pxSemaphoreBuffer 保存信号量结构体 此函数创建二值信号量所需要的内存需要由用户分配
2. 释放信号量 xSemaphoreGive
xSemaphoreGive( SemaphoreHandle_t xSemaphore )xSemaphore要释放的信号量句柄 此函数用于释放二值信号量、计数型信号量或互斥信号量
xSemaphoreGiveFromISR xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken)xSemaphore要释放的信号量句柄BaseType_t *pxHigherPriorityTaskWoken标记退出此函数以后是否进行任务切换此值为pdTRUE的时候在退出中断之前一定要进行一次任务切换
此函数只能用来释放二值信号量和计数型信号量
3. 获取信号量 xSemaphoreTake
xSemaphoreTake(* SemaphoreHandle_t xSemaphore,* TickType_t xBlockTime* )SemaphoreHandle_t xSemaphore要获取信号量的句柄TickType_t xBlockTime阻塞时间 此函数用于获取二值信号量、计数型信号量或互斥信号量
xSemaphoreTakeFromISR xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken)SemaphoreHandle_t xSemaphore要获取信号量的句柄BaseType_t *pxHigherPriorityTaskWoken标记退出此函数以后是否进行任务切换等于pdTURE一定进行任务切换
4. 验证
设计一个通过串口发送指定的指令来控制开发版上的LED1和BEEP开关的实验。指令如下 LED1ON打开LED1 LED1OFF关闭LED1 BEEFON打开BEEF BEEFOFF关闭BEEF 设计三个任务功能如下 start_task用来创建其他2个任务 task1_task控制LED0闪烁提示系统正在运行 DataProcess_task指令处理任务根据接收到的指令来控制不同的外设 实验中还创建一个二值信号量BinarySemaphore用于完成串口中断和任务DataProcess_task之间的同步。
DataProcess_task函数
void DataProcess_task(void *pvParameters)
{u8 len 0;u8 CommandValue COMMANDERR;BaseType_t err pdFALSE;u8 *CommandStr;POINT_COLOR BLUE;while(1){if(BinarySemaphore!NULL){errxSemaphoreTake(BinarySemaphore,portMAX_DELAY); //获取信号量if(errpdTRUE) //获取信号量成功{lenUSART_RX_STA0x3fff; //得到此次接收到的数据长度CommandStrmymalloc(SRAMIN,len1); //申请内存sprintf((char*)CommandStr,%s,USART_RX_BUF);CommandStr[len]\0; //加上字符串结尾符号LowerToCap(CommandStr,len); //将字符串转换为大写 CommandValueCommandProcess(CommandStr); //命令解析if(CommandValue!COMMANDERR){LCD_Fill(10,90,210,110,WHITE); //清除显示区域LCD_ShowString(10,90,200,16,16,CommandStr); //在LCD上显示命令printf(命令为:%s\r\n,CommandStr);switch(CommandValue) //处理命令{case LED1ON: LED10;break;case LED1OFF:LED11;break;case BEEPON:BEEP0;break;case BEEPOFF:BEEP1;break;}}else{printf(无效的命令请重新输入!!\r\n);}USART_RX_STA0;memset(USART_RX_BUF,0,USART_REC_LEN); //串口接收缓冲区清零myfree(SRAMIN,CommandStr); //释放内存}}else if(errpdFALSE){vTaskDelay(10); //延时10ms也就是10个时钟节拍 }}
}DataProcess_task是用来申请获取信号量如果申请到了就往下执行如果没事申请到就会一直阻塞申请到之后对数据做处理然后做出相应的回应。
串口1中断服务程序
//串口1中断服务程序
void USART1_IRQHandler(void)
{ u32 timeout0;u32 maxDelay0x1FFFF;BaseType_t xHigherPriorityTaskWoken;HAL_UART_IRQHandler(UART1_Handler); //调用HAL库中断处理公用函数timeout0;while (HAL_UART_GetState(UART1_Handler) ! HAL_UART_STATE_READY)//等待就绪{timeout;超时处理if(timeoutmaxDelay) break; } timeout0;while(HAL_UART_Receive_IT(UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) ! HAL_OK)//一次处理完成之后重新开启中断并设置RxXferCount为1{timeout; //超时处理if(timeoutmaxDelay) break; }//释放二值信号量if((USART_RX_STA0x8000)(BinarySemaphore!NULL))//接收到数据并且二值信号量有效{xSemaphoreGiveFromISR(BinarySemaphore,xHigherPriorityTaskWoken); //释放二值信号量portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换}
} 串口1中断服务程序是用来接收串口发送的数据如果接收完毕将会释放二值信号量DataProcess_task才能往下执行如果没有接收完数据或者没有接收到数据DataProcess_task会一直阻塞。