硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3824|回复: 9
收起左侧

[RL-RTX] 【RTX操作系统教程】第17章    定时器组

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2016-1-5 17:11:22 | 显示全部楼层 |阅读模式
第17章    定时器组


    本章节为大家讲解RTX支持的定时器组,或者叫软件定时器,或者叫用户定时器均可。软件定时器的功能比较简单,也容易掌握。被称为定时器组是因为用户可以创建多个定时器,创建的个数是可配置的。
    本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。
    17.1   定时器组介绍
    17.2   定时器组API函数
    17.3   实验例程说明
     17.4    总结
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-1-5 17:12:40 | 显示全部楼层
17.1   定时器组介绍

    RTX提供的定时器功能仅支持单次定时器,也就是用户创建了定时器并启动了定时器后,定时时间到将不再重新执行,此定时器会被删除掉并且就执行一次,下次使用要重新的创建,这个就是单次定时器的含义。另外就是单次定时时间到后会调用定时器的回调函数,用户可以回调函数中加入需要执行的工程代码。
    使用此定时器组注意以下问题:
u 定时器回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
u 定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,因为回调函数是在滴答定时器中断中执行的。
u RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建。
u  可以创建的定时器个数可以在RTX配置向导中设置:
17.1.png
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-1-5 17:14:56 | 显示全部楼层
17.2 定时器组API函数


    使用如下3个函数可以实现RTX的定时器组:
u os_tmr_create
u os_tmr_kill
u os_tmr_call
关于这3个函数的讲解及其使用方法可以看教程第3章3.3小节里面说的参考资料rlarm.chm文件
17.2.png

这里我们重点的说一下函数os_tmr_create和os_tmr_call。

17.2.1 函数os_tmr_create


函数原型:
  1. OS_ID os_tmr_create (
  2.     U16 tcnt,      /* 定时器的时钟节拍个数 */
  3.     U16 info );    /* 定时器回调函数的参数,可用于区分不同的定时器 */
复制代码
函数描述:
函数os_tmr_create用于创建定时器组并启动定时器,定时时间到后调用回调函数os_tmr_call。函数os_tmr_create的第二个参数也会传递给回调函数os_tmr_call用于区分不同的定时器。
u 第1个参数填写定时器的时钟节拍个数。范围0-0xFFFF。
u 第2个参数填写回调函数的参数,可用于区分不同的定时器。
u 定时器创建成功的话会返回定时器的ID标识,失败的话返回NULL。
使用举例:
  1. #include <rtl.h>
  2. /* 定时器句柄 */
  3. OS_ID  OneShotTimerID1;
  4. __task void task1 (void) {
  5.    ..
  6.   OneShotTimerID1= os_tmr_create (10, 1);
  7.   if (OneShotTimerID1 == NULL) {
  8.     printf ("创建失败\\n");
  9.   }
  10.    ..
  11. }
复制代码

17.2.2 函数os_tmr_call


函数原型:
  1. void os_tmr_call (
  2.     U16 info );    /*定时器回调函数的参数,可用于区分不同的定时器*/
复制代码
函数描述:
当函数os_tmr_create设置的定时时间到后调用回调函数os_tmr_call。函数os_tmr_create的第二个参数也会传递给回调函数os_tmr_call用于区分不同的定时器。此函数执行完毕后,通过函数os_tmr_create创建的定时器会被删除,下次使用需要重新创建。
u 此函数的参数不需要用户去添加,系统会自动将函数os_tmr_create第二个参数赋值给这个参数。
使用举例:
  1. #include <rtl.h>
  2. void os_tmr_call (U16 info) {
  3.   /* 定时器回调函数中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在
  4.      滴答定时器中断中执行的。
  5.   */
  6.   switch(info)
  7.   {
  8. case 1:          /* 参数为1 */
  9.          isr_sem_send (&semaphore);     
  10.          break;
  11.          
  12.       case 2:          /* 参数为2 */
  13.         bsp_LedToggle(1);   
  14.         break;
  15.   }
  16. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-1-5 17:22:09 | 显示全部楼层
17.3 实验例程说明

17.3.1 STM32F103开发板实验

配套例子:
    V4-416_RTX实验_定时器组
实验目的:
    1.     学习RTX的定时器组
    2.     RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建
    3.     定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在滴答定时器中断中执行的。
    4.     回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务AppTaskMsgPro发信号量同步信号。
    3.K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1。
    4.各个任务实现的功能如下:
      AppTaskUserIF任务   :按键消息处理。
      AppTaskLED任务     :LED闪烁。
      AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
      AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
17.3.png

u  Task Configuration
l Number of concurrent running tasks
    允许创建4个任务,实际创建了如下四个任务:
                     AppTaskUserIF任务   :按键消息处理。
                     AppTaskLED任务     :LED闪烁。
                    AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
                    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
    创建的4个任务都是采用自定义堆栈方式。
l Number of user timers
    范围1 – 250,表示用户定时器个数。
    这里创建了1个用户定时器。
RTX任务调试信息:
17.4.png

程序设计:
u  任务栈大小分配:
     staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
     staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
     staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
     staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
       将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
u  系统栈大小分配:
17.5.png

u  RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码
u  RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码
u  创建信号量:
  1. OS_SEM semaphore;
  2. /*
  3. *********************************************************************************************************
  4. *    函 数 名: AppObjCreate
  5. *    功能说明: 创建任务通信机制
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. static void AppObjCreate (void)
  11. {
  12.      /* 创建信号量计数值是0, 用于任务同步 */
  13.      os_sem_init (&semaphore, 0);
  14.    
  15. }
复制代码
u  四个RTX任务的实现,定时器的创建在任务AppTaskUserIF中实现:
  1. /*
  2. /*
  3. *********************************************************************************************************
  4. *    函 数 名: AppTaskUserIF
  5. *    功能说明: 按键消息处理     
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  9. *********************************************************************************************************
  10. */
  11. __task void AppTaskUserIF(void)
  12. {
  13.      uint8_t ucKeyCode;
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下,打印调试说明 */
  23.                    case KEY_DOWN_K1:
  24.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\\r\\n");
  25.                        break;  
  26.                   
  27.                    /*
  28.                       K2键按下,创建单次定时器,定时时间10个系统时钟节拍, 在定时器回调函数中给任务
  29.                       AppTaskMsgPro发信号量同步信号
  30.                    */
  31.                    case KEY_DOWN_K2:
  32.                        printf("K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务
  33. AppTaskMsgPro发信号量同步信号\\r\\n");
  34.                        /*
  35.                          1. RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建
  36.                          2. 定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函
  37. 数是在滴答定时器中断中执行的。
  38.                          3. 回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
  39.                        */
  40.                        OneShotTimerID1 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */
  41.                                                       1);  /* 回调函数的参数,可用于区分不同的定时器 */
  42.                      
  43.                        if (OneShotTimerID1 == NULL)
  44.                        {
  45.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
  46.                        }
  47.                        break;
  48.                      
  49.                    case KEY_DOWN_K3:
  50.                        printf("K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1\\r\\n");
  51.                        OneShotTimerID2 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */
  52.                                                        2);  /* 回调函数的参数,可用于区分不同的定时器 */
  53.                      
  54.                        if (OneShotTimerID2 == NULL)
  55.                        {
  56.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
  57.                        }
  58.                        break;
  59.                    /* 其他的键值不处理 */
  60.                    default:                    
  61.                        break;
  62.               }
  63.          }
  64.         
  65.          os_dly_wait(20);
  66.      }
  67. }
  68. /*
  69. *********************************************************************************************************
  70. *    函 数 名: AppTaskLED
  71. *    功能说明: LED闪烁。
  72. *    形    参: 无
  73. *    返 回 值: 无
  74. *   优 先 级: 2
  75. *********************************************************************************************************
  76. */
  77. __task void AppTaskLED(void)
  78. {
  79.      const uint16_t usFrequency = 200; /* 延迟周期 */
  80.    
  81.      /* 设置延迟周期 */
  82.      os_itv_set(usFrequency);
  83.    
  84.     while(1)
  85.     {
  86.          bsp_LedToggle(2);
  87.          bsp_LedToggle(3);
  88.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  89.          os_itv_wait();
  90.     }
  91. }
  92. /*
  93. *********************************************************************************************************
  94. *    函 数 名: AppTaskMsgPro
  95. *    功能说明: 消息处理,等待RTX定时器发来的信号量同步信号
  96. *    形    参: 无
  97. *    返 回 值: 无
  98. *   优 先 级: 3
  99. *********************************************************************************************************
  100. */
  101. __task void AppTaskMsgPro(void)
  102. {
  103.      OS_RESULT xResult;
  104.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
  105.    
  106.     while(1)
  107.     {
  108.          xResult = os_sem_wait (&semaphore, usMaxBlockTime);
  109.         
  110.          switch (xResult)
  111.          {
  112.               /* 无需等待接受到信号量同步信号 */
  113.               case OS_R_OK:
  114.                    printf("无需等待接受到信号量同步信号\\r\\n");
  115.                    break;  
  116.               /* 信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号 */
  117.               case OS_R_SEM:
  118.                    printf("信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号\\r\\n");
  119.                    break;
  120.               /* 超时 */
  121.               case OS_R_TMO:
  122.                    bsp_LedToggle(4);
  123.                    break;
  124.             
  125.               /* 其他值不处理 */
  126.               default:                    
  127.                    break;
  128.          }   
  129.     }
  130. }
  131. /*
  132. *********************************************************************************************************
  133. *    函 数 名: AppTaskStart
  134. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
  135. *    形    参: 无
  136. *    返 回 值: 无
  137. *   优 先 级: 4
  138. *********************************************************************************************************
  139. */
  140. __task void AppTaskStart(void)
  141. {
  142.      /* 创建任务 */
  143.      AppTaskCreate();
  144.    
  145.      /* 创建任务通信机制 */
  146.      AppObjCreate();
  147.    
  148.     while(1)
  149.     {
  150.          /* 按键扫描 */
  151.          bsp_KeyScan();
  152.         os_dly_wait(10);
  153.     }
  154. }
复制代码
u  定时器回调函数的实现,在文件RTX_Conf_CM.c:
  1. /*--------------------------- os_tmr_call -----------------------------------*/
  2. #include "bsp.h"
  3. extern OS_SEM semaphore;
  4. void os_tmr_call (U16 info) {
  5.   /* This function is called when the user timer has expired. Parameter   */
  6.   /* 'info' holds the value, defined when the timer was created.          */
  7.   /* HERE: include optional user code to be executed on timeout. */
  8.   /* 定时器回调函数中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在
  9.      滴答定时器中断中执行的。
  10.   */
  11.   switch(info)
  12.   {
  13.      case 1:          /* 参数为1 */
  14.       isr_sem_send (&semaphore);     
  15.       break;
  16.    
  17.      case 2:          /* 参数为2 */
  18.        bsp_LedToggle(1);   
  19.       break;
  20.   }
  21. }
复制代码

17.3.2 STM32F407开发板实验

配套例子:
    V4-416_RTX实验_定时器组
实验目的:
    1.     学习RTX的定时器组。
    2.     RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建。
    3.     定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在滴答定时器中断中执行的。
    4.     回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务AppTaskMsgPro发信号量同步信号。
    3.K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1。
    4.各个任务实现的功能如下:
     AppTaskUserIF任务   :按键消息处理。
     AppTaskLED任务     :LED闪烁。
     AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
     AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
     RTX配置向导详情如下:
17.6.png

u  Task Configuration
l Number of concurrent running tasks
    允许创建4个任务,实际创建了如下四个任务:
                    AppTaskUserIF任务   :按键消息处理。
                    AppTaskLED任务     :LED闪烁。
                    AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
                    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
    创建的4个任务都是采用自定义堆栈方式。
l Number of user timers
    范围1 – 250,表示用户定时器个数。
     这里创建了1个用户定时器。
RTX任务调试信息:
17.7.png

程序设计:
u  任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
      将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
u  系统栈大小分配:
17.8.png

u  RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码
u  RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码
u  创建信号量:
  1. OS_SEM semaphore;
  2. /*
  3. *********************************************************************************************************
  4. *    函 数 名: AppObjCreate
  5. *    功能说明: 创建任务通信机制
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. static void AppObjCreate (void)
  11. {
  12.      /* 创建信号量计数值是0, 用于任务同步 */
  13.      os_sem_init (&semaphore, 0);
  14.    
  15. }
复制代码
u  四个RTX任务的实现,定时器的创建在任务AppTaskUserIF中实现:
  1. /*
  2. /*
  3. *********************************************************************************************************
  4. *    函 数 名: AppTaskUserIF
  5. *    功能说明: 按键消息处理     
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  9. *********************************************************************************************************
  10. */
  11. __task void AppTaskUserIF(void)
  12. {
  13.      uint8_t ucKeyCode;
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下,打印调试说明 */
  23.                    case KEY_DOWN_K1:
  24.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\\r\\n");
  25.                        break;  
  26.                   
  27.                    /*
  28.                       K2键按下,创建单次定时器,定时时间10个系统时钟节拍, 在定时器回调函数中给任务
  29.                       AppTaskMsgPro发信号量同步信号
  30.                    */
  31.                    case KEY_DOWN_K2:
  32.                        printf("K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务
  33. AppTaskMsgPro发信号量同步信号\\r\\n");
  34.                        /*
  35.                          1. RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建
  36.                          2. 定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函
  37. 数是在滴答定时器中断中执行的。
  38.                          3. 回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
  39.                        */
  40.                        OneShotTimerID1 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */
  41.                                                       1);  /* 回调函数的参数,可用于区分不同的定时器 */
  42.                      
  43.                        if (OneShotTimerID1 == NULL)
  44.                        {
  45.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
  46.                        }
  47.                        break;
  48.                      
  49.                    case KEY_DOWN_K3:
  50.                        printf("K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1\\r\\n");
  51.                        OneShotTimerID2 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */
  52.                                                        2);  /* 回调函数的参数,可用于区分不同的定时器 */
  53.                      
  54.                        if (OneShotTimerID2 == NULL)
  55.                        {
  56.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
  57.                        }
  58.                        break;
  59.                    /* 其他的键值不处理 */
  60.                    default:                    
  61.                        break;
  62.               }
  63.          }
  64.         
  65.          os_dly_wait(20);
  66.      }
  67. }
  68. /*
  69. *********************************************************************************************************
  70. *    函 数 名: AppTaskLED
  71. *    功能说明: LED闪烁。
  72. *    形    参: 无
  73. *    返 回 值: 无
  74. *   优 先 级: 2
  75. *********************************************************************************************************
  76. */
  77. __task void AppTaskLED(void)
  78. {
  79.      const uint16_t usFrequency = 200; /* 延迟周期 */
  80.    
  81.      /* 设置延迟周期 */
  82.      os_itv_set(usFrequency);
  83.    
  84.     while(1)
  85.     {
  86.          bsp_LedToggle(2);
  87.          bsp_LedToggle(3);
  88.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  89.          os_itv_wait();
  90.     }
  91. }
  92. /*
  93. *********************************************************************************************************
  94. *    函 数 名: AppTaskMsgPro
  95. *    功能说明: 消息处理,等待RTX定时器发来的信号量同步信号
  96. *    形    参: 无
  97. *    返 回 值: 无
  98. *   优 先 级: 3
  99. *********************************************************************************************************
  100. */
  101. __task void AppTaskMsgPro(void)
  102. {
  103.      OS_RESULT xResult;
  104.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
  105.    
  106.     while(1)
  107.     {
  108.          xResult = os_sem_wait (&semaphore, usMaxBlockTime);
  109.         
  110.          switch (xResult)
  111.          {
  112.               /* 无需等待接受到信号量同步信号 */
  113.               case OS_R_OK:
  114.                    printf("无需等待接受到信号量同步信号\\r\\n");
  115.                    break;  
  116.               /* 信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号 */
  117.               case OS_R_SEM:
  118.                    printf("信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号\\r\\n");
  119.                    break;
  120.               /* 超时 */
  121.               case OS_R_TMO:
  122.                    bsp_LedToggle(4);
  123.                    break;
  124.             
  125.               /* 其他值不处理 */
  126.               default:                    
  127.                    break;
  128.          }   
  129.     }
  130. }
  131. /*
  132. *********************************************************************************************************
  133. *    函 数 名: AppTaskStart
  134. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
  135. *    形    参: 无
  136. *    返 回 值: 无
  137. *   优 先 级: 4
  138. *********************************************************************************************************
  139. */
  140. __task void AppTaskStart(void)
  141. {
  142.      /* 创建任务 */
  143.      AppTaskCreate();
  144.    
  145.      /* 创建任务通信机制 */
  146.      AppObjCreate();
  147.    
  148.     while(1)
  149.     {
  150.          /* 按键扫描 */
  151.          bsp_KeyScan();
  152.         os_dly_wait(10);
  153.     }
  154. }
复制代码
u  定时器回调函数的实现,在文件RTX_Conf_CM.c:
  1. /*--------------------------- os_tmr_call -----------------------------------*/
  2. #include "bsp.h"
  3. extern OS_SEM semaphore;
  4. void os_tmr_call (U16 info) {
  5.   /* This function is called when the user timer has expired. Parameter   */
  6.   /* 'info' holds the value, defined when the timer was created.          */
  7.   /* HERE: include optional user code to be executed on timeout. */
  8.   /* 定时器回调函数中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在
  9.      滴答定时器中断中执行的。
  10.   */
  11.   switch(info)
  12.   {
  13.      case 1:          /* 参数为1 */
  14.       isr_sem_send (&semaphore);     
  15.       break;
  16.    
  17.      case 2:          /* 参数为2 */
  18.        bsp_LedToggle(1);   
  19.       break;
  20.   }
  21. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-1-5 17:23:23 | 显示全部楼层
17.4    总结

    本章节主要为大家讲解了软件定时器,对于初学者来说,比较容易掌握。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

4

主题

12

回帖

34

积分

新手上路

积分
34
发表于 2016-1-7 10:26:41 | 显示全部楼层
感觉RTX简化了API功能以获取更快的反应速度
回复

使用道具 举报

5

主题

578

回帖

593

积分

版主

Rank: 7Rank: 7Rank: 7

积分
593
发表于 2016-1-7 18:32:15 | 显示全部楼层
rtx提供了区间延时功能,差不多就是个周期定时器,不过必须作为一个任务使用

还有非常特殊的一点,软件定时器回调函数是可以调用os_前缀api的,不过一般没有意义,这是逻辑上的问题,,,

但是重新创建一个定时器却是有意义的,相当于周期定时器了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106959
QQ
发表于 2016-1-9 11:22:42 | 显示全部楼层

回 myxiaonia 的帖子

myxiaonia:rtx提供了区间延时功能,差不多就是个周期定时器,不过必须作为一个任务使用

还有非常特殊的一点,软件定时器回调函数是可以调用os_前缀api的,不过一般没有意义,这是逻辑上的问题,,,

但是重新创建一个定时器却是有意义的,相当于周期定时器了 (2016-01-07 18:32) 
感谢myxiaonia提点。[s:151]
回复

使用道具 举报

5

主题

578

回帖

593

积分

版主

Rank: 7Rank: 7Rank: 7

积分
593
发表于 2016-1-13 08:10:55 | 显示全部楼层

回 eric2013 的帖子

eric2013:感谢myxiaonia提点。[s:151] (2016-01-09 11:22) 
我修改的rtx代码里,优化了下定时器回调函数,定时到了就再次建立一个定时器,用这样的办法做成一个周期定时器

优化主要是先删除定时器链表中到期的定时器再新建定时器,这样rtx_config.c配置为一个定时器就可以建立周期定时器了,否则的话需要2个
回复

使用道具 举报

6

主题

390

回帖

408

积分

高级会员

积分
408
发表于 2016-1-13 15:09:27 | 显示全部楼层
[s:142] [s:142]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-11 22:02 , Processed in 0.205789 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表