通用软件定时器(C语言实现)

目录

一、软件定时器功能描述

二、使用场景

三、使用注意事项

四、数据结构

五、操作函数声明

六、具体实现


一、软件定时器功能描述

通用软件定时器是通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断时,就对链表中处于运行状态的软件定时器的计数值进行递减,并判断是否递减到0以判断是否超时,如超时则执行相应的回调函数。在执行完超时回调函数后,如该软件定时器模式为单次定时则将定时器状态置为完成状态;如该软件定时器为周期定时则将定时器状态置为运行状态,并重新装载软件定时器的计数值为周期时间,重新开始计数。

二、使用场景

在硬件定时器资源受限,但又有较多任务需要周期处理,对执行周期要求不是很严格的情况下,可以由一个硬件定时器产生固定的时钟节拍,模拟出多个软件定时器来单次或周期性的执行相应的任务,这样就不会受限于硬件资源的不足

三、使用注意事项

1、不要在软件定时器的超时回调函数中做一些耗时的处理,比如延时、多次循环等

2、如果使用了RTOS,并在超时回调函数中调用了RTOS的API,需要注意是否有只能在中断中调用的限制,如FreeRTOS中就有专门在中断中使用的释放信号量、发送消息到消息队列的API

扫描二维码关注公众号,回复: 9399852 查看本文章

3、需要根据硬件定时器周期重新设置软件定时器的时钟节拍

四、数据结构

/* It needs to be modified according to the user's own environment before use !!!!!!!*/
#define SOFT_TIMER_TICK_MS      5
#define SOFT_TIMER_MALLOC(size) pvPortMalloc(size)
#define SOFT_TIMER_FREE(p)      vPortFree(p)

/* soft timer unit */
#define SOFT_TIMER_UNIT_MIN           1
#define SOFT_TIMER_UNIT_S             2
#define SOFT_TIMER_UNIT_MS            3

/* soft timer mode */
#define SOFT_TIMER_MODE_UNUSED        0
#define SOFT_TIMER_MODE_SIGLE         1
#define SOFT_TIMER_MODE_RERIOD        2

/* soft timer status */
#define SOFT_TIMER_STATUS_UNUSED      0
#define SOFT_TIMER_STATUS_STOP        1
#define SOFT_TIMER_STATUS_RUNNING     2
#define SOFT_TIMER_STATUS_COMPLETED   3

struct soft_timer
{
	struct soft_timer *next; /* timer list */
	unsigned char mode;      /* timer mode */
	unsigned char status;    /* timer status */
	unsigned char unit;      /* set unit:min/s/ms */
	unsigned long timeout;   /* soft timer period(ms) */
	unsigned long count;     /* timeout decrement value */
    void *param;             /* timeout_callback param */
	void (*timeout_cb)(void *param);/* timeout_callback */
};

五、操作函数声明

extern struct soft_timer *creat_soft_timer(void);
extern void soft_timer_del   (struct soft_timer *this_timer);
extern void soft_timer_start (struct soft_timer *this_timer);
extern void soft_timer_stop  (struct soft_timer *this_timer);
extern void soft_timer_reload(struct soft_timer *this_timer);

extern void soft_timer_config(struct soft_timer *this_timer, \
                              unsigned long timeout, \
                              unsigned char mode, \
                              unsigned char unit, \
                              void *param,\
                              void (*timeout_cb)(void *param));

extern void soft_timer_set_timeout(struct soft_timer *this_timer, unsigned long timeout);
extern unsigned char get_soft_timer_status(struct soft_timer *this_timer);
extern void soft_timer_exe(void);

六、具体实现

#include  <stdlib.h>
#include  <stdio.h>
#include "drv_soft_timer.h"

static struct soft_timer *soft_timer_list_head = NULL;/*the head of the soft timer list*/

/**
 * dynamically create a soft timer.
 * 
 * @param NONE
 * @return NULL:malloc fail
 *        !NULL:the soft timer
 */
struct soft_timer *creat_soft_timer(void)
{
	struct soft_timer *new_timer = NULL;
	struct soft_timer *p_timer = NULL;
	
	/* create a new soft timer */
	new_timer = SOFT_TIMER_MALLOC(sizeof(struct soft_timer));
	
	/* does the new soft timer created success */
	if (new_timer == NULL)
	{
		return NULL;
	}
	else
	{
		new_timer->timeout = 0;
		new_timer->count = 0;
		new_timer->mode = SOFT_TIMER_MODE_UNUSED;
		new_timer->status = SOFT_TIMER_STATUS_UNUSED;
	}
	
	/* does the soft timer list already exit */
	if (soft_timer_list_head == NULL)
	{
        new_timer->next = NULL;
		soft_timer_list_head = new_timer;
	}
	else
	{
		/* add the new soft timer to the end of the soft timer list */
		p_timer = soft_timer_list_head;
		while(p_timer->next != NULL)
		{
			p_timer = p_timer->next;
		}
        new_timer->next = NULL;
		p_timer->next = new_timer;
	}
	
	return new_timer;
}

/**
 * delete a soft timer from the timer list.
 * 
 * @param this_timer:soft timer to be deleted 
 * @return NONE
 */
void soft_timer_del(struct soft_timer *this_timer)
{
	struct soft_timer *cur_timer = soft_timer_list_head;
	struct soft_timer *pre_timer = NULL;
	
	/* does this soft timer is vaild */
	if (this_timer == NULL)
		return;
	
	/* find this timer delete it from timer list */
	while (cur_timer != NULL)
	{
		if (cur_timer == this_timer)
		{
			/* head node is the find soft timmer */
			if (cur_timer == soft_timer_list_head)
				soft_timer_list_head = cur_timer->next;
			else
				pre_timer->next = cur_timer->next;
			
			cur_timer->next = NULL;
			SOFT_TIMER_FREE(cur_timer);
			cur_timer = NULL;
			break;
		}
		pre_timer = cur_timer;
		cur_timer = cur_timer->next;
	}
}

/**
 * start the soft timer.
 * 
 * @param this_timer:soft timer to start
 * @return NONE
 */
void soft_timer_start(struct soft_timer *this_timer)
{
    if (this_timer->timeout == 0)
      return;
    
	this_timer->status = SOFT_TIMER_STATUS_RUNNING;
    this_timer->count  = this_timer->timeout;
}

/**
 * stop the soft timer.
 * 
 * @param this_timer:soft timer to stop
 * @return NONE
 */
void soft_timer_stop(struct soft_timer *this_timer)
{
	this_timer->status = SOFT_TIMER_STATUS_STOP;
}

/**
 * reload the soft timer.
 * 
 * @param this_timer:soft timer to reload
 * @return NONE
 */
void soft_timer_reload(struct soft_timer *this_timer)
{
    if (this_timer->timeout == 0)
      return;
    
	this_timer->status = SOFT_TIMER_STATUS_RUNNING;
    this_timer->count  = this_timer->timeout;
}

/**
 * config the soft timer.
 * 
 * @param this_timer:soft timer to config
 * @param timeout:soft timer period
 * @param mode:SOFT_TIMER_MODE_SIGLE  SOFT_TIMER_MODE_RERIOD
 * @param unit:SOFT_TIMER_UNIT_MIN    SOFT_TIMER_UNIT_S    SOFT_TIMER_UNIT_MS
 * @param param:timeout callback param
 * @param timeout_cb:timeout callback
 *
 * @return NONE
 */
void soft_timer_config(struct soft_timer *this_timer, \
                              unsigned long timeout, \
                              unsigned char mode, \
                              unsigned char unit, \
                              void *param,\
                              void (*timeout_cb)(void *param))

{
    this_timer->mode  = mode;
    this_timer->unit  = unit;
    this_timer->param = param;
    this_timer->timeout_cb = timeout_cb;
	soft_timer_set_timeout(this_timer, timeout);
}

/**
 * set the soft timer timeout.
 * 
 * @param this_timer:soft timer to config
 * @param timeout:soft timer period
 *
 * @return NONE
 */
void soft_timer_set_timeout(struct soft_timer *this_timer, unsigned long timeout)
{
	/* since the increments are ms, different units of timing need to be converted to ms */
	if (this_timer->unit == SOFT_TIMER_UNIT_MS)
		this_timer->timeout = timeout;
	else if (this_timer->unit == SOFT_TIMER_UNIT_S)
		this_timer->timeout = timeout*1000;
	else if (this_timer->unit == SOFT_TIMER_UNIT_MIN)
		this_timer->timeout = timeout*60*1000;
}

/**
 * get the soft timer status.
 * 
 * @param this_timer:soft timer to get
 *
 * @return soft timer status
 */
unsigned char get_soft_timer_status(struct soft_timer *this_timer)
{
	return this_timer->status;
}

/**
 * soft timer execute.
 * 
 * @param NONE
 *
 * @return NONE
 */
void soft_timer_exe(void)
{
    struct soft_timer *p_timer = soft_timer_list_head;
	
	/* effective timer */
	while (p_timer != NULL)
	{
		if (p_timer->status == SOFT_TIMER_STATUS_RUNNING)
		{
			/* Counting time decrement */
			if (p_timer->count < SOFT_TIMER_TICK_MS)
				p_timer->count = 0;
			else
				p_timer->count -= SOFT_TIMER_TICK_MS;
			
			/* time out */
			if (p_timer->count == 0)
			{
				if (p_timer->mode == SOFT_TIMER_MODE_SIGLE)
				{
					p_timer->status = SOFT_TIMER_STATUS_COMPLETED;
					if (p_timer->timeout_cb != NULL)
						p_timer->timeout_cb(p_timer->param);
				}
				else if (p_timer->mode == SOFT_TIMER_MODE_RERIOD)
				{
					p_timer->status = SOFT_TIMER_STATUS_RUNNING;
					p_timer->count = p_timer->timeout;
					if (p_timer->timeout_cb != NULL)
						p_timer->timeout_cb(p_timer->param);
				}
			}
		}
		
		p_timer = p_timer->next;
	}
}
发布了35 篇原创文章 · 获赞 22 · 访问量 1141

猜你喜欢

转载自blog.csdn.net/m0_37845735/article/details/103555693