单片机软件定时器V1.0,可大批量创建,操作简单
V2.0版本已出
移植方法:1: 把 counter_prosess(); 放入1ms中断回调2: 修改 MAX_TIMER_NUM 的定义值 (根据自己想要使用的数量)3: 查看底部例程使用方法4: 使用前调用一次counter_init();主意事项: 定时器器触发后一定要关掉(挂起)定时器或者删除
.H
#ifndef __SORFT_TIMER_H
#define __SORFT_TIMER_H
//#include "sys.h"
typedef unsigned char u8;
typedef unsigned char uint8_t;
typedef unsigned short int u16;
typedef unsigned short int uint16_t;
typedef unsigned int u32;
typedef unsigned int uint32_t;//**移植修改步骤**//
/*1: 把 counter_prosess(); 放入1ms中断回调2: 修改 MAX_TIMER_NUM 的定义值 3: 查看底部例程使用方法4: 使用前调用一次counter_init();5: 记得把printf注释掉,如果没有配置printf会停在printf的while循环里面
*///***********计数值状态****start*******/
#define JUST_CREATED 0 //刚刚开始或创建
#define TIMING 2 //计数中
#define TIMING_END 1 //计时结束(常用)
#define DESTROYED 3 //未创建状态(常用)
#define TIM_SUSPEND 4 //暂停定时器
#define TIM_CRAT_ERROR 5 //出现错误
#define LOCK_TIMNG 6 //锁定计数,只能等到计数结束(常用)
#define TIM_ONCE 7 //单次计数模式//********************end*************///*******定时器结构体 start*********//
typedef struct id_menber{ //uint16_t id; //uint32_t count; //计数值 //uint32_t target; //目标值 //uint8_t state; //状态 //uint8_t end_state;
}s_id; ////
#define MAX_TIMER_NUM 24 //定时器最大个数(可修改)//
typedef struct timer_id{ //s_id id_ary[MAX_TIMER_NUM]; //uint16_t timer_lsat_index; //
}s_timer_id; //
//****************end***************//void counter_prosess(void); //此函数放入定时器中断回调函数void sorft_timer_init(void); //初始化定时器u8 start_timer(u16 ID,u32 count ,u8 state); //开启一个定时器u8 start_once_timer(u16 ID,u32 count ,u8 state); //开启一次定时器u8 close_timer(u16 ID,u8 state ); //关掉或者暂停一个定时器u8 timer_state(u16 ID); //读取定时器状态u32 timer_count_value(u16 ID); //查询定时器计数值
//**使用例程 start**//
/* 此例程适用 按键触发等裸机大循环#define ENTER_WAIT 80
#define BACK_WAIT 90
#define KEY1_DELAY_ID 0x01
#define OPEN_DELAY_ID 0x02if( !PIN_STATE(key1_pin) ){ //检查按键是否按下//防抖延时if( timer_state(KEY1_DELAY_ID) == TIMING_END){ //查看是否计时结束close_timer(KEY1_DELAY_ID,TIM_SUSPEND); //挂起定时器//do something}else{start_timer(KEY1_DELAY_ID,ENTER_WAIT,LOCK_TIMNG); //开启一个定时器//第一个参数是ID,第二个参数是计数值,第三个参数是计数状态}}else{close_timer(KEY1_DELAY_ID ,DESTROYED); //挂起定时器}
-------------------------------------------------if(timer_state(OPEN_DELAY_ID) == DESTROYED){ //定时一秒进入//do somethingstart_once_timer(OPEN_DELAY_ID,1000,LOCK_TIMNG);}*/
//**end**//#endif
.C
#include "sorft_timer.h"
//#include "HAL_device.h" //用户头文件
//#include "HAL_conf.h" //用户头文件
//#include "key.h" //用户头文件
#include "stdio.h"/***********计数值**************/
#define START_COUNT 0
#define END_COUNT 99999999
#define ID_CLEAR 0
/****************************/s_timer_id timer_id;
uint8_t OPEN_COUNTER = 0;
/**
* @bref 定时器中断回调,对所有计数值进行减少
* 中断触发为 1ms
* 根据用户层需要的计时时间,到达就改变状态
**/
void counter_prosess(void){ //此函数放入中断回调uint8_t i = 0;if(OPEN_COUNTER){for(i = 0 ;i < MAX_TIMER_NUM ; i++){if((timer_id.id_ary[i].id) != ID_CLEAR){if(timer_id.id_ary[i].state != TIM_SUSPEND ){if((++(timer_id.id_ary[i].count)) >= (timer_id.id_ary[i].target )){timer_id.id_ary[i].count = END_COUNT;timer_id.id_ary[i].state = TIMING_END;if(timer_id.id_ary[i].end_state == TIM_ONCE){ //单次计数在结束时需要挂起定时器close_timer(timer_id.id_ary[i].id , DESTROYED);}}}}}}
}/**@bref 定时器id赋值,使用定时器前先调用一次此接口
**/
void sorft_timer_init(void){ uint8_t i = 0;//清空定时器所有 ID = 0for(i = 0 ;i < MAX_TIMER_NUM ; i++){timer_id.id_ary[i].id = ID_CLEAR; //清空IDtimer_id.id_ary[i].count = END_COUNT;timer_id.id_ary[i].state = DESTROYED; //定时器还未创建状态timer_id.id_ary[i].target = END_COUNT;timer_id.id_ary[i].end_state = DESTROYED;}timer_id.timer_lsat_index = 0; //对管理的timer进行计数OPEN_COUNTER = 1;//printf("初始化软件定时器 \n");
}/**@bref 启动一个定时器
* ID 用户自定义ID
* 需要计数时间MS
* 计数状态,LOCK_TIMING(计数时无法刷新计数值,只能等到计数结束)
* 计数状态,TIMING 可以中途重新刷新计数值
**/
u8 start_timer(u16 ID,u32 count ,u8 state){uint8_t i = 0;if(ID == 0||count == 0){return 0 ;}
/*************查看是否有相同ID****************/for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID ){ if(timer_id.id_ary[i].state != LOCK_TIMNG){timer_id.id_ary[i].id = ID; //IDtimer_id.id_ary[i].count = START_COUNT; //计数初始值timer_id.id_ary[i].state = JUST_CREATED; //刚刚创建或启动timer_id.id_ary[i].target = count;if(state == LOCK_TIMNG){timer_id.id_ary[i].state = LOCK_TIMNG; //锁定计数}//printf("start_timer:%d ",ID);return START_COUNT; //返回刚刚创建的状态}else{return LOCK_TIMNG;}}}
/********** 没有对应ID,找到ID为0的重新分配一个*********/for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID_CLEAR){ //printf("找到空闲timer\n");break; //找到ID为0 跳出来}}//printf("此时i: %d\n",i);if((timer_id.timer_lsat_index) < MAX_TIMER_NUM){timer_id.id_ary[i].id = ID; //IDtimer_id.id_ary[i].count = START_COUNT; //计数初始值timer_id.id_ary[i].state = JUST_CREATED; //刚刚创建或启动timer_id.id_ary[i].target = count; if(state == LOCK_TIMNG){timer_id.id_ary[i].state = LOCK_TIMNG; //锁定计数}timer_id.timer_lsat_index++; //新增一个ID ,进行+1计数//printf("start_timer:%d ",ID);return START_COUNT; //返回刚刚创建的状态}else{//printf("定时器数量到达最大\n");return TIM_CRAT_ERROR;}}
/*@bref 关掉定时器,TIM_SUSPEND 定时器不销毁,计数暂停DESTROYED 销毁定时器,ID将被抹去
*/
u8 close_timer(u16 ID,u8 state ){uint8_t i = 0;if(ID == 0){return 0 ;}if(state == TIM_SUSPEND){ //暂停定时器,也就是关掉的意思/***暂停定时器**** 查看是否有相同ID ********/for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID){ timer_id.id_ary[i].id = ID ; //ID不能抹去timer_id.id_ary[i].count = END_COUNT; //计数初始值timer_id.id_ary[i].state = TIM_SUSPEND; //挂起定时器timer_id.id_ary[i].end_state = TIM_SUSPEND; //timer_id.id_ary[i].target = END_COUNT;return TIM_SUSPEND; //返回刚刚创建的状态}}}else if(state == DESTROYED){ //销毁定时器/****销毁定时器*** 查看是否有相同ID ********/for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID){ timer_id.id_ary[i].id = ID_CLEAR; //清空IDtimer_id.id_ary[i].count = END_COUNT;timer_id.id_ary[i].state = DESTROYED; //定时器还未创建状态timer_id.id_ary[i].end_state = DESTROYED;timer_id.id_ary[i].target = END_COUNT;timer_id.timer_lsat_index--;//printf("delet_timer:%d ",ID);return DESTROYED; //返回刚刚创建的状态}}}return 0;
}/***@bref 返回定时器状态有此ID的定时器就返回当前状态没有就返回DESTROYED* **/
u8 timer_state(u16 ID){u8 i =0;if(ID == 0){return DESTROYED ;}for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID){ return timer_id.id_ary[i].state; //定时器状态}}return DESTROYED;
}
/***@bref 启动一次定时器* 计时结束自动销毁定时器* **/
u8 start_once_timer(u16 ID,u32 count ,u8 state){uint8_t i = 0;if(ID == 0||count == 0){return 0 ;}
/*************查看是否有相同ID****************/for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID ){ if(timer_id.id_ary[i].state != LOCK_TIMNG){timer_id.id_ary[i].id = ID; //IDtimer_id.id_ary[i].count = START_COUNT; //计数初始值timer_id.id_ary[i].state = JUST_CREATED; //刚刚创建或启动timer_id.id_ary[i].end_state = TIM_ONCE;timer_id.id_ary[i].target = count;if(state == LOCK_TIMNG){timer_id.id_ary[i].state = LOCK_TIMNG; //锁定计数}//printf("start_timer:%d ",ID);return START_COUNT; //返回刚刚创建的状态}else{return LOCK_TIMNG;}}}
/********** 没有对应ID,找到ID为0的重新分配一个*********/for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID_CLEAR){ //printf("找到空闲timer\n");break; //找到ID为0 跳出来}}//printf("此时i: %d\n",i);if((timer_id.timer_lsat_index) < MAX_TIMER_NUM){timer_id.id_ary[i].id = ID; //IDtimer_id.id_ary[i].count = START_COUNT; //计数初始值timer_id.id_ary[i].state = JUST_CREATED; //刚刚创建或启动timer_id.id_ary[i].end_state = TIM_ONCE; //标记为计数一次timer_id.id_ary[i].target = count; if(state == LOCK_TIMNG){timer_id.id_ary[i].state = LOCK_TIMNG; //锁定计数}timer_id.timer_lsat_index++; //新增一个ID ,进行+1计数//printf("start_timer:%d ",ID);return START_COUNT; //返回刚刚创建的状态}else{//printf("定时器数量到达最大\n");return TIM_CRAT_ERROR;}
}
/*@bref 查询计数值
*/
u32 timer_count_value(u16 ID){u8 i =0;if(ID == 0){return END_COUNT;}for(i = 0 ;i < MAX_TIMER_NUM ; i++){if( (timer_id.id_ary[i].id) == ID){ return timer_id.id_ary[i].count; //定时器状态}}return END_COUNT;
}
单片机软件定时器V1.0,可大批量创建,操作简单相关推荐
- 单片机软件定时器的使用方法
单片机软件定时器的使用方法 特别声明:文章是原创但是本文讲述的思想是在国外的开源代码中借鉴的 初学者在编写单片机程序时经常会用到延时函数,但是当系统逐步复杂以后(没有复杂到使用操作系统)延时会因为延时 ...
- 鼠标手势软件MouseGesture v1.0.0.3中文绿色版.rar 相关下载
鼠标手势软件MouseGesture v1.0.0.3中文绿色版.rar 开发技术 > 其它 > 鼠标手势软件MouseGesture v1.0.0.3中文绿色版.rar mousege ...
- java版左右手桌面盯盘软件dstock V1.0
V1.0功能比较简陋,先满足自己桌面盯盘需要 V1.0 版本功能介绍: 1. 1s实时刷新盯盘数据 主要市面上的,符合我要求的桌面应用要VIP,穷啊,还是月月付,年年付,还是自己搞吧! 2. 配置文件 ...
- 游客视频剪辑软件·免费版v1.0.0功能有哪些?
游客视频剪辑软件·免费版发布 往往剪辑一条视频需要很久.我们的程序到来就是为了更好更简单.快捷.省时的完成既定工作: 定位:给用户提供一些简单视频处理功能: 定位:提供功能完全免费.让大家更加省时省力 ...
- 准确测试身高的软件,情侣身高对比软件-身高模拟对比软件预约 v1.0最新版_5577安卓网...
情侣身高对比软件是一款非常简单实用的身高比较软件!有了它用户就能精准模拟对比身高,一键输入相关数据即可轻松模拟对比,操作简单便捷,喜欢的小伙伴可不要错过哦! [特别说明] 该软件暂未正式上线,敬请期待 ...
- 情侣测试身高软件,情侣身高对比软件-身高模拟对比软件预约v1.0最新版_5577安卓网...
情侣身高对比软件是一款非常简单实用的身高比较软件!有了它用户就能精准模拟对比身高,一键输入相关数据即可轻松模拟对比,操作简单便捷,喜欢的小伙伴可不要错过哦! [特别说明] 该软件暂未正式上线,敬请期待 ...
- c++手机编程软件_积木编程软件手机版下载-积木编程软件下载v1.0.1 安卓版
积木编程软件是可以在线可以学习编程的软件,平台给用户提供了大量的编程学习教程,软件还支持在线编程,学习内容丰富,让用户学习起来不会枯燥乏味,就算你是零基础的小白,也可以体验到编程的乐趣. 积木编程官方 ...
- app息屏后ajax请求不执行_息屏时钟app下载-息屏时钟软件下载v1.0 安卓版
息屏时钟app是一款息屏后可以在手机上显示各种时间的app,软件中可以感受全新的主题桌面,美化手机屏幕,不需要唤醒手机也能查看时间,软件的功能众多,还可以设置不同的息屏画面,超多内容可以体验,快来试试 ...
- 多软件启动器 v1.0
简介: 平常工作的时候常常需要同时启动很多个软件,一个个文件夹打开太麻烦了,所以作者制作了这个可以帮助用户一次性启动多个软件的小工具,也就是小编今天带来的这款多软件启动器,功能就是如上述说的一样,非常 ...
最新文章
- 第三篇 (.net socket 与 android )
- shell学习笔记 (2)
- python制作工资计算器-Python制作个税计算器
- [系统安全] 四十四.APT系列(9)Metasploit技术之基础用法万字详解及防御机理
- python编程基础_月隐学python第2课
- Mac OS使用技巧十九:Safari碉堡功能之二查看网页源码
- 安装python扩展库时只能使用pip_安装 Python 扩展库时只能使用 pip 工具在线安装,如果安装不成功就没有别的办法了。_学小易找答案...
- LeetCode 646. 最长数对链
- ServiceComb微服务开发框架介绍
- NUC1333 Knight Moves【DFS】
- ajax请求出错_学习笔记:Ajax总结
- rk3399_android7.1平台调试sensor流程记录
- 8 -- 深入使用Spring -- 2... Spring的“零配置”支持
- 全面剖析雅虎助手以及网络实名的流氓行径(2)
- vue实例的参数说明
- 中国智慧VS西方智慧-看中国IT风云
- Oracle 锁表查询及解锁
- c# 解决 DataGridView 排序后颜色丢失
- 长春市职称计算机考试成绩查询,长春市助理工程师查询网站
- 不应忘却的纪念-小百合(Lilybbs)
热门文章
- vue3 使用element表格导出excel表格(带图片)
- 洛谷P4188 Lifeguards S
- shell脚本--杀死进程
- 【360补天计划】记第一次漏洞提交
- cad镜像后标注尺寸数字反了_CAD中镜像文字后,文字反转了,可以这样轻松调整过来...
- 利用JS制作抖音同款3D照片墙(three.js)
- php 公众号发表文章,微信公众号如何发布文章最基本教程
- enumerate使用
- 我所理解的羽毛球运动(没有教练业余羽毛球如何让自己提高?)
- C++900行代码实现中国象棋游戏规则以及相关功能