打印
[STM32F1]

ucos-3的应用之外部中断

[复制链接]
3633|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
小小小小白|  楼主 | 2014-7-5 10:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    按键消抖,这个古老的话题,如今再拿出来和大家讨论讨论。
    本文不仅讨论按键消抖,也说说ucos-3的使用。
    几句话概括完ucos-3的功能。
    用于时间管理的有两个函数,一个是OSTimeDly();另一个是OSTimeDlyHMSM();其实也就是用于延时,具体的用法大家查查API就知道了。
    然后定时器&回调函数,对于cortex-M3,定时器是基于systick定时器模拟的,可以创建无数个定时器。但是精度取决于systick(一般为10-1000Hz),相对较低。不能用于高精度定时。
    用于资源管理的是互斥型信号量,也可以使用信号量,但可能造成任务优先级反转,所以推荐使用互斥型信号量。
    任务同步用信号量,也可以用事件标志组。信号量具体的用法比如我们可以在ISR里边向对应的任务发送信号量,这样能大大缩短ISR的执行时间。事件标志组用于多任务同步。
    用于消息传递的是消息队列。注意消息与信号的区别。信号只是0或者1(可以递增,表示事件发生了多少次),标志某种事件的发生与否。而消息是一个指针,可以指向任意的数据结构,甚至函数。

    大致就说到这儿。下面是我做的按键外部中断的代码。

/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/


#include <includes.h>


/*
*********************************************************************************************************
*                                                main()
*
* Description : This is the standard entry point for C code.  It is assumed that your code will call
*               main() once you have performed all necessary initialization.
*
* Arguments   : none
*
* Returns     : none
*********************************************************************************************************
*/


int  main (void)
{
    OS_ERR  err;




    BSP_IntDisAll();                                            /* Disable all interrupts.                              */


    OSInit(&err);                                               /* Init uC/OS-III.                                      */


    OSTaskCreate((OS_TCB     *)&AppTaskStartTCB,                /* Create the start task                                */
                 (CPU_CHAR   *)"App Task Start",
                 (OS_TASK_PTR ) AppTaskStart,
                 (void       *) 0,
                 (OS_PRIO     ) APP_TASK_START_PRIO,
                 (CPU_STK    *)&AppTaskStartStk[0],
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE,
                 (OS_MSG_QTY  ) 5u,
                 (OS_TICK     ) 0u,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&err);


    OSStart(&err);                                              /* Start multitasking (i.e. give control to uC/OS-III). */
//        SystemInit();
}




/*
*********************************************************************************************************
*                                          STARTUP TASK
*
* Description : This is an example of a startup task.  As mentioned in the book's text, you MUST
*               initialize the ticker only once multitasking has started.
*
* Arguments   : p_arg   is the argument passed to 'AppTaskStart()' by 'OSTaskCreate()'.
*
* Returns     : none
*
* Notes       : 1) The first line of code is used to prevent a compiler warning because 'p_arg' is not
*                  used.  The compiler should not generate any code for this statement.
*********************************************************************************************************
*/


static  void  AppTaskStart (void *p_arg)
{
    CPU_INT32U  cpu_clk_freq;
    CPU_INT32U  cnts;
    OS_ERR      err;




   (void)p_arg;


    BSP_Init();                                                 /* Initialize BSP functions                             */
    CPU_Init();


    cpu_clk_freq = BSP_CPU_ClkFreq();                           /* Determine SysTick reference freq.                    */
    cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz ;        /* Determine nbr SysTick increments                     */
    OS_CPU_SysTickInit(cnts);                                   /* Init uC/OS periodic time src (SysTick).              */


    Mem_Init();                                                 /* Initialize Memory Management Module                  */


#if OS_CFG_STAT_TASK_EN > 0u
    OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif


    CPU_IntDisMeasMaxCurReset();


//#if (APP_CFG_SERIAL_EN == DEF_ENABLED)
//    BSP_Ser_Init(115200);                                       /* Enable Serial Interface                              */
//#endif
    STM_EVAL_COMInit(COM2);


    printf("Creating Application Events...\n\r");
    AppObjCreate();                                             /* Create Application Objects                           */


    printf("Creating Application Tasks...\n\r");
    AppTaskCreate();                                            /* Create Application Tasks                             */
   
        printf("cpu_clk_freq:  %dMHz\n\r",cpu_clk_freq/1000000);
   
    BSP_LED_Off(0);


        BSP_BEEP_On();


    OSTimeDlyHMSM(0, 0, 0, 10,
                        OS_OPT_TIME_HMSM_STRICT,
                  &err);
       
        BSP_BEEP_Off();
       
    while (DEF_TRUE)
        {                                          /* Task body, always written as an infinite loop.       */
        BSP_LED_Toggle(1);
        OSTimeDlyHMSM(0, 0, 0, 500,
                      OS_OPT_TIME_HMSM_STRICT,
                      &err);
    }
}




/*
*********************************************************************************************************
*                                      CREATE APPLICATION TASKS
*
* Description:  This function creates the application tasks.
*
* Arguments  :  none
*
* Returns    :  none
*********************************************************************************************************
*/


static  void  AppTaskCreate (void)
{
        OS_ERR  err;


    OSTaskCreate((OS_TCB     *)&AppTask_EXTI4_TCB,
                     (CPU_CHAR   *)"App Task EXTI4",
                     (OS_TASK_PTR )AppTaskEXTI4,
                     (void       *)0,
                     (OS_PRIO     )APP_TASK_EXTI4_PRIO,
                     (CPU_STK    *)&AppTask_EXTI4_Stk[0],
                     (CPU_STK_SIZE)APP_TASK_EXTI4_STK_SIZE / 10,
                     (CPU_STK_SIZE)APP_TASK_EXTI4_STK_SIZE,
                     (OS_MSG_QTY  )10,
                     (OS_TICK     ) 0,
                     (void       *) 0,
                     (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                     (OS_ERR     *)&err);


        OSTaskCreate((OS_TCB     *)&AppTask_EXTI15_10_TCB,
                     (CPU_CHAR   *)"App Task EXTI15_10",
                     (OS_TASK_PTR )AppTaskEXTI15_10,
                     (void       *)0,
                     (OS_PRIO     )APP_TASK_EXTI15_10_PRIO,
                     (CPU_STK    *)&AppTask_EXTI15_10_Stk[0],
                     (CPU_STK_SIZE)APP_TASK_EXTI15_10_STK_SIZE / 10,
                     (CPU_STK_SIZE)APP_TASK_EXTI15_10_STK_SIZE,
                     (OS_MSG_QTY  )10,
                     (OS_TICK     ) 0,
                     (void       *) 0,
                     (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                     (OS_ERR     *)&err);


        if(err==OS_ERR_NONE)
                printf("OSTaskCreate OK!\n\r");
        else
                printf("OSTaskCreate err=%d\n\r",err);


}




/*
*********************************************************************************************************
*                                      CREATE APPLICATION EVENTS
*
* Description:  This function creates the application kernel objects.
*
* Arguments  :  none
*
* Returns    :  none
*********************************************************************************************************
*/


static  void  AppObjCreate (void)
{
       
}






static  void  AppTaskEXTI4   (void *p_arg)
{
        OS_ERR       err;
        OS_SEM_CTR   ctr;
        CPU_TS       ts;
        static       NVIC_InitTypeDef   NVIC_InitStructure;


        NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;


        BSP_IntVectSet((CPU_INT08U   )BSP_INT_ID_EXTI4,          /* Set the Interrupt vector                              */
                   (CPU_FNCT_VOID)App_IntHandlerEXTI4);


        while(1)
        {       
                ctr=OSTaskSemPend(0, OS_OPT_PEND_BLOCKING, &ts, &err);


                NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;          //关中断
            NVIC_Init(&NVIC_InitStructure);


                BSP_LED_Toggle(2);


                OSTaskSemSet(&AppTask_EXTI4_TCB, 0, &err);                          //设置ctr=0


                printf("AppTaskEXTI4 ctr=%d\n\r",ctr);


                OSTimeDlyHMSM(0, 0, 1, 0,                                                          //延时
                      OS_OPT_TIME_HMSM_STRICT,
                      &err);


                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //开中断
            NVIC_Init(&NVIC_InitStructure);
                                                                                          
        }       
}


static  void  AppTaskEXTI15_10   (void *p_arg)
{
        OS_ERR       err;
        OS_SEM_CTR   ctr;
        CPU_TS       ts;
        static       NVIC_InitTypeDef   NVIC_InitStructure;


        NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;


          BSP_IntVectSet((CPU_INT08U   )BSP_INT_ID_EXTI15_10,          /* Set the Interrupt vector                              */
                   (CPU_FNCT_VOID)App_IntHandlerEXTI15_10);


        while(1)
        {       
                ctr=OSTaskSemPend(0, OS_OPT_PEND_BLOCKING, &ts, &err);


                NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;          //关中断
            NVIC_Init(&NVIC_InitStructure);


                BSP_LED_Toggle(3);


                OSTaskSemSet(&AppTask_EXTI15_10_TCB, 0, &err);                  //设置ctr=0


                printf("AppTaskEXTI15_10 ctr=%d\n\r",ctr);


                OSTimeDlyHMSM(0, 0, 1, 0,                                                          //延时
                      OS_OPT_TIME_HMSM_STRICT,
                      &err);


                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //开中断
            NVIC_Init(&NVIC_InitStructure);
                                                                                          
        }       
}












static  void  App_IntHandlerEXTI4 (void)
{
    OS_ERR  err;


        EXTI_ClearITPendingBit(EXTI_Line4);               /* Clear the Timer #1 Update interrupt                            */
       
        OSTaskSemPost(&AppTask_EXTI4_TCB, OS_OPT_POST_NO_SCHED, &err);       
}




static  void  App_IntHandlerEXTI15_10(void)
{
    OS_ERR  err;


        if(EXTI_GetFlagStatus(EXTI_Line10)==SET)
        {
                EXTI_ClearITPendingBit(EXTI_Line10);               /* Clear the Timer #1 Update interrupt                    */       
       
                OSTaskSemPost(&AppTask_EXTI15_10_TCB, OS_OPT_POST_NO_SCHED, &err);
        }
}


    有一点需要注意,内核对象需要在创建任务之前建立,也就是AppObjCreate();  要在AppTaskCreate();之前执行。
    程序的整体思路是ISR给任务发送信号量,然后在任务里边关中断,LED取反,延时1s,再开中断。之所以延时1s,是因为按键按下和松开都会有抖动的波形,触发中断。所以我希望用户在1s内按下并且松开按键。但是现在还是不够稳定。有时候会执行一次,有时候是两次。这里应该是NVIC的问题,大家帮忙看看,共同讨论。
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

515

帖子

4

粉丝