软件定时器实现,32位单片机平台均可以兼容

软件定时器实现,32位单片机平台均可以兼容

1说明

实现一个了软件定时器,在32位平台下均可运行,采用数组法和链表法实现,各有优劣(数组法运行较快,但是数组大小固定,链表法运行较慢,但是支持创建任意数量的软件定时器)

2代码展示

my_softtimer.c

#include "my_softtimer.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"

#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)
	static pMY_SOFT_TIMER g_timer_list = NULL;	//链表
	static pMY_SOFT_TIMER g_head = NULL;				//链表头
#endif

#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
	static MY_SOFT_TIMER g_time_array[MAX_TIMER_NUM];//定义定时器数组,最大为MY_SOFT_TIMER
#endif

/*定时器系统计数*/
static volatile TIM_U32_TYPE sys_cnt = 0;

/*定时器源 1ms级别*/
void soft_timer_source_tick(void)
{
	sys_cnt++;
}

/*软件定时器初始化*/
void soft_timer_init(void)
{	
#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)
	g_head = malloc(sizeof(MY_SOFT_TIMER));
	g_head->pNext = NULL;
	g_timer_list = g_head;
#elif (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
	memset(g_time_array,0,sizeof(g_time_array));
#endif	
	
}

/*添加一个定时器*/
char* soft_timer_add(MY_TIMER_CB timer_cb,TIM_U32_TYPE t_ms,char *name)
{
	
#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)
	//指针头插法
	pMY_SOFT_TIMER pt = malloc(sizeof(MY_SOFT_TIMER));
	pt->pNext = g_head->pNext;
	g_head->pNext = pt;
	
	//赋值
	strcpy(pt->name,name);
	pt->timr_cb = timer_cb;
	pt->par_cnt = t_ms;
	pt->cur_cnt = sys_cnt;
	pt->set_cnt = sys_cnt + t_ms;
	pt->sta			=	TIMER_RUN;
#elif (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
	TIM_S16_TYPE idx = -1;
	
	for(TIM_S16_TYPE i = 0;i<MAX_TIMER_NUM;i++)//寻找数组内的空位
	{
		if(TIMER_STOP == g_time_array[i].sta)
		{
			idx = i;		//记录数组内空位
			break;
		}
	}
	
	if(idx == -1) 
	{
		//无空位了
		return NULL;
	}
	
	//赋值操作
	strcpy(g_time_array[idx].name,name);
	g_time_array[idx].timr_cb = timer_cb;
	g_time_array[idx].par_cnt = t_ms;
	g_time_array[idx].cur_cnt = sys_cnt;
	g_time_array[idx].set_cnt = sys_cnt + t_ms;
	g_time_array[idx].sta			=	TIMER_RUN;	
#endif
	return name;
}	

/*删除一个定时器*/
TIM_S16_TYPE soft_timer_delete_by_name(char *name)
{
#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)
	pMY_SOFT_TIMER ptmp = g_head->pNext;
	pMY_SOFT_TIMER pfont= g_head;
	
	while(ptmp)
	{
		if(0 == strcmp(name,ptmp->name))
		{
			break;
		}
		pfont = ptmp;
		ptmp = ptmp->pNext;
	}
	
	//不存在该名字定时器
	if(!ptmp)
	{
		printf("can't find this node\r\n");
		return -1;
	}
	
	//找到,删除该节点
	pfont->pNext = ptmp->pNext;
	
	//释放该节点
	if(ptmp)
	{
		free(ptmp);
	}
	return 0;
#elif (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
	for(TIM_S16_TYPE i = 0;i<MAX_TIMER_NUM;i++)
	{
		if(0 == strcmp(name,g_time_array[i].name))
		{
			memset(&g_time_array[i],0,sizeof(MY_SOFT_TIMER));
			return 0;
		}
	}
	return -1;
#endif
}

/*定时器轮询*/
void soft_timer_polling(void)
{
#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST
	pMY_SOFT_TIMER ptmp = g_timer_list->pNext;
#elif (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
	pMY_SOFT_TIMER ptmp = g_time_array;
#endif

#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)
	while(ptmp){
#elif (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
	for(TIM_S16_TYPE i=0;i<MAX_TIMER_NUM;i++)
	{
		ptmp = &g_time_array[i];
#endif
	
		switch(ptmp->sta) 
		{
			case TIMER_STOP:	//处于停止状态
			{
				/*
					暂时不做事情
				*/
							
				
			}break;
			
			case TIMER_RUN:		//处于计数状态
			{
				//数据未发生溢出
				if((ptmp->set_cnt) > (ptmp->cur_cnt))	//设定值期望>设定记录值
				{
					if(sys_cnt > (ptmp->set_cnt))
					{
						ptmp->sta = TIMER_OVER_FLOW;
					}
				}
				else 
				{
					printf("发生数据溢出====================================\r\n");

					if((sys_cnt+ptmp->cur_cnt) > (ptmp->set_cnt))
					{
						ptmp->sta = TIMER_OVER_FLOW;
					}
				}
				
			
			}break;
			
			case TIMER_OVER_FLOW://处于溢出状态
			{
				
				TIM_S16_TYPE ret = ptmp->timr_cb(NULL);
				
				if(ret >= 0)			//返回值>0,继续下一次
				{
					ptmp->sta = TIMER_RUN;
					
					//赋值
					
					ptmp->cur_cnt = sys_cnt;
					ptmp->set_cnt = sys_cnt + ptmp->par_cnt;
					
				}
				else							//只运行一次
				{
					ptmp->sta = TIMER_STOP;
					soft_timer_delete_by_name(ptmp->name);
				}
				
			}break;
			
			default :{}break;
		}
#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)

				ptmp = ptmp->pNext;//指向下一个

#endif	
		
	}
	
}

/*链表遍历打印*/
void list_printf_test(void)
{
#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)
	pMY_SOFT_TIMER ptmp = g_timer_list->pNext;
	while(ptmp)
	{
		printf("Ttem name %s,address 0x%p\r\n",ptmp->name,ptmp);
		ptmp = ptmp->pNext;
	}
#elif (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
#endif	
}

my_softtimer.h

#ifndef __MY_SOFT_TIMER_H_
#define  __MY_SOFT_TIMER_H_

typedef unsigned int 		TIM_U32_TYPE;
typedef unsigned short 	TIM_U16_TYPE;
typedef int							TIM_S32_TYPE;
typedef short						TIM_S16_TYPE;

#define SOFT_TIMER_BY_LIST	1
#define SOFT_TIMER_BY_ARRAY	2
//定时器方式选择,推荐使用数组法
#define SOFT_TIMER_TYPE			SOFT_TIMER_BY_ARRAY
#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_ARRAY)
	//最大支持多少个软件定时器
	#define MAX_TIMER_NUM	5
#endif
#define MAX_CNT 4294967295UL

//声明定时器回调函数的类型
typedef TIM_S16_TYPE (*MY_TIMER_CB)(char *arg);

typedef enum TIMER_STA{
	TIMER_STOP = 0,
	TIMER_RUN	 = 1,
	TIMER_OVER_FLOW = 2,
}TIMER_STA;

typedef struct MY_SOFT_TIMER{
	char name[10];							//名字,句柄
	TIM_U32_TYPE par_cnt;				//传入值
	TIM_U32_TYPE cur_cnt;				//当前值
	TIM_U32_TYPE set_cnt;				//期望值
	TIMER_STA sta;							//状态值
	MY_TIMER_CB timr_cb;				//执行回调

#if (SOFT_TIMER_TYPE == SOFT_TIMER_BY_LIST)	
	
	struct MY_SOFT_TIMER *pNext;

#endif

}MY_SOFT_TIMER,*pMY_SOFT_TIMER;

void soft_timer_source_tick(void);
void soft_timer_init(void);
char* soft_timer_add(MY_TIMER_CB timer_cb,TIM_U32_TYPE t_ms,char *name);
TIM_S16_TYPE soft_timer_delete_by_name(char *name);
void soft_timer_polling(void);
	
#endif


3代码移植说明

作者:lin ying wei

版本:V1.0 2022.8.24

移植系统说明:
(1)将soft_timer_source_tick(); 放置在1ms的定时器硬件中断内
(2)将soft_timer_polling(); 函数放置在死循环体内(不能被阻塞)
(3)soft_timer_add(); 添加一个定时器
(4)soft_timer_delete_by_name(); 删除一个定时器
(5)soft_timer_init(); 参数初始化
(6)系统必须能提供32位的无符号变量类型
(7)需要提供几个变量类型

使用说明:
(1)本文件提供了数组法和链表法,建议使用数组法

使用样例:
(1)

void Timer_1ms_ServelFun(void)
{
soft_timer_source_tick();
}

TIM_S16_TYPE led1(char *arg)
{
printf(“This is led1\r\n”);
return 0;
}

TIM_S16_TYPE led2(char *arg)
{
printf(“This is led2\r\n”);
return 0;
}

TIM_S16_TYPE main(void)
{
other_init();//伪代码
soft_timer_init();
soft_timer_add(led1,1000,“led1”); //注册1s的调用回调函数
soft_timer_add(led1,1000,“led2”);
while(1)
{
soft_timer_polling();
}
}

4申明

如有BUG欢迎大家指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值