方法:
采用了一个定时器链表,按照定时时间从早到大进行排序,可加速处理的速度
并且加入了一个哨兵节点,定时时间设置为0xffffffff,来简化节点插入的操作
Timer.h
#ifndef __TIMER_H__
#define __TIMER_H__
#include "fifo.h"
//设定最多有500个定时器
#define MAX_TIMER 500
//已配置状态
#define TIMER_FLAGS_ALLOC 1
//定时器运行状态
#define TIMER_FLAGS_USING 2
//该定时器没有分配 使用
#define TIMER_FLAGS_NOT_USE 0
struct TIMER
{
struct TIMER *pNext;
unsigned int u32TimeOut;
unsigned int u32Flag;//记录当前的定时器是否被使用过
struct FIFO *pFifo;//缓冲区队列
int nData;
};
struct TIMER_CONTRAL
{
unsigned int u32Count;//当前总共计数的秒数
unsigned int u32Next;//下一个需要比较的定时器的时间
struct TIMER *pTimerHead;//定时器 链表的 头结点
struct TIMER TimerArr[MAX_TIMER];
};
//获得一个定时器
struct TIMER *GetTimer(void);
//释放一个定时器
void TimerFree(struct TIMER *pTimer);
//初始化定时器
void TimerInit(struct TIMER *pTimer, struct FIFO *pFifo, int nData);
//设置定时器
void SetTimer(struct TIMER *pTimer, unsigned int u32TimeOut);
#endif
初始化定时器
//初始化定时器 每10ms 发生一次中断
void InitPit(void)
{
int i;
struct TIMER *pShaoBIng;//感觉没有必要添加哨兵节点
//使用计数器0 先写入低字节在写入高字节 方式2循环计数 采用二进制
io_out8(PIT_CTRL, 0x34);//00 11 010 0
io_out8(PIT_COUNT0, 0x9c);
io_out8(PIT_COUNT0, 0x2e);
TimerCtl.u32Count = 0;
//将所有的定时器都设置为 未使用
for(i = 0; i < MAX_TIMER; i++)
{
TimerCtl.TimerArr[i].u32Flag = TIMER_FLAGS_NOT_USE;
}
//获得一个SB定时器 并将其放在定时器链表的最后
pShaoBIng = GetTimer();
pShaoBIng->u32TimeOut = 0xffffffff;
pShaoBIng->u32Flag = TIMER_FLAGS_USING;
pShaoBIng->pNext = 0;
//没有正在运行的定时器 所以就设置为SB的定时时间
TimerCtl.u32Next = 0xffffffff;
//设定定时器链表的头结点 为SB节点
TimerCtl.pTimerHead = pShaoBIng;
return;
}
定时器的中断处理
每次将TCL 的计数值+1 , 如何没有大于头结点设置的那个定时值,那么直接返回,到了后,查找定时值最小的那个,设置为头结点
void IntHandler20(int *pEsp)//定时器中断IRQ0
{
struct TIMER *pTimerTemp;
io_out8(PIC0_OCW2, 0x60);
//每次中断+1 来计数
TimerCtl.u32Count++;
//下一个需要比较的时间 未到 那么什么也不做
if(TimerCtl.u32Next > TimerCtl.u32Count)
{
return;
}
//把定时器链表的 头结点 赋值给 Temp
pTimerTemp = TimerCtl.pTimerHead;
//Temp 在循环结束时候 是第一个未超时的那个 或者都超时了
while(1)
{
//一直运行到 不超时那个TIMER 为止 因为pTimer数组是经过排序的
if(pTimerTemp->u32TimeOut > TimerCtl.u32Count)
{
break;
}
//处理超时的定时器
pTimerTemp->u32Flag = TIMER_FLAGS_ALLOC;
FifoSaveData(pTimerTemp->pFifo, pTimerTemp->nData);
pTimerTemp = pTimerTemp->pNext;
}
//改变头结点
TimerCtl.pTimerHead = pTimerTemp;
TimerCtl.u32Next = TimerCtl.pTimerHead->u32TimeOut;
return;
}