首页 > 学院 > 开发设计 > 正文

软件定时器(一)

2019-11-11 01:42:26
字体:
来源:转载
供稿:网友

之前偶尔了解到软件定时器,也在网上找了许多网友写的各种版本,知道读到嵌入式TCP/ip协议栈中的软件定时器的写法时,叹为观止,故将其修改移植到裸机stm32上使用,并向大家做一分享。

首先得感谢那些兢兢业业从事着自己的工作,并毫不吝啬的向别人公布自己源代码的前辈们,正因为他们慷慨无私,我们才能阅读到各种精巧的代码,并从中汲取养分,从而培养了许多热爱技术,真诚无私的人。

/**@brief:1、该文件参考LWIP协议中的times.c编写 * 2、该超时定时器按链表的形式进行组织,按时间长短进行排序,时间最短的永远排在最前面 * 3、移植时应该注意的几点: * a.周期性的调用函数。b.需要外部定时器实现时基。c.注意动态内存分配mallco的使用。 *@author: LT *@date: 2016/12/3 */#ifndef __SOFT_TIME_H#define __SOFT_TIME_H#include "typedef.h"#include <string.h>#include <stdlib.h>/* 定时器超时处理函数指针 */typedef void (* soft_timeout_handler)(void *arg);/* 超时定时器 */struct soft_timeo { struct soft_timeo *next; u32 time; soft_timeout_handler h; void *arg;};#define MEMP_soft_TIMEOUT (sizeof(struct soft_timeo))void soft_timeouts_init(u32 msecs, soft_timeout_handler handler, void *arg);void soft_timeout(u32 msecs, soft_timeout_handler handler, void *arg);void soft_untimeout(soft_timeout_handler handler, void *arg);void soft_check_timeouts(void);void soft_restart_timeouts(void);void soft_run_timeout(soft_timeout_handler handler, void *arg);u32 time_to_sec(char *RTC_set);u32 RTC_set(char* RTC_set);#endif#include "soft_time.h"#include "bsp.h"#include "malloc.h"extern volatile u32 g_soft_timer_count;static u32 timeouts_last_time; static struct soft_timeo *next_timeout;/*从字符串的左边截取n个字符*/char * str_left(char *dst,const char *src, int n){ const char *p = src; char *q = dst; int len = strlen(src); if(n>len) n = len; while(n--) *(q++) = *(p++); *(q++)='/0'; /*有必要吗?很有必要*/ return dst;}u32 soft_time_now(void){ return RTC_GetCounter();}/** @brief 计算预定时间距现在的时间(单位:s) * @param 预定时间转成的字符串(例如:2016 12 03 18 30 00 错误) * ( 2016 12 3 18 30 0 正确) * @retval * @tips 注意strtol函数的使用 */u32 time_to_sec(char *RTC_set){ u32 set_sec;// u32 now_sec; u8 n; char *pEnd; n = accumulationdayfrom1970((int*)&set_sec, RTC_set); set_sec = set_sec * 3600 * 24 + (int)strtol(RTC_set + n,&pEnd,0) * 3600 ; set_sec = set_sec + (int)strtol(pEnd, &pEnd, 0) * 60; set_sec = set_sec + (int)strtol(pEnd, NULL, 0);/* RTC_Get_str(RTC_now); n = accumulationdayfrom1970((int*)&now_sec, RTC_now); now_sec = now_sec * 3600 * 24 + (int)strtol(RTC_now + n,&pEnd_,0) * 3600 ; now_sec = now_sec + (int)strtol(pEnd_, &pEnd_, 0) * 60; now_sec = now_sec + (int)strtol(pEnd_, NULL, 0); PRintf("%d /n",set_sec - now_sec);*/ return (set_sec - RTC_GetCounter());}/** @brief 计算预定时间距1970/1/1的时间(单位:s) * @param 预定时间转成的字符串(例如:2016 12 03 18 30 00 错误) * ( 2016 12 3 18 30 0 正确) * @retval 时间 单位 S * @tips 注意strtol函数的使用 */u32 RTC_set(char* RTC_set){ u32 set_sec; char* pEnd; u8 n; n = accumulationdayfrom1970((int*)&set_sec, RTC_set); set_sec = set_sec * 3600 * 24 + (int)strtol(RTC_set + n,&pEnd,0) * 3600 ; set_sec = set_sec + (int)strtol(pEnd, &pEnd, 0) * 60; set_sec = set_sec + (int)strtol(pEnd, NULL, 0); return set_sec;}/** Initialize this module */void soft_timeouts_init(u32 msecs, soft_timeout_handler handler, void *arg){ soft_timeout(msecs, handler, arg); timeouts_last_time = soft_time_now();}/* * Must be called periodically from your main loop. * 检查是否有某个定时器的时间到了,以作出进一步的处理 */voidsoft_check_timeouts(void){ if (next_timeout) { struct soft_timeo *tmptimeout; u32 diff; soft_timeout_handler handler; void *arg; u8 had_one; u32 now; now = soft_time_now(); /* this cares for wraparounds */ diff = now - timeouts_last_time; do { had_one = 0; tmptimeout = next_timeout; if (tmptimeout && (tmptimeout->time <= diff)) { /* timeout has expired */ had_one = 1; timeouts_last_time = now; diff -= tmptimeout->time; next_timeout = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; myfree(SRAMIN, tmptimeout); if (handler != NULL) { handler(arg); } } /* repeat until all expired timers have been called */ }while(had_one); }} /* * 功能:添加超时定时器 * */voidsoft_timeout(u32 msecs, soft_timeout_handler handler, void *arg){ struct soft_timeo *timeout, *t; timeout = (struct soft_timeo *)mymalloc(SRAMIN, MEMP_soft_TIMEOUT); if (timeout == NULL) { printf("soft_timeout: timeout != NULL, pool MEMP_soft_TIMEOUT is empty"); return; } timeout->next = NULL; timeout->h = handler; timeout->arg = arg; timeout->time = msecs; if (next_timeout == NULL) { next_timeout = timeout; return; }/* 实现对定时器链表的插入,排列顺序按照定时时间的长短确定 */ if (next_timeout->time > msecs) { next_timeout->time -= msecs; timeout->next = next_timeout; next_timeout = timeout; } else { for(t = next_timeout; t != NULL; t = t->next) { timeout->time -= t->time; if (t->next == NULL || t->next->time > timeout->time) { if (t->next != NULL) { t->next->time -= timeout->time; } timeout->next = t->next; t->next = timeout; break; } } }}/* * 功能:删除与所指定的回调函数及参数相同的第一个定时器 */voidsoft_untimeout(soft_timeout_handler handler, void *arg){ struct soft_timeo *prev_t, *t; if (next_timeout == NULL) { return; } for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { if ((t->h == handler) && (t->arg == arg)) { /* We have a match */ /* Unlink from previous in list */ if (prev_t == NULL) { next_timeout = t->next; } else { prev_t->next = t->next; } /* If not the last one, add time of this one back to next */ if (t->next != NULL) { t->next->time += t->time; } myfree(MEMP_soft_TIMEOUT, t); return; } } return;}/* * 功能:如果定时器回调函数在很久没有被调用,可以使用该函数更新 * 计数值,使之前的函数被调用。 */voidsoft_restart_timeouts(void){ timeouts_last_time = soft_time_now();}/* * 功能:直接指定相应的定时器执行 */voidsoft_run_timeout(soft_timeout_handler handler, void *arg){ soft_untimeout(handler,arg); soft_timeout(0, handler, arg);}
上一篇:poj1018

下一篇:LeetCode: Combination Sum II

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表