zoukankan      html  css  js  c++  java
  • μC/OS-II系统中信号量的使用

    以下内容主要注重应用,对源码不做分析,对源码有兴趣的可参考官方具体文档,相关链接: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

  • 相关阅读:
    Lua笔记——8.Lua & C
    Shader笔记——5.渲染纹理
    常用工具——2.Mac
    Shader笔记——4.纹理基础
    设计模式学习笔记四:简单工厂模式抽象工厂模式工厂方法模式
    设计模式学习笔记三:策略模式和状态模式
    设计模式学习笔记二:单例模式
    设计模式学习笔记一:程序设计原则
    数据结构和算法学习笔记十六:红黑树
    数据结构和算法学习笔记十五:多路查找树(B树)
  • 原文地址:https://www.cnblogs.com/wenhao-Web/p/13797416.html
Copyright © 2011-2022 走看看