打印
[应用相关]

UCOSII-软件定时器

[复制链接]
1620|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zljiu|  楼主 | 2021-7-8 10:10 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一.软件定时器简介
定时器本质上是递减计数器,当计数器减到0可以触发某种动作的执行(这里采用回调函数的方式,计数值到0后执行一次回调函数),UCOSSII支持任一数量的定时器。
回调函数就是一个通过指针调用的函数。如果把函数的指针(地址)作为参数传递给另外一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应。


使用特权

评论回复
沙发
zljiu|  楼主 | 2021-7-8 10:11 | 只看该作者
二.软件定时器的相关API函数
OSTmrCreate();       //1.创建定时器并制定运行模式****
OSTmrDel();          //2.删除定时器*
OSTmrRemainGet();    //3.获取定时器的剩余时间
OSTmrStart();        //4.启动定时器计数***
OSTmrStateGet();     //5.获取当前定时器状态
OSTmrStop();         //6.停止计数器倒计时***


其中创建,开始,停止函数用的比较多。


使用特权

评论回复
板凳
zljiu|  楼主 | 2021-7-8 10:12 | 只看该作者
三.UCOSII中软件定时器的配置步骤
1.在os_cfg.h文件夹中使能条件编译
OS_TMR_EN=1u

2.创建定时器:
OS_TMR   * tmr1;                           //软件定时器1
OS_TMR   * tmr2;                           //软件定时器2
OS_TMR   * tmr3;                           //软件定时器3



3.创建回调函数:
//软件定时器1的回调函数       
//每100ms执行一次             
void tmr1_callback(OS_TMR *ptmr,void *p_arg)
{   
   .....................................................
}
//软件定时器2的回调函数,200ms溢出一次                                    
void tmr2_callback(OS_TMR *ptmr,void *p_arg)
{       
   .....................................................                                                                                  
}
//软件定时器3的回调函数,100ms溢出一次                            
void tmr3_callback(OS_TMR *ptmr,void *p_arg)
{       
   .....................................................
}



4.创建定时器:
OSTmrCreate()函数原型:

/* Description: This function is called by your application code to create a timer.
*
* Arguments  : dly           Initial delay.
*                            If the timer is configured for ONE-SHOT mode, this is the timeout used
*                            If the timer is configured for PERIODIC mode, this is the first timeout to wait for
*                               before the timer starts entering periodic mode
*
*              period        The 'period' being repeated for the timer.
*                               If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer expires, it will
*                               automatically restart with the same period.
*
*              opt           Specifies either:
*                               OS_TMR_OPT_ONE_SHOT       The timer counts down only once
*                               OS_TMR_OPT_PERIODIC       The timer counts down and then reloads itself
*
*              callback      Is a pointer to a callback function that will be called when the timer expires.  The
*                               callback function must be declared as follows:
*
*                               void MyCallback (OS_TMR *ptmr, void *p_arg);
*
*              callback_arg  Is an argument (a pointer) that is passed to the callback function when it is called.
*
*              pname         Is a pointer to an ASCII string that is used to name the timer.  Names are useful for
*                               debugging.
*
*              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
*                               OS_ERR_NONE
*                               OS_ERR_TMR_INVALID_DLY     you specified an invalid delay
*                               OS_ERR_TMR_INVALID_PERIOD  you specified an invalid period
*                               OS_ERR_TMR_INVALID_OPT     you specified an invalid option
*                               OS_ERR_TMR_ISR             if the call was made from an ISR
*                               OS_ERR_TMR_NON_AVAIL       if there are no free timers from the timer pool
*/
#if OS_TMR_EN > 0u            //条件编译使能
OS_TMR  *OSTmrCreate (INT32U           dly,     //单次定时延时时长,或循环定时初始延时时长
                      INT32U           period,  //周期定时延时时长
                      INT8U            opt,     //定时模式选择:单次/循环
                      OS_TMR_CALLBACK  callback,//回调函数
                      void            *callback_arg,
                      INT8U           *pname,   //定时器名称
                      INT8U           *perr)    //返回错误信息指针
{
    OS_TMR   *ptmr;
#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
    }
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
    if (OSSafetyCriticalStartFlag == OS_TRUE) {
        OS_SAFETY_CRITICAL_EXCEPTION();
    }
#endif

#if OS_ARG_CHK_EN > 0u
    switch (opt) {                                          //Validate arguments
        case OS_TMR_OPT_PERIODIC:
             if (period == 0u) {
                 *perr = OS_ERR_TMR_INVALID_PERIOD;
                 return ((OS_TMR *)0);
             }
             break;

        case OS_TMR_OPT_ONE_SHOT:
             if (dly == 0u) {
                 *perr = OS_ERR_TMR_INVALID_DLY;
                 return ((OS_TMR *)0);
             }
             break;

        default:
             *perr = OS_ERR_TMR_INVALID_OPT;
             return ((OS_TMR *)0);
    }
#endif
    if (OSIntNesting > 0u) {                                /* See if trying to call from an ISR                      */
        *perr  = OS_ERR_TMR_ISR;
        return ((OS_TMR *)0);
    }
    OSSchedLock();
    ptmr = OSTmr_Alloc();                                   /* Obtain a timer from the free pool                      */
    if (ptmr == (OS_TMR *)0) {
        OSSchedUnlock();
        *perr = OS_ERR_TMR_NON_AVAIL;
        return ((OS_TMR *)0);
    }
    ptmr->OSTmrState       = OS_TMR_STATE_STOPPED;          /* Indicate that timer is not running yet                 */
    ptmr->OSTmrDly         = dly;
    ptmr->OSTmrPeriod      = period;
    ptmr->OSTmrOpt         = opt;
    ptmr->OSTmrCallback    = callback;
    ptmr->OSTmrCallbackArg = callback_arg;
#if OS_TMR_CFG_NAME_EN > 0u
    ptmr->OSTmrName        = pname;
#endif
    OSSchedUnlock();
    *perr = OS_ERR_NONE;
    return (ptmr);
}
#endif


OSTmrCreate()函数调用:


        tmr1=OSTmrCreate(10,10,OS_TMR_OPT_PERIODIC,(OS_TMR_CALLBACK)tmr1_callback,0,"tmr1",&err);                //100ms执行一次,周期循环模式
        tmr2=OSTmrCreate(10,20,OS_TMR_OPT_PERIODIC,(OS_TMR_CALLBACK)tmr2_callback,0,"tmr2",&err);                //200ms执行一次,周期循环模式
        tmr3=OSTmrCreate(10,10,OS_TMR_OPT_PERIODIC,(OS_TMR_CALLBACK)tmr3_callback,0,"tmr3",&err);                //100ms执行一次,周期循环模式



使用特权

评论回复
地板
zljiu|  楼主 | 2021-7-8 10:13 | 只看该作者
创建定时器单次定时模式(ONE-SHOT mode):

创建定时器循环定时模式(PERIODIC mode),有根据初始计数值dly的设置来分为无初始延迟,有初始延迟模式。


使用特权

评论回复
5
zljiu|  楼主 | 2021-7-8 10:14 | 只看该作者
5.启动定时器:
        OSTmrStart(tmr1,&err);              //启动软件定时器1                                 
        OSTmrStart(tmr2,&err);              //启动软件定时器2                                 
        OSTmrStart(tmr3,&err);              //启动软件定时器3       



6.关闭定时器:
        tmr2sta=!tmr2sta;
        if(tmr2sta)OSTmrStart(tmr2,&err);                                    //开启软件定时器2
        else
        {                                        
                  OSTmrStop(tmr2,OS_TMR_OPT_NONE,0,&err);              //关闭软件定时器2
                LCD_ShowString(148,262,240,16,16,"TMR2 STOP");//提示定时器2关闭了       
        }



四.小结
UCOSSII软件定时器和我们平时使用的定时器基本一致,都是在计数时间到了以后执行某个动作,不同的是我们平时用的定时器是采用中断执行的方式,而这里的定时器是采用回调函数的方式执行事件,大同小异。
软件定时器的配置较为简单,首先创建一个定时器,然后启用它之后便开始计时,停止它便停止计时,在UCOSII操作系统中简单好用!


使用特权

评论回复
6
木木guainv| | 2021-8-6 14:32 | 只看该作者
定时精度能达到多少啊

使用特权

评论回复
7
xiaoqizi| | 2021-8-6 14:36 | 只看该作者
长时间的定时偏差会不会很大呢

使用特权

评论回复
8
wowu| | 2021-8-6 14:40 | 只看该作者
所有的额定时器都是可用的吗

使用特权

评论回复
9
wakayi| | 2021-8-6 14:44 | 只看该作者
这种实时性还是很不错的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

3323

帖子

3

粉丝