1.什么是软件定时器
软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些
2.声明文件

/** @Descripttion: * @version: V0.1* @Author: Kris* @Date: 2020* @LastEditors: Kris* @LastEditTime: 2020*/#include "gd32e23x.h"
#include "main.h"#define TIMER_NUM_MAX 10//创建的定时器id号
typedef enum{TMR_STRING_PRINT = 0,TMR_TWINKLING,
}tim_mode_t;
typedef void (*callback_t)(void *argv, uint16_t argc);/***  @brief:定时器运行状态 */
typedef enum
{SOFT_TIMER_STOP = 0,  //停止SOFT_TIMER_RUNNING,      //运行SOFT_TIMER_TIMEOUT       //超时
}tmrState_t;/***    @brief:定时器运行模式*/
typedef enum
{MODE_ONE_SHOT = 0,         //单次模式MODE_PERIODIC,            //周期模式
}tmrMode_t;/*** @brief:软件定时器的结构*/
typedef struct
{char name[12];          //名字最大12个字节tmrState_t state;        //状态tmrMode_t mode;          //模式uint32_t match;          //到期时间uint32_t period;         //定时周期callback_t cb;           //回调函数指针void *argv;              //参数指针uint16_t argc;           //参数个数
}softTimer_t;//软件定时器所有函数入口
struct soft_timer_t
{const uint8_t  * const pre_num_of_sft;uint8_t (*creat_start)(char *, uint8_t , tmrMode_t , uint32_t , callback_t , void *, uint16_t);void (*stop)(char* );void (*reply)(char* );tmrState_t (* get_status)(char* );void (*updata)(void );uint32_t (*get_time)(void);
};extern struct soft_timer_t g_soft_timer;
extern uint8_t g_softTimer_creat_start(char *name, uint8_t id,tmrMode_t mode, uint32_t time, callback_t cb, void *argv, uint16_t argc);#if 0
extern void g_softTimer_Update(void);
extern void g_softTimer_reply(char *name);
extern void g_softTimer_Stop(char *name);
extern tmrState_t g_softTimer_GetState(char *name);
#endif

PS:获取的时间在函数systick中计数,通过***g_get_systickcnt()***获取当前的计时

static volatile uint16_t systick_Cnt;
static volatile uint32_t systick_cnt = 0;
void SysTick_Handler(void)
{//1m-ssystick中断delay_decrement();systick_Cnt++;if(systick_Cnt >= 50)//50ms{systick_Cnt = 0;systick_cnt++;}
}//获取当前softtime全局值
uint32_t g_get_systickcnt(void)
{return systick_cnt;//g_tim13_cnt;
}

3.源文件
由于有单次定时中断的软件定时器,如果单次检测结束会一直占用堆栈内存,因此就此添加了单次软件定时结束后自动删除当前的单次软件定时器,增加定时器软件定时的效率.

/** @Descripttion: * @version: V0.1* @Author: Kris* @Date: 2020* @LastEditors: Kris* @LastEditTime: 2020*/
static softTimer_t softTimer[TIMER_NUM_MAX];//软件定时器数组
static uint8_t present_tim_num = 0; //当前软件定时器个数/*** @name: softTimer_creat_start* @brief: 创建并启动一个定时器* @param {name:定时器的名字标识符,可以通过name定位到哪一个软件定时器 *          id:当前没有用*           mode:设备模式,单次还是周期*           time:软件定时器中断时长 基准为50ms 最小软件定时器50 delay*             cb:回调函数处理*          argv:回调函数的参数 没有就是NULL*          argc:回调函数的参数     没有就是null* @return: 当前软件定时器数量*/
uint8_t g_softTimer_creat_start(            char *name, uint8_t id,tmrMode_t mode, uint32_t time, callback_t cb, void *argv, uint16_t argc)
{//assert_param(id < TIMER_NUM_MAX);//assert_param(mode == MODE_ONE_SHOT || mode == MODE_PERIODIC);if((present_tim_num > TIMER_NUM_MAX) || (strlen(name) > 12) || (time < 50)){printf("Softtime creat error!\r\n");return present_tim_num;}for(size_t i = 0;i < present_tim_num;i++){if(0 == strcmp(softTimer[id].name,name)){printf("Already hava same name time,please change name!\r\n");return present_tim_num;}}present_tim_num ++;id = present_tim_num -1;memcpy(&softTimer[id].name,name,strlen(name));softTimer[id].match = g_get_systickcnt() + time/50;softTimer[id].period = time/50;softTimer[id].state = SOFT_TIMER_RUNNING;softTimer[id].mode = mode;softTimer[id].cb = cb;softTimer[id].argv = argv;softTimer[id].argc = argc;return present_tim_num;
}/*** @name: softTimer_stop* @brief: //停止定时器计时* @param {name:具体的那个一软件定时器} * @return: NULL*/
static void softTimer_stop(char *name)
{//assert_param(id < TIMER_NUM_MAX);for(size_t i=0;i<present_tim_num;i++){if(0 == strcmp(softTimer[i].name,name)){softTimer[i].state = SOFT_TIMER_STOP;break;}else{//printf("name no match or the time already delete in list\r\n");}}
}/*** @name: softTimer_reply* @brief: //恢复定时器计时 只能回复周期定时器* @param {name:具体的那个一软件定时器} * @return: NULL*/
static void softTimer_reply(char *name)
{//assert_param(id < TIMER_NUM_MAX);for(size_t i=0;i<present_tim_num;i++){if(0 == strcmp(softTimer[i].name,name)){softTimer[i].state = SOFT_TIMER_RUNNING;softTimer[i].match = g_get_systickcnt() + softTimer[i].period;break;}}
}/*** @name: softTimer_getstate* @brief: 获取定时器状态* @param {name:具体的那个一软件定时器} * @return: NULL*/
static tmrState_t softTimer_getstate(char *name)
{uint8_t i;for (i=0;i<present_tim_num;i++){if(0 == strcmp(softTimer[i].name,name)){printf("123123\r\n");break;}} return softTimer[i].state;
}//更新定时器值
static void softTimer_update(void)
{uint8_t i;uint8_t tempbuf[10] = {0,};//buf是存下标,表明哪一个定时器已经定时结束,uint8_t already_subscript = 0;//for(i=0; i<present_tim_num; i++) {switch (softTimer[i].state) {case SOFT_TIMER_STOP:if(softTimer[i].mode == MODE_ONE_SHOT){//单侧定时中断结束uint8_t tempbuf_value;already_subscript++;tempbuf[already_subscript] = i;//定时器下标比较前后if(tempbuf[already_subscript] < tempbuf[already_subscript-1]){tempbuf_value = tempbuf[already_subscript - 1];tempbuf[already_subscript - 1] = tempbuf[already_subscript];tempbuf[already_subscript] = tempbuf_value;}}break;case SOFT_TIMER_RUNNING:if(softTimer[i].match <= g_get_systickcnt()) {softTimer[i].state = SOFT_TIMER_TIMEOUT;softTimer[i].cb(softTimer[i].argv, softTimer[i].argc);       //执行回调函数}break;case SOFT_TIMER_TIMEOUT:if(softTimer[i].mode == MODE_ONE_SHOT){softTimer[i].state = SOFT_TIMER_STOP;} else {softTimer[i].match = g_get_systickcnt() + softTimer[i].period;softTimer[i].state = SOFT_TIMER_RUNNING;//periodcnt++;}break;default:printf("timer[%d] state error!\r\n", i);break;}}if(already_subscript == 0)return;if( already_subscript ==  present_tim_num){memset(&softTimer[0].name,0,12);present_tim_num = 0;return;}for(i = 0;i<already_subscript;i++)//循环次数{for(size_t start = tempbuf[already_subscript - i];start <= (present_tim_num - (tempbuf[already_subscript]+1));start++){//起始位置为tempbuf中最后面的值,循环次数为当前软件定时器总数量-当前位置的下标(下标从0开始)memcpy(&softTimer[start],&softTimer[start+1],sizeof(softTimer_t));}}memset(&softTimer[present_tim_num-1].name,0,12);present_tim_num -= already_subscript;}//软件定时器入口
struct soft_timer_t g_soft_timer =
{&present_tim_num,g_softTimer_creat_start,softTimer_stop,softTimer_reply,softTimer_getstate,softTimer_update,g_get_systickcnt,
};

之后 可以在main函数里面循环调用updata函数,单次函数单次中断结束就不再运行,周期软件定时器进行周期定时中断


void stringPrint(void *argv, uint16_t argc)
{printf("111TEST\r\n");
}
void stringPrint111(void *argv, uint16_t argc)
{printf("222TEST\r\n");
}
void test_tt1(void *argv, uint16_t argc)
{printf("TTT111\r\n");
}
void test_tt2(void *argv, uint16_t argc)
{printf("TTT222\r\n");
}void LED0_Twinkling(void *argv, uint16_t argc)
{HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_2);printf("TEST.\r\n");
}
int main(void)
{/**初始化函数*///创建3个软件定时器g_softTimer_creat_start("POWERON", 0, MODE_ONE_SHOT, 1000, LED0_Twinkling, NULL, NULL);g_softTimer_creat_start("ADCCHECK", 0, MODE_PERIODIC, 5000, stringPrint111, NULL, NULL);g_softTimer_creat_start("test1", 0, MODE_ONE_SHOT, 2000, test_tt1, NULL, NULL);g_softTimer_creat_start("221", 0, MODE_PERIODIC, 2500, test_tt2, NULL, NULL);for(;;){g_soft_timer.updata(); }
}

基于数组(非链表)实现软件定时器---可以移植到未使用系统的单片机,通用型相关推荐

  1. 基于linux的地震数据处理软件的设计与实现,地震监测系统AETA的数据处理设计与实现.PDF...

    地震监测系统AETA的数据处理设计与实现.PDF 第28卷 第1期 计 算机 技 术 与发 展 Vol.28 No.1 2018年1月 COMPUTERTECHNOLOGY AND DEVELOPME ...

  2. 基于MessageSolution 邮件归档系统EEA的通用型信息泄露漏洞挖洞

    前几天无意间看到这个通用型漏洞,编号是CNVD-2021-10543,想着也来试试.MessageSolution企业邮件归档管理系统 EEA是北京易讯思达科技开发有限公司开发的一款邮件归档系统.该系 ...

  3. c#数据结构之集合的实现(数组及链表两种实现)

    集合的概念 集合是由一些确定的.彼此不同的成员或者元素构成的一个整体.如果将紧密相关的数据组合到一个集合中,则能够更有效地处理这些紧密相关的数据.代替编写不同的代码来处理每一单独的对象,您可以使用相同 ...

  4. microLite_timer,简洁、小巧精干的软件定时器

    microLite_timer是裸机软件定时器,源自microLite裸机系统的Kernel组件.​ 在本文的文末给出了microLite_timer的开源项目地址. 注:在前面一篇文章<mic ...

  5. 【FreeRTOS】11 软件定时器

    定时器是MCU常用的外设,我们在学习各种单片机时必然会学习它的硬件定时器.但是,MCU自带的硬件定时器资源是有限的,而且一般会用在实时性要求很强的地方. 在freeRTOS中提供了软件定时器的功能,来 ...

  6. 基于Android的个人记账软件的设计与实现

    基于Android的个人记账软件的设计与实现 [系统要求] 通过查阅和分析相关资料,应用所学知识与技术,独自完成一套基于Android的个人记账系统.系统开发过程应遵循软件工程思想,任务包括系统架构的 ...

  7. FreeRTOS学习笔记(7)——软件定时器

    一.头文件 #include "FreeRTOS.h" #include "timers.h" 二.软件定时器 2.1 基本概念 软件定时器在被创建之后,当经过 ...

  8. jQuery 一次定时器_学习RTOS(18)软件定时器

    l 软件定时器的基本概念 定时器,是指从指定的时刻开始,经过一个指定时间,然后触发一个超时事件,用户可以自定义定时器的周期与频率.类似生活中的闹钟,我们可以设置闹钟每天什么时候响,还能设置响的次数,是 ...

  9. 基于S32K144平台实现两种软件定时器

    文章目录 1.网红软件定时器MultiTimer 1.1 MultiTimer 简介 1.2 准备工作 1.3 MultiTimer 使用 1.3.1 新建工程 1.3.2 修改主函数 1.3.3 增 ...

最新文章

  1. 艾伟_转载:DataTable.NewRow 内存泄漏问题
  2. proguard的简单配置说明
  3. C++入门之常量与变量
  4. C/C++只做经典编程语言
  5. Android Gradle配置资源前缀
  6. 计算机wifi共享怎么设置,笔者教你win7如何设置wifi共享
  7. 相控阵天线(三):直线阵列天线低副瓣综合(切比雪夫、泰勒分布、SinZ-Z和Villeneuve分布、含python代码)
  8. 员工培训与开发实训心得体会_人力资源管理实训心得体会
  9. 关于verilog中综合的过程,可综合与不可综合的理解
  10. 微信小程序:修复图片音频全新升级带特效喝酒神器源码
  11. TR069服务器配置DHCP/IP/PING/Tracert/HTTP/PPPoE等仿真诊断模板及IPWAN和PPPoE WAN模板创建
  12. 个人号微信淘宝客机器人SDK定制开发教程
  13. DBSCAN聚类——Python实现
  14. nas系统存储服务器,我的瞎折腾NAS之系统选择篇
  15. Android通讯录模糊查询搜索(号码,姓名,首字母简拼,全拼),批量选取联系人
  16. acdream 1725 哗啦啦的小彭玉染色问题 离散化并查集
  17. linux 3.10在mini210s上移植----02.minicom安装
  18. 面向开发人员的 ChatGPT 提示词教程中文版 - ChatGPT 版
  19. 既然选择了前方,便不顾风雨兼程。
  20. 华中“HackFUN”创客马拉松大赛

热门文章

  1. 灰色预测方法预测温度matlab,灰色预测matlab代码怎么写
  2. 生物特征识别性能的不同衡量标准以及python源代码
  3. IT职业病预防之颈椎病(一)
  4. 小程序报错类—— thirdScriptError sdk uncaught third Error Cannot read property '$mount' of unde
  5. 打开任务管理器的多种方法
  6. UC/OS-II(一)资料绪论
  7. 推荐1个易上手代码开源的好用的H5网页编辑工具
  8. java输入十个,键盘输入十个数,输出最大数
  9. 主流Paas云平台架构设计思想
  10. m3u8.sqlite文件转视频工具(开源免费)