单片机软件定时器V3.0

单片机软件定时器V3.0

使用方法:
1: 把	counter_prosess(); 放入1ms中断回调或1ms的OS任务中
2: 修改 MAX_TIMER_NUM  的定义值,比如需要用到10个定时器就改为>=10
3: 查看底部例程使用方法
4: 记得把printf注释掉,如果没有配置printf会停在printf的while循环里面

.H

#ifndef __SORFTIME_APP_H
#define __SORFTIME_APP_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中断回调或1ms的OS任务中
 2: 修改 MAX_TIMER_NUM  的定义值,比如需要用到10个定时器就改为>=10
 3: 查看底部例程使用方法
 4: 记得把printf注释掉,如果没有配置printf会停在printf的while循环里面
*/

//***********计数值状态****start*******/
typedef enum timer_state{
	//--------------------------------------//
	TIM_CRAT_ERROR 		=  0,  //刚刚开始或创建(几乎不用)
	TIM_CREATED   		=  1,  //计时结束(常用于状态比较)
	TIM_END 			=  2,  //出现错误(几乎不用)
	//--------------------------------------//
	TIM_ONCE	   		=  3,  //单次计数模式(几乎不用)
	TIM_CYCLE			=  4,  //循环计数
	//--------------------------------------//
	TIM_DESTROYED    	=  5,  //销毁状态(常用于close_timer)
	TIM_SUSPEND  		=  6,  //挂起定时器(偶尔用于close_timer)
	//--------------------------------------//
	TIM_LOCK   			=  7,  //锁定计数,不能再次更新计数值,只能等到计数结束(常用于start_timer)
	TIM_UNLOCK      	=  8  //正在计数中,可以再次手动更新计数值(偶尔用于start_timer)
	
}state_t;

typedef void (*rtn_func_t)(uint16_t); 

//*******定时器结构体 start*********//
typedef struct id_menber{			//
	uint16_t id;					//
	uint32_t count;	 //计数值			//
	uint32_t target; //目标值			//
	state_t  state;	//运行时的状态			//
	state_t  end_state; //结束后的状态
	rtn_func_t rtn_func;			//计时结束的回调函数
}s_id;								//
									//
#define  MAX_TIMER_NUM   10  //定时器最大个数(可修改)
									//
typedef struct timer_id{			//
	s_id id_ary[MAX_TIMER_NUM];		//
	uint16_t timer_last_index;		//
}s_timer_id;						//
//****************end***************//

void counter_init(void);

void counter_prosess(void); //此函数放入定时器中断回调函数

state_t  start_timer(u16 ID,u32 count ,state_t state); //开启一个定时器

state_t start_once_timer(u16 ID,u32 count ,state_t state); //开启一次定时器

/**
 * @brief state:TIM_LOCK\TIM_UNLOCK\TIM_ONCE\TIM_CYCLE
*/
state_t start_cb_timer(u16 ID, u32 count, state_t run_state,state_t end_state, rtn_func_t rtn_func); //计时结束,执行回调函数,函数执行完毕自动销毁该定时器

state_t  close_timer(u16 ID,state_t state ); //关掉或者暂停一个定时器
 
state_t  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  0x02

	if( !PIN_STATE(key1_pin) ){  //检查按键是否按下
		//防抖延时
		if( timer_state(KEY1_DELAY_ID) == TIM_END){ //查看是否计时结束
			close_timer(KEY1_DELAY_ID,TIM_SUSPEND);  //挂起定时器
			//do something
		}
		else{
			start_timer(KEY1_DELAY_ID,ENTER_WAIT,TIM_LOCK); //开启一个定时器
			//第一个参数是ID,第二个参数是计数值,第三个参数是计数状态
		}
	}
	else{
		close_timer(KEY1_DELAY_ID ,TIM_DESTROYED);  //挂起定时器
	}
-------------------------------------------------
	if(timer_state(OPEN_DELAY_ID) == TIM_DESTROYED){  //定时一秒进入
		//do something
		start_once_timer(OPEN_DELAY_ID,1000,TIM_LOCK);
	}

*/
//**end**//


#endif





.C

#include "sorftime_app.h"
#include "config_time.h"

#include "stdio.h"

/***********计数值**************/
#define START_COUNT 0
#define END_COUNT 999999999
#define ID_CLEAR 0
/****************************/
#define NULL_ID 0
#define NEW_ID 1
#define OLD_ID 2

// 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;

s_timer_id timer_id;
u8 OPEN_COUNTER = 0;
uint8_t MAX_USE_NUMBER = 0;
/**
 * @bref 定时器中断回调,对所有计数值进行减少
 *       中断触发为 1ms
 * 		根据用户层需要的计时时间,到达就改变状态
 **/
void counter_prosess(void)
{ // 此函数放入中断回调
	uint8_t i = 0;
	state_t temp_state;

	if (OPEN_COUNTER)
	{
		for (i = 0; i < MAX_USE_NUMBER; i++)
		{
			if ((timer_id.id_ary[i].id) != ID_CLEAR)
			{
				if ((timer_id.id_ary[i].state != TIM_SUSPEND) && (timer_id.id_ary[i].state != TIM_END))
				{
					if ((++(timer_id.id_ary[i].count)) >= (timer_id.id_ary[i].target))
					{
						timer_id.id_ary[i].count = END_COUNT;
						temp_state = timer_id.id_ary[i].state;
						timer_id.id_ary[i].state = TIM_END;

						if (timer_id.id_ary[i].rtn_func != NULL)
						{
							timer_id.id_ary[i].rtn_func(timer_id.id_ary[i].id);
							if (timer_id.id_ary[i].end_state == TIM_CYCLE)
							{ // 循环触发
								timer_id.id_ary[i].count = START_COUNT;
								timer_id.id_ary[i].state = temp_state;
							}
						}
						if (timer_id.id_ary[i].end_state == TIM_ONCE)
						{ // 单次计数在结束时需要挂起定时器
							close_timer(timer_id.id_ary[i].id, TIM_DESTROYED);
						}
					}
				}
			}
		}
	}
}

/**
 @bref 定时器id赋值,使用定时器前先调用一次此接口
**/
void counter_init(void)
{
	uint8_t i = 0;
	// 清空定时器所有 ID = 0
	for (i = 0; i < MAX_TIMER_NUM; i++)
	{
		timer_id.id_ary[i].id = ID_CLEAR; // 清空ID
		timer_id.id_ary[i].count = END_COUNT;
		timer_id.id_ary[i].state = TIM_DESTROYED; // 定时器还未创建状态
		timer_id.id_ary[i].target = END_COUNT;
		timer_id.id_ary[i].end_state = TIM_DESTROYED;
		timer_id.id_ary[i].rtn_func = NULL;
	}
	timer_id.timer_last_index = 0; // 对管理的timer进行计数
	OPEN_COUNTER = 1;
	// printf("初始化软件定时器 \n");
}

/**
 @bref 启动一个定时器
*		ID 用户自定义ID
*		需要计数时间MS
*		计数状态,LOCK_TIMING(计数时无法刷新计数值,只能等到计数结束)
*		计数状态,TIMING 可以中途重新刷新计数值
**/

state_t start_timer(u16 ID, u32 count, state_t state)
{
	uint8_t i = 0;
	uint8_t first_i = 0;
	uint8_t flag = NULL_ID;

	if (ID == 0 || count == 0)
	{
		return TIM_DESTROYED;
	}
	if (!OPEN_COUNTER)
	{
		counter_init();
	}
	/*************查找相同ID或者直接创建****************/
	for (i = 0; i < MAX_TIMER_NUM; i++)
	{
		if (timer_id.id_ary[i].id == ID)
		{
			first_i = i;
			flag = OLD_ID; // 查找相同ID
			if ((timer_id.id_ary[i].state == TIM_LOCK) || (timer_id.id_ary[i].state == TIM_END))
			{
				return TIM_LOCK;
			}
			break;
		}
		if ((timer_id.id_ary[i].id == ID_CLEAR) && (!flag))
		{
			first_i = i;
			flag = NEW_ID; // 查找并记录空闲ID
		}
	}
	if (!flag)
	{
		return TIM_CRAT_ERROR; // 防止未查找到
	}
	if ((timer_id.timer_last_index) < MAX_TIMER_NUM)
	{
		timer_id.id_ary[first_i].id = ID;			  // ID
		timer_id.id_ary[first_i].count = START_COUNT; // 计数初始值
		timer_id.id_ary[first_i].state = state;		  // 刚刚创建或启动
		timer_id.id_ary[first_i].target = count;
		timer_id.id_ary[first_i].end_state = TIM_DESTROYED;
		timer_id.id_ary[first_i].rtn_func = NULL;

		if (flag == NEW_ID)
		{
			if (first_i >= MAX_USE_NUMBER)
			{
				MAX_USE_NUMBER = first_i + 1;
				// printf("(%d)",MAX_USE_NUMBER);
			}
			if (++timer_id.timer_last_index >= MAX_USE_NUMBER) // 新增一个ID ,进行+1计数
			{
				timer_id.timer_last_index = MAX_USE_NUMBER;
			}
		}
		return TIM_CREATED; // 返回刚刚创建的状态
	}
	else
	{
		// printf("定时器数量到达最大\n");
		return TIM_CRAT_ERROR;
	}
}
/**
 *@bref 启动一次定时器
 * 计时结束自动销毁定时器
 * **/
state_t start_once_timer(u16 ID, u32 count, state_t state)
{
	uint8_t i = 0;
	uint8_t first_i = 0;
	uint8_t flag = NULL_ID;

	if (ID == 0 || count == 0)
	{
		return TIM_DESTROYED;
	}
	if (!OPEN_COUNTER)
	{
		counter_init();
	}
	/*************查找相同ID或者直接创建****************/
	for (i = 0; i < MAX_TIMER_NUM; i++)
	{
		if (timer_id.id_ary[i].id == ID)
		{
			first_i = i;
			flag = OLD_ID; // 查找相同ID
			if (timer_id.id_ary[i].state == TIM_LOCK)
			{
				return TIM_LOCK;
			}
			break;
		}
		if ((timer_id.id_ary[i].id == ID_CLEAR) && (!flag))
		{
			first_i = i;
			flag = NEW_ID; // 查找并记录空闲ID
		}
	}
	if (!flag)
	{
		return TIM_CRAT_ERROR; // 防止未查找到
	}
	if ((timer_id.timer_last_index) < MAX_TIMER_NUM)
	{
		timer_id.id_ary[first_i].id = ID;			  // ID
		timer_id.id_ary[first_i].count = START_COUNT; // 计数初始值
		timer_id.id_ary[first_i].state = state;		  // 刚刚创建或启动
		timer_id.id_ary[first_i].target = count;
		timer_id.id_ary[first_i].end_state = TIM_ONCE;
		timer_id.id_ary[first_i].rtn_func = NULL;
		if (flag == NEW_ID)
		{
			if (first_i >= MAX_USE_NUMBER)
			{
				MAX_USE_NUMBER = first_i + 1;
				// printf("(%d)",MAX_USE_NUMBER);
			}
			if (++timer_id.timer_last_index >= MAX_USE_NUMBER) // 新增一个ID ,进行+1计数
			{
				timer_id.timer_last_index = MAX_USE_NUMBER;
			}
		}
		return TIM_CREATED; // 返回刚刚创建的状态
	}
	else
	{
		// printf("定时器数量到达最大\n");
		return TIM_CRAT_ERROR;
	}
}

state_t start_cb_timer(u16 ID, u32 count, state_t run_state, state_t end_state, rtn_func_t rtn_func)
{
	uint8_t i = 0;
	uint8_t first_i = 0;
	uint8_t flag = NULL_ID;

	if (ID == 0 || count == 0 || rtn_func == NULL)
	{
		return TIM_DESTROYED;
	}
	if (!OPEN_COUNTER)
	{
		counter_init();
	}
	/*************查找相同ID或者直接创建****************/
	for (i = 0; i < MAX_TIMER_NUM; i++)
	{
		if (timer_id.id_ary[i].id == ID)
		{
			first_i = i;
			flag = OLD_ID; // 查找相同ID
			if (timer_id.id_ary[i].state == TIM_LOCK)
			{
				return TIM_LOCK;
			}
			break;
		}
		if ((timer_id.id_ary[i].id == ID_CLEAR) && (!flag))
		{
			first_i = i;
			flag = NEW_ID; // 查找并记录空闲ID
		}
	}
	if (!flag)
	{
		return TIM_CRAT_ERROR; // 防止未查找到
	}
	if ((timer_id.timer_last_index) < MAX_TIMER_NUM)
	{
		timer_id.id_ary[first_i].id = ID;			  // ID
		timer_id.id_ary[first_i].count = START_COUNT; // 计数初始值
		timer_id.id_ary[first_i].state = run_state;	  // 刚刚创建或启动
		timer_id.id_ary[first_i].target = count;
		timer_id.id_ary[first_i].end_state = end_state;
		timer_id.id_ary[first_i].rtn_func = rtn_func;

		if (flag == NEW_ID)
		{
			if (first_i >= MAX_USE_NUMBER)
			{
				MAX_USE_NUMBER = first_i + 1;
				// printf("(%d)",MAX_USE_NUMBER);
			}
			if (++timer_id.timer_last_index >= MAX_USE_NUMBER) // 新增一个ID ,进行+1计数
			{
				timer_id.timer_last_index = MAX_USE_NUMBER;
			}
		}
		return TIM_CREATED; // 返回刚刚创建的状态
	}
	else
	{
		// printf("定时器数量到达最大\n");
		return TIM_CRAT_ERROR;
	}
}

/*
 @bref 关掉定时器,
 TIM_SUSPEND 定时器不销毁,计数暂停
 TIM_DESTROYED  销毁定时器,ID将被抹去
*/
state_t close_timer(u16 ID, state_t state)
{
	uint8_t i = 0;
	if (ID == 0)
	{
		return TIM_DESTROYED;
	}
	for (i = 0; i < MAX_USE_NUMBER; i++)
	{
		if (timer_id.id_ary[i].id == ID)
		{
			break;
		}
	}
	if (i >= MAX_USE_NUMBER)
	{
		return TIM_DESTROYED;
	}
	if (state == TIM_SUSPEND)
	{ // 暂停定时器,也就是关掉的意思
		/***暂停定时器****	查看是否有相同ID       	 ********/
		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 == TIM_DESTROYED)
	{ // 销毁定时器
		/****销毁定时器***	查看是否有相同ID       	 ********/
		if ((timer_id.id_ary[i].id) == ID)
		{
			timer_id.id_ary[i].id = ID_CLEAR; // 清空ID
			timer_id.id_ary[i].count = END_COUNT;
			timer_id.id_ary[i].state = TIM_DESTROYED; // 定时器还未创建状态
			timer_id.id_ary[i].end_state = TIM_DESTROYED;
			timer_id.id_ary[i].target = END_COUNT;
			timer_id.id_ary[i].rtn_func = NULL;

			if (timer_id.timer_last_index > 0)
			{
				timer_id.timer_last_index--;
			}
			// printf("delet_timer:%d ",ID);
			if (timer_id.id_ary[MAX_USE_NUMBER - 1].state == TIM_DESTROYED)
			{
				MAX_USE_NUMBER--;
				// printf("(%d)",MAX_USE_NUMBER);
			}
			return TIM_DESTROYED; // 返回刚刚创建的状态
		}
	}

	return TIM_DESTROYED;
}

/**
 *@bref 返回定时器状态
 有此ID的定时器就返回当前状态
 没有就返回DESTROYED
 * **/
state_t timer_state(u16 ID)
{
	u8 i = 0;
	if (ID == 0)
	{
		return TIM_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 TIM_DESTROYED;
}

/*
 @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;
}


使用例程

//!定时回调函数样例
void myrtn(void) //自定义函数
{
	printf("into _ test");
}

//!按键防抖案例
while(1){
if( !PIN_STATE(key1_pin) )
{  //检查按键是否按下
		//防抖延时
		if( timer_state(0x110) == TIM_END)//查看防抖计时是否结束
		{ 
			close_timer(0x110,TIM_DESTROYED);  //销毁定时器
			//do something ,执行用户按下按键之后的事情
		}else
		{
			start_timer(0x110,60,TIM_LOCK); //开启一个防抖定时器
			//第一个参数是ID,第二个参数是计数值,第三个参数是计数状态
		}
}else
{
	close_timer(0x110,TIM_DESTROYED);  //销毁定时器
}

//--------------------------------------
#define MY_EVENT_FLG 100
#define MY_EVENT_SLEEP_FLG 101
void Tree_Task_ProcessEvent(uint16_t events)
{

    if (events == MY_EVENT_FLG)
    {
        LOG("MY_EVENT_FLG\n");
        return;
    }

    if (events == MY_EVENT_SLEEP_FLG)
    {
        LOG("MY_EVENT_SLEEP_FLG\n");
        return;
    }
}

start_cb_timer(MY_EVENT_FLG,2,TIM_LOCK,TIM_CYCLE,Tree_Task_ProcessEvent);
start_cb_timer(MY_EVENT_SLEEP_FLG,2,TIM_LOCK,TIM_CYCLE,Tree_Task_ProcessEvent);
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漏洞百出

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值