请教一个定时器的写法

2019-12-19 18:09发布

现在的搞法
typedef        struct                        //毫秒延时结构体
{
        uint8_t         En;
        uint32_t        Cnt;                       
}DelayMs_TypeDef;

DelayMs_TypeDef msTimer1;

//初始化定时器
msTimer1.En = 1;
msTimer1.Cnt = 2000;        //2000ms

//计时
if(msTimer1.En==1)
{
        if(--msTimer1.Cnt==0)
        {
                msTimer1.En = 0;
        }
        //这里定时器时间到执行一系列动作
}

这样如果定时器一多,好像就比较繁杂了,初始化和计时又不在同一个地方,求一简单的写法
如:将上诉过程全部封装起来,用一个函数 func1 实现初始化和计时,同时函数参数里面给另外一个函数 func2 的指针 ,func2 函数用来执行定时器时间到之后的动作,并且func2需要传参进去
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
12条回答
whatcanitbe
1楼-- · 2019-12-19 19:09
多个定时器可以用结构体数组啊
istars2005
2楼-- · 2019-12-19 23:11
无法添加附件了?
下面是C文件   MCU是STM32F103x
  1. #include "SysTick.h"
  2. #include <stdlib.h>

  3. #include "SEGGER_RTT.h"

  4. //===================================================================
  5. #ifndef true
  6.   #define true 1
  7.   #define false 0
  8. #endif
  9. //===================================================================
  10. //------------超时标记变量定义区---------------
  11. #define TM_OUT_CNT   32                         /* 最多超时变量个数,建议不要超过32个*/
  12. vu32 *gTimOut[TM_OUT_CNT] = {0};                // 超时计数变量指针数组
  13.                                                 // 可以配置多个超时变量
  14.                                                 // 超时变量不可复用,不然会出问题
  15.                                                 // 但是只是变量指针,具体的变量值需要调用TimeOutSet来配置
  16. static u8  tm_Out_Cnt = 0;                      // 实际超时变量个数

  17. //------------定时回调变量定义区----------------
  18. #define TM_CB_CNT    64
  19. struct  TimCBDef {
  20.         u32 tim;
  21.         void (*hook)(void);
  22.         struct TimCBDef *next;
  23. };
  24. struct  TimCBDef *_gTimCBPtr = 0;
  25. u16     _gTimCBSize = 0;

  26. volatile union  SysTickTimerFlag  SysTick_T;            // 系统时间标志位
  27. volatile u32    SysTick_MsDelay_T;                              // SysTick毫秒延时计数
  28. static   u32    SysTick_Timer = 0;


  29. /**
  30.   * 函数功能: 配置定时回调
  31.   * 输入参数: tset=定时时间(毫秒)  hook=回调函数
  32.   * 输出参数: 0=配置成功, -1配置失败
  33.   * 功能说明:
  34.   */
  35. s8 TimeCallBackSet(u32 tmset, void (*hook)(void))
  36. {
  37.     if(_gTimCBSize >= TM_CB_CNT)
  38.         return -1;
  39.     struct TimCBDef *tsnewDef = (struct TimCBDef*)malloc(sizeof(struct TimCBDef));     // 新申请一块内存
  40.     if(tsnewDef == NULL)
  41.         return -1;
  42.     tsnewDef->tim = tmset + SysTick_Timer;
  43.     tsnewDef->hook = hook;
  44.     tsnewDef->next = NULL;
  45. //Jprintf(0," =%x %d",hook,_gTimCBSize);
  46.     _gTimCBSize += 1;
  47.     if(_gTimCBSize == 1) {
  48.         _gTimCBPtr = tsnewDef;
  49.     } else {
  50.                 if(tsnewDef->tim < _gTimCBPtr->tim) {
  51.                         tsnewDef->next = _gTimCBPtr;
  52.                         _gTimCBPtr = tsnewDef;
  53.                         return 0;
  54.                 }
  55.         struct TimCBDef *tstmpDef = _gTimCBPtr;     // 当前节点指针
  56.         struct TimCBDef *tslstDef = _gTimCBPtr;     // 上一节点
  57.         while(tstmpDef->next != NULL) {
  58.                         if(tsnewDef->tim < tstmpDef->tim) {
  59.                                 tsnewDef->next = tstmpDef;
  60.                                 tslstDef->next = tsnewDef;
  61.                                 break;
  62.                         }
  63.                         tslstDef = tstmpDef;
  64.                         tstmpDef = tstmpDef->next;
  65.                 }
  66.                 if(tsnewDef->next == NULL) {
  67.                         if(tsnewDef->tim < tstmpDef->tim) {
  68.                                 tsnewDef->next = tstmpDef;
  69.                                 tslstDef->next = tsnewDef;
  70.                         } else {
  71.                                 tstmpDef->next = tsnewDef;
  72.                         }
  73.                 }
  74.     }
  75.     return 0;
  76. }

  77. /**
  78.   * 函数功能: 查看回调链表是否有任务就绪
  79.   */
  80. static void CheckTimCallback(void)
  81. {
  82.     if(_gTimCBSize == 0)
  83.         return;
  84.     if(_gTimCBPtr->tim <= SysTick_Timer) {
  85.         struct TimCBDef *tstmpDef = _gTimCBPtr;
  86.         _gTimCBPtr = _gTimCBPtr->next;
  87.         _gTimCBSize -= 1;
  88.         if(tstmpDef->hook != NULL) {
  89.             void (*tshook)(void);
  90. //Jprintf(0," >%x",tstmpDef->hook);
  91.             tshook = tstmpDef->hook;
  92.             free(tstmpDef);
  93.             tshook();
  94. //Jputs(0,">");
  95.         }
  96.     }
  97. }

  98. /**
  99. * 函数功能: 配置超时指针
  100. * 输入参数: *ptout 需要传入的超时变量指针
  101. * 输出参数: 配置结果 0:成功  -1:索引溢出  1:超时指针重复(不影响正常结果)
  102. * 功能说明: 修改原来实现方式的bug,不再使用idx变量
  103.              当超过最大允许的超时变量个数时返回-1
  104. */
  105. s8 TimeOutSet(vu32 *ptout)
  106. {
  107.     if(tm_Out_Cnt >= TM_OUT_CNT)
  108.         return -1;
  109.     for(int i=0;i<tm_Out_Cnt;i++) {
  110.         if(ptout == gTimOut[i])
  111.             return 1;
  112.     }
  113.     gTimOut[tm_Out_Cnt] = ptout;
  114.     tm_Out_Cnt++;
  115.     return 0;
  116. }

  117. /**
  118.   *函数功能:SysTick初始化
  119.   *函数名称:SysTick_Init
  120.   *输入参数:无
  121.   *输出参数:无
  122.   */
  123. void SysTick_Init(void)
  124. {
  125.     if(SysTick_Config(SystemCoreClock / 1000)) {        //1ms
  126.         while(1);
  127.     }
  128.     SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);    //选择时钟源
  129.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  130.     NVIC_SetPriority(SysTick_IRQn,4);                   //中断
  131. }

  132. /**
  133.   *SysTick中断服务函数
  134.   *输入参数无
  135.   *输出参数无
  136.   */
  137. void SysTick_Handler_Service(void)
  138. {
  139.    
  140.     SysTick_Timer++;                                                                                    // 每个毫秒进行一次累加
  141.         SysTick_MsDelay_T ? SysTick_MsDelay_T-- : 0;                                // 全局毫秒计数如果不等于0则减一
  142.                                                                                    
  143.     int i=0;
  144.     while(i<tm_Out_Cnt) {                                                       // 扫描超时变量,并且把不为0的变量进行自减一
  145.         *gTimOut[i] ? (*gTimOut[i])-- : 0;
  146.         i++;
  147.     }
  148.     CheckTimCallback();     // 查看定时回调任务就绪情况
  149.    
  150.         /* if嵌套原则: 一定是有约数关系才能嵌套,而且选择最大的约数嵌套,
  151.                                    如500可以和20嵌套也可以和50嵌套,则选50,
  152.                                    目的为减少判断次数
  153.         */
  154.     if(SysTick_Timer%10!=0)   // 10ms判断一次,用于减少判断次数
  155.         return;
  156.     if(SysTick_Timer%20==0)                     SysTick_T.bits._20ms   = true;  // 20ms   标志置位
  157.     if(SysTick_Timer%50==0) {                   SysTick_T.bits._50ms   = true;  // 50ms   标志置位
  158.       if(SysTick_Timer%100==0) {                SysTick_T.bits._100ms  = true;  // 250ms  标志置位
  159.         if(SysTick_Timer%500==0) {              SysTick_T.bits._500ms  = true;        // 500ms  标志置位
  160.            if(SysTick_Timer%1000 == 0) {        SysTick_T.bits._1000ms = true;         // 1000ms 标志置位
  161.              if(SysTick_Timer%2000 == 0) {      SysTick_T.bits._2000ms = true;         // 2000ms 标志置位
  162.                if(SysTick_Timer%60000 == 0) {   SysTick_T.bits._60s    = true;         // 60秒   标志置位
  163.                }
  164.              }
  165.            }
  166.         }
  167.       }
  168.     }
  169. }
复制代码
istars2005
3楼-- · 2019-12-20 04:00
下面是.h文件
  1. #ifndef __SYSTICK_H
  2. #define __SYSTICK_H

  3. #include "stm32f10x.h"

  4. //--------------------定义区----------------------
  5. union   SysTickTimerFlag        //系统时间标志位
  6. {
  7.     uint16_t Flag;
  8.     struct {
  9. //        uint8_t _10ms   :1;         // 10ms   标志
  10.         uint8_t _20ms   :1;         // 20ms   标志
  11.         uint8_t _50ms   :1;         // 50ms   标志
  12.         uint8_t _100ms  :1;         // 100ms  标志
  13. //        uint8_t _250ms  :1;         // 250ms  标志
  14.         uint8_t _500ms  :1;         // 500ms  标志
  15.         uint8_t _1000ms :1;         // 1000ms 标志
  16.         uint8_t _2000ms :1;         // 2000ms 标志
  17. //        uint8_t _30s    :1;         // 30秒   标志
  18.         uint8_t _60s    :1;         // 60秒   标志
  19.     }bits;
  20. };

  21. //===================对外变量声明===========================
  22. extern volatile union SysTickTimerFlag  SysTick_T;      // 系统时间标志位,(用于查看各个定时时间段的标志位,不允许对变量赋值)

  23. //===================对外函数接口===========================
  24. void SysTick_Init(void);                                // SysTick初始化
  25. s8   TimeCallBackSet(u32 tmset, void (*hook)(void));    // 定时回调,tmset=回调时间(毫秒),  hook= 定时时间到的回调函数
  26. s8   TimeOutSet(vu32 *ptout);                           // 超时变量配置(在用到超时变量时,需要提前调用此函数进行初始化)

  27. #endif
复制代码
istars2005
4楼-- · 2019-12-20 09:56
 精彩回答 2  元偷偷看……
Junsea
5楼-- · 2019-12-20 15:01
istars2005 发表于 2018-4-12 15:12
你可以用TimeCallBackSet 设置好时间和回调函数
定时时间到了之后会自动调用,不过现在只支持 无参数无返回 ...

谢谢,好好研究研究
avr_sz
6楼-- · 2019-12-20 15:17
3楼厉害,系统级的写法,我还没看懂

一周热门 更多>