OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2496|回复: 0

软件定时器驱动,不再担心定时器不够用了

[复制链接]

2

主题

3

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-6-28
在线时间
7 小时
发表于 2019-8-17 17:35:09 | 显示全部楼层 |阅读模式

       创建软件定时器,纯C语言,只依赖一个硬件定时器,现在每个单片机至少都有一个定时器吧,所以支持多平台单片机移植。最多可以创建65535个软件定时器,定时精度可以达到硬件定时器的水平,再也不用担心定时器不够用了!
​      具体实现方法主要通过一个单链表。
头文件:

  1. #ifndef __BSP_SOFTTIMER_H
  2. #define __BSP_SOFTTIMER_H

  3. #ifndef uint32_t
  4. #define  uint32_t unsigned long
  5. #endif
  6. #ifndef uint16_t
  7. #define uint16_t unsigned int
  8. #endif
  9. #ifndef uint8_t
  10. #define uint8_t unsigned char
  11. #endif

  12. /* 开关全局中断的宏 */
  13. #define ENABLE_INT()        __set_PRIMASK(0)        /* 使能全局中断 */
  14. #define DISABLE_INT()        __set_PRIMASK(1)        /* 禁止全局中断 */

  15. #define SET_BIT(dat,bits)           (dat |= (1<<bits))
  16. #define IS_BIT(dat,bits)                (dat & (1<<bits))
  17. #define CLEAR_BIT(dat,bits)                (dat &= ~(1<<bits))



  18. typedef enum _en_typeTimer{
  19.         HARD_TIMER=0,
  20.         SOFT_TIMER,
  21. }en_typeTimer;
  22. typedef enum _en_timerRunStatus{
  23.         RUNNING = 0,
  24.         STOP,
  25. }en_timerRunStatus;

  26. typedef void (*timerFunction) (void *arg);

  27. typedef struct st_timer_ts
  28. {
  29.         struct st_timer_ts *nextNode;        /*下一定时器结点的地址*/
  30.         uint32_t u32DurationTicks;                 /*定时的时间,一个u32DurationTicks就是周期调用bsp_timerLoop_ToIrq()函数的中断时长*/
  31.         uint32_t u32DelayTicks;                    /*当前定时递减计数值*/
  32.         timerFunction timerFunc;                /*回调函数地址*/
  33.         void * arg;                                         /*传递给回调函数的参数*/
  34.         en_typeTimer en_typeTime;                /*定时器类型,HARD_TIMER=硬定时器,在定时器中断中执行回调函数,时间精度高。
  35.                                                                                                 SOFT_TIMER=软定时器,在main while()大循环中执行回调函数。
  36.                                                                         */
  37.         en_timerRunStatus en_runSta;        /*定时器的运行状态*/
  38.         uint8_t         u8TimerCtr;                        /*bit0:1=定时时间到,0=时间未到
  39.                                                                           bit1:1=循环定时器,0=一次性定时器
  40.                                                                         */
  41. }st_timer_t;




  42. void bsp_createTimer(st_timer_t *st_timer, en_typeTimer en_typeTime, timerFunction func, void *arg);
  43. void bsp_timerLoop_ToIrq (st_timer_t *headTimer);
  44. void bsp_softRunTimer(st_timer_t *headTimer);
  45. void bsp_startTime(st_timer_t *st_timer,  uint32_t u32DurationTicks);
  46. void bsp_startAutoTime(st_timer_t *st_timer,  uint32_t u32DurationTicks);
  47. void bsp_stopTime(st_timer_t *st_timer);
  48. #endif
复制代码




C文件:
  1. /*
  2. *********************************************************************************************************
  3. *
  4. *   模块名称 : 软件定时器
  5. *   文件名称 : bsp_softTimer.c
  6. *   版    本 : V2.0
  7. *   说    明 : 本文件可以创建65535个软件定时器。定时器的回调函数可以在定时器中断中执行,这种方式定时时间精度高。
  8. *              也可以在main主函数大循环中调用,可以执行一些对时间要求不高的功能。每个定时器的回调函数执行方式可
  9. *              以二选一。
  10. *               
  11. *   修改记录 :
  12. *       版本号         日期        作者     说明
  13. *       V1.0        2017-09-07     徐
  14. *       V2.0        2019-08-17     徐      增加创建一次性和循环定时器函数,增加停止函数。
  15. *********************************************************************************************************
  16. */

  17. #include "bsp.h"

  18. static uint16_t   s_g_u16TimerCnt = 0;//创建的定时器数量


  19. /*
  20. *********************************************************************************************************
  21. *   函 数 名: bsp_createTimer
  22. *   功能说明: 创建一个软件定时器,此时软件定时器是停止状态。
  23. *   形    参: *st_timer:定时器结构体地址。    en_typeTime:回调函数的执行方式
  24. *              func     :回调函数地址。        *arg      :回调函数的形参。
  25. *   返 回 值: 无
  26. *********************************************************************************************************
  27. */
  28. void bsp_createTimer(st_timer_t *st_timer, en_typeTimer en_typeTime, timerFunction func, void *arg)
  29. {
  30.         static st_timer_t *st_pPreTimer = (st_timer_t*)0;
  31.     if(s_g_u16TimerCnt != 0)               /*第一次进入,nextNode不赋值*/
  32.     {
  33.         st_pPreTimer->nextNode = st_timer;    //上次定时器的nextNode赋值
  34.     }
  35.     st_pPreTimer = st_timer;                   //记录本次定时器的地址
  36.         s_g_u16TimerCnt++;
  37.     st_timer->u32DurationTicks = 0;
  38.     st_timer->u32DelayTicks = 0;
  39.     st_timer->timerFunc = func;
  40.     st_timer->arg = arg;
  41.     st_timer->en_typeTime = en_typeTime;
  42.     st_timer->en_runSta = STOP;
  43.     st_timer->u8TimerCtr = 0;
  44. }
  45. /*
  46. *********************************************************************************************************
  47. *   函 数 名: bsp_startTime
  48. *   功能说明: 启动一个一次性软件定时器。
  49. *   形    参: *st_timer:定时器结构体地址。    u32DurationTicks: 定时时长,单位多少个中断周期。            
  50. *   返 回 值: 无
  51. *********************************************************************************************************
  52. */
  53. void bsp_startTime(st_timer_t *st_timer,  uint32_t u32DurationTicks)
  54. {
  55.     if(st_timer == 0)
  56.         return ;
  57.     DISABLE_INT();                                  /*关总中断*/
  58.     st_timer->en_runSta = RUNNING;
  59.     st_timer->u32DurationTicks = u32DurationTicks;
  60.     st_timer->u32DelayTicks = u32DurationTicks;
  61.     CLEAR_BIT(st_timer->u8TimerCtr,1);     
  62.     ENABLE_INT();
  63. }

  64. /*
  65. *********************************************************************************************************
  66. *   函 数 名: bsp_startAutoTime
  67. *   功能说明: 启动一个循环软件定时器。
  68. *   形    参: *st_timer:定时器结构体地址。    u32DurationTicks: 定时时长,单位多少个中断周期。            
  69. *   返 回 值: 无
  70. *********************************************************************************************************
  71. */
  72. void bsp_startAutoTime(st_timer_t *st_timer,  uint32_t u32DurationTicks)
  73. {
  74.     if(st_timer == 0)
  75.         return ;   
  76.     DISABLE_INT();                                  /*关总中断*/
  77.     st_timer->en_runSta = RUNNING;
  78.     st_timer->u32DurationTicks = u32DurationTicks;
  79.     st_timer->u32DelayTicks=u32DurationTicks;
  80.     SET_BIT(st_timer->u8TimerCtr,1);
  81.     ENABLE_INT();
  82. }
  83. /*
  84. *********************************************************************************************************
  85. *   函 数 名: bsp_stopTime
  86. *   功能说明: 停止一个软件定时器。
  87. *   形    参: *st_timer:定时器结构体地址。            
  88. *   返 回 值: 无
  89. *********************************************************************************************************
  90. */
  91. void bsp_stopTime(st_timer_t *st_timer)
  92. {
  93.     st_timer->en_runSta = STOP;
  94. }

  95. /*
  96. *********************************************************************************************************
  97. *   函 数 名: bsp_timerLoop_ToIrq
  98. *   功能说明: 软件定时器逻辑具体实现的函数,必须放在硬件定时器中断中循环调用。
  99. *   形    参: *headTimer:创建的第一个定时器结构体地址。            
  100. *   返 回 值: 无
  101. *********************************************************************************************************
  102. */
  103. void bsp_timerLoop_ToIrq(st_timer_t *headTimer)
  104. {
  105.    
  106.           uint16_t j=0;
  107.         st_timer_t *timer=headTimer;
  108.         for(; j<s_g_u16TimerCnt; j++)
  109.     {
  110.         if(timer->en_runSta == RUNNING)
  111.         {
  112.             if ((timer->u32DelayTicks == 0) || (--timer->u32DelayTicks == 0))
  113.             {
  114.                 if(timer->en_typeTime == HARD_TIMER)//硬件定时器,执行回调函数
  115.                 {
  116.                     timer->timerFunc(timer->arg);
  117.                 }
  118.                 else
  119.                 {
  120.                     SET_BIT(timer->u8TimerCtr,0);//软件定时器,在while中执行
  121.                 }
  122.                 if(IS_BIT(timer->u8TimerCtr,1)) /*循环定时器重装载计数值*/
  123.                 {
  124.                     timer->u32DelayTicks = timer->u32DurationTicks;
  125.                 }
  126.                 else    /*一次性定时器*/
  127.                 {
  128.                     timer->en_runSta = STOP;
  129.                 }
  130.             }            
  131.         }
  132.                 timer=timer->nextNode;
  133.     }
  134.        
  135. }


  136. /*
  137. *********************************************************************************************************
  138. *   函 数 名: bsp_softRunTimer
  139. *   功能说明: 遍历软定时器,查询定时时间是否到了,在main.c while{}中执行
  140. *   形    参: *headTimer:创建的第一个定时器结构体地址。            
  141. *   返 回 值: 无
  142. *********************************************************************************************************
  143. */
  144. void bsp_softRunTimer(st_timer_t *headTimer)
  145. {
  146.         uint16_t j=0;
  147.         st_timer_t *timer=headTimer;
  148.         for(; j<s_g_u16TimerCnt; j++)
  149.     {
  150.              if(IS_BIT(timer->u8TimerCtr,0))
  151.             {
  152.             CLEAR_BIT(timer->u8TimerCtr,0);
  153.                         timer->timerFunc(timer->arg);
  154.             }
  155.                 timer=timer->nextNode;
  156.     }

  157. }


复制代码


最后来个简单的例子:




  1. #include "bsp.h"

  2. st_timer_t timer1;
  3. st_timer_t timer2;


  4. void timer1Task(void *arg)
  5. {
  6.     printf("time1 run\r\n");
  7.    
  8. }
  9. void timer2Task(void *arg)
  10. {
  11.     printf("time1 run\r\n");

  12. }

  13. int main(void)
  14. {

  15.     SysTick_Config(SystemCoreClock / 1000); /*1ms滴答中断定时器*/

  16.     bsp_createTimer(&timer1,SOFT_TIMER,timer1Task,(void*)0);
  17.     bsp_createTimer(&timer2,HARD_TIMER,timer2Task,(void*)0);


  18.     bsp_startTime(&timer1,100);     /*100个定时器中断执行一次*/
  19.     bsp_startAutoTime(&timer2,500);

  20.     while(1)
  21.     {
  22.         bsp_softRunTimer(&timer1);
  23.     }

  24. }


  25. /*
  26. *********************************************************************************************************
  27. *   函 数 名: SysTick_Handler
  28. *   功能说明: 系统嘀嗒定时器中断服务程序。启动文件中引用了该函数。建议中断时间1ms。
  29. *   形    参:  无
  30. *   返 回 值: 无
  31. *********************************************************************************************************
  32. */
  33. void SysTick_Handler(void)
  34. {
  35.     bsp_timerLoop_ToIrq(&timer1);  
  36. }

复制代码



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-11 05:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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