Free RTOS的互斥信号量

二进制信号量和互斥量非常相似,但确实有一些细微的区别。互斥体包含优先级继承机制,而二进制信号量没有。这使得二进制信号量成为实现同步(任务之间或任务与中断之间)的更好选择,互斥体成为实现简单互斥的更好选择。
使用互斥信号量时,需要在freertosconfig.h中加入配置代码
//使用互斥信号量#define configuse_mutexes 1  
创建互斥信号量
semaphorehandle_t xsemaphorecreatemutex( void ); 返回值:
            null:创建信号量失败,因为freertos堆栈不足。
           其它值:信号量创建成功。这个返回值存储着信号量句柄。
释放和获取api函数请看二值信号量那篇推文
实验小例程
#include stm32f10x.h#include #include freertos.h#include task.h#include semphr.h//毫秒级的延时void delay_ms(u16 time){ u16 i=0; while(time--) { i=12000; //自己定义 while(i--) ; }}void led_init(void){ gpio_inittypedef gpio_initstructure; //定义结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioc,enable); //开启时钟 gpio_initstructure.gpio_pin=gpio_pin_0; //选择你要设置的io口 gpio_initstructure.gpio_mode=gpio_mode_out_pp; //设置推挽输出模式 gpio_initstructure.gpio_speed=gpio_speed_50mhz; //设置传输速率 gpio_init(gpioc,&gpio_initstructure); //初始化gpio gpio_setbits(gpioc,gpio_pin_0); //将led端口拉高,熄灭led}void key_init(void){ gpio_inittypedef gpio_initstructure; //定义结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioa|rcc_apb2periph_gpioe,enable); gpio_initstructure.gpio_pin=gpio_pin_0; //选择你要设置的io口 gpio_initstructure.gpio_mode=gpio_mode_ipd;//下拉输入 gpio_initstructure.gpio_speed=gpio_speed_50mhz; //设置传输速率 gpio_init(gpioa,&gpio_initstructure); /* 初始化gpio */ gpio_initstructure.gpio_pin=gpio_pin_3|gpio_pin_2|gpio_pin_4; gpio_initstructure.gpio_mode=gpio_mode_ipu; //上拉输入 gpio_initstructure.gpio_speed=gpio_speed_50mhz; gpio_init(gpioe,&gpio_initstructure);}void usart_init(uint32_t bound){ gpio_inittypedef gpio_initstruct; //定义gpio结构体变量 usart_inittypedef usart_initstruct; //定义串口结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioa|rcc_apb2periph_usart1,enable); //使能gpioc的时钟 gpio_initstruct.gpio_pin=gpio_pin_9; //配置tx引脚 gpio_initstruct.gpio_mode=gpio_mode_af_pp; //配置pa9为复用推挽输出 gpio_initstruct.gpio_speed=gpio_speed_50mhz; //配置pa9速率 gpio_init(gpioa,&gpio_initstruct); //gpio初始化函数 gpio_initstruct.gpio_pin=gpio_pin_10; //配置rx引脚 gpio_initstruct.gpio_mode=gpio_mode_in_floating; //配置pa10为浮空输入 gpio_initstruct.gpio_speed=gpio_speed_50mhz; //配置pa10速率 gpio_init(gpioa,&gpio_initstruct); //gpio初始化函数 usart_initstruct.usart_mode=usart_mode_tx|usart_mode_rx; //发送接收模式 usart_initstruct.usart_parity=usart_parity_no; //无奇偶校验 usart_initstruct.usart_baudrate=bound; //波特率 usart_initstruct.usart_stopbits=usart_stopbits_1; //停止位1位 usart_initstruct.usart_wordlength=usart_wordlength_8b; //字长8位 usart_initstruct.usart_hardwareflowcontrol=usart_hardwareflowcontrol_none; //无硬件数据流控制 usart_init(usart1,&usart_initstruct); //串口初始化函数 usart_cmd(usart1,enable); //使能usart1}int fputc(int ch,file *f) //printf重定向函数{ usart_senddata(usart1,(uint8_t)ch); //发送一字节数据 while(usart_getflagstatus(usart1,usart_flag_txe) == reset); //等待发送完成 return ch;}#define start_task_prio 5 //任务优先级#define start_stk_size 128 //任务堆栈大小taskhandle_t starttask_handler; //任务句柄void start_task(void *pvparameters);//任务函数#define low_task_prio 2 //任务优先级#define low_stk_size 50 //任务堆栈大小taskhandle_t lowtask_handler; //任务句柄void low_task(void *p_arg); //任务函数#define med_task_prio 3 //任务优先级#define med_stk_size 50 //任务堆栈大小taskhandle_t medtask_handler; //任务句柄void med_task(void *p_arg); //任务函数#define high_task_prio 4 //任务优先级#define high_stk_size 50 //任务堆栈大小taskhandle_t hightask_handler; //任务句柄void high_task(void *p_arg); //任务函数semaphorehandle_t mutex_handle =null; //二值信号量句柄int main( void ) { nvic_prioritygroupconfig(nvic_prioritygroup_4);//设置系统中断优先级分组 4 led_init(); //初始化 led key_init(); usart_init(9600); //创建开始任务 xtaskcreate( (taskfunction_t )start_task, //任务函数 (const char* )start_task, //任务名称 (uint16_t )start_stk_size, //任务堆栈大小 (void* )null, //传递给任务函数的参数 (ubasetype_t )start_task_prio, //任务优先级 (taskhandle_t* )&starttask_handler //任务句柄 ); vtaskstartscheduler(); //开启调度}//开始任务函数void start_task(void *pvparameters){ taskenter_critical(); //进入临界区 /* 创建test_queue */ mutex_handle = xsemaphorecreatemutex(); if(mutex_handle != null) { xsemaphoregive(mutex_handle);//释放信号量 } //创建 low 任务 xtaskcreate( (taskfunction_t )low_task, (const char* )low_task, (uint16_t )low_stk_size, (void* )null, (ubasetype_t )low_task_prio, (taskhandle_t* )&lowtask_handler ); //创建 med 任务 xtaskcreate( (taskfunction_t )med_task, (const char* )med_task, (uint16_t )med_stk_size, (void* )null, (ubasetype_t )med_task_prio, (taskhandle_t* )&medtask_handler ); //创建 high 任务 xtaskcreate( (taskfunction_t )high_task, (const char* )high_task, (uint16_t )high_stk_size, (void* )null, (ubasetype_t )high_task_prio, (taskhandle_t* )&hightask_handler ); vtaskdelete(starttask_handler); //删除开始任务 taskexit_critical(); //退出临界区}void low_task(void *pvparameters){ int count = 0; while(1) { printf(low正在等待n); xsemaphoretake(mutex_handle,portmax_delay); printf(low获取成功%d次n,++count); delay_ms(5000); xsemaphoregive(mutex_handle);//释放信号量 vtaskdelay(50); }}void med_task(void *pvparameters){ //basetype_t xreturn = null; while(1) { printf(正在运行n); vtaskdelay(50); }}void high_task(void *pvparameters){ int count = 0; while(1) { printf(high正在等待n); xsemaphoretake(mutex_handle,portmax_delay); printf(high获取成功%d次n,++count); xsemaphoregive(mutex_handle);//释放信号量 vtaskdelay(50); }}  
实验现象
解读:互斥信号量,其实就是将low任务的优先级和high任务的优先级变成了一样的优先级(短暂拉高最低优先级任务),从而解决优先级翻转问题

大幅面扫描仪的扫描速度
d型空气开关和c型空气开关的区别
dfrobot树莓派UPS电源扩展板简介
智能门禁电源的注意事项你都知道吗!
日本对韩限贸后首次批准向韩国出口半导体制造材料
Free RTOS的互斥信号量
什么是步进电机?步进电机的种类
智芯传感连续荣获国家“高新技术企业”称号
苹果AirPods:称霸无线耳机市场,拿下八成市占率
智能锁企业想要脱颖而出 首先要做到以下几条
太阳能电站成清洁机器人首个商用级目标市场
分享一个图形化PING测试工具
电流互感器的低频率补偿电路图
你知道什么是铁基板吗
SIMV薄膜表面瑕疵在线检测设备的原理、参数及特点
模拟信号有哪些常见参数?放大器的功能有哪些?
紫光同芯又双叒叕荣获中国芯“优秀技术创新产品”奖
为什么机器人需要5G技术
使用Verilog实现基于FPGA的SDRAM控制器
【笔记】单片机的“身份证号码”实现的三种方式