以下内容主要注重应用,对源码不做分析,对源码有兴趣的可参考官方具体文档,相关链接:https://doc.micrium.com/display/ucos/
开发环境:TrueSTUDIO
单片机:STM32F103VET6(HAL库)
一、创建一个信号量,OSSemCreate()
信号量需要创建才能被使用,通过调用OSSemCreate()函数创建信号量,并指定初始信号量的数目,初始信号量的取值范围是0~65535。如果您使用信号量来表示一个或多个事件的发生,您通常会将信号量初始化为0。如果您使用这个信号量来访问一个共享资源,那么您需要将这个信号量初始化为1(也就是说,将它用作二进制信号量)。如果该信号量允许应用程序获得n个相同资源中的任何一个,则将该信号量初始化为n,并将其用作计数信号量。函数的原型为:
1、OS_EVENT *OSSemCreate (INT16U cnt)。
- cnt是指初始可用信号量的数目;
- 返回与信号量相关联的指向事件控制块的指针。
二、发送一个信号量,OSSemPost()
发送信号量,函数原型为:
1、INT8U OSSemPost (OS_EVENT *pevent)。
- pevent是信号量相关联的指向事件控制块的指针;
- 返回值是错误类型。
三、等待一个信号量,OSSemPend()
如果没有可用的信号量,则等待信号量,函数原型为:
1、void
OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)。
- pevent是信号量相关联的指向事件控制块的指针;
- timeout等待时长(如果是0将一直等下去,直到有可用的信号量);
- err保存错误类型。
四、示例代码(非中断方式)
1、定义一个信号量事件指针:
/* 定义一个信号量事件指针 */ OS_EVENT *Semp;
2、创建信号量,初始可用的信号量为0:
/* 创建信号量,初始可用的信号量为0 */ Semp = OSSemCreate(0);
3、在一个任务中发送信号量
static void AppTask1(void *p_arg) { (void)p_arg; while(1) { /* 发送一个信号量 */ OSSemPost(Semp); OSTimeDlyHMSM(0, 0, 1, 0); } }
4、在一个任务中接收信号量
static void AppTaskLed(void *p_arg) { INT8U err; (void)p_arg; while(1) { /* 等待一个信号量 */ OSSemPend(Semp, 0, &err); if(err == OS_ERR_NONE) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); } } }
五、示例代码(中断方式)
1、定义信号量事件指针:
/* 定义信号量事件指针 */ OS_EVENT *Semp1; OS_EVENT *Semp2;
2、创建信号量,初始可用的信号量为0:
/* 创建两个信号量,初始可用的信号量都为0 */ Semp1 = OSSemCreate(0); Semp2 = OSSemCreate(0);
3、中断函数中进行针对μC/OS系统的处理:
/** * @brief This function handles EXTI line0 interrupt. */ void EXTI0_IRQHandler(void) { #if uCOS_EN == 1 #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif OS_ENTER_CRITICAL(); OSIntEnter(); OS_EXIT_CRITICAL(); #endif HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); #if uCOS_EN == 1 OSIntExit(); #endif } /** * @brief This function handles EXTI line[15:10] interrupts. */ void EXTI15_10_IRQHandler(void) { #if uCOS_EN == 1 #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif OS_ENTER_CRITICAL(); OSIntEnter(); OS_EXIT_CRITICAL(); #endif HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); #if uCOS_EN == 1 OSIntExit(); #endif }
4、在中断的回调函数中发送信号量,针对不同端口引脚被触发发送不同的信号量:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_0) { /* 发送信号量 */ OSSemPost(Semp1); } if(GPIO_Pin == GPIO_PIN_13) { /* 发送信号量 */ OSSemPost(Semp2); } }
5、在两个任务分别去接收中断发出的信号量:
static void AppTaskLed1(void *p_arg) { INT8U err; (void)p_arg; while(1) { /* 等待可用的信号量 */ OSSemPend(Semp1, 0, &err); if(err == OS_ERR_NONE) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); } } } static void AppTaskLed2(void *p_arg) { INT8U err; (void)p_arg; while(1) { /* 等待可用的信号量 */ OSSemPend(Semp2, 0, &err); if(err == OS_ERR_NONE) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); } } }
#endif