前言:该定时器设计方法使用Systick中断机制实现。
1.定义定时器结构
包含:软件定时器数量、工作模式、结构体成员
#define TMR_NUM 15//软件定时器数量
typedef enum
{
TMR_ONCE_MODE = 0; //一次性工作模式
TMR_AUTO_MDOE = 1; //自动定时工作模式
}TMR_MDDE_E;
//定时器结构体,成员必须volatile,否则C编译器优化可能有问题
typedef struct
{
volatile uint8_t Mode; //计数器模式
volatile uint8_t Flag; //定时器到达标志
volatile uint32_t Count; //计数器
volatile uint32_t PreLoad; //计数器预装载值
}SOFT_TMR;
函数应用层面
//定义软件定时器结构体变量
static SOFT_TMR s_tTmr[TMR_NUM];
//基于systick的中断的定时初始化清空
void bsp_InitTimer(void)
{
uint8_t i;
//清空软件定时器
for(i=0;i<TMR_NUM;i++)
{
s_tTmr[i].Count = 0;
s_tTmr[i].PreLoad = 0;
s_tTmr[i].Flag = 0;
s_tTmr[i].Mode = TMR_ONCE_MODE;
}
SysTick_Config(FREQ_SYS / 1000);//设定滴答定时器
}
//每隔1ms对所有定时器变量-1.必须被SysTick_ISR周期调用
stattic void bsp_SoftTimeDec(SOFT_TMR *_tmr)
{
if(_tmr->Count > 0)//启用了定时器
{
//如果定时器变量减到1则设置定时器到达标志
if(--_tmr-> == 0)
{
_tmr->Flag = 1;
//如果是自动模式,则自动重装计数器
if(_tmr->Mode == TMR_AUTO_MODE)
{
_tmr->Count = _tmr->PreLoad;
}
}
}
}
__IO int32_t g_iRunTime = 0;
void SysTick_ISR(void)
{
uint8_t i;
//每隔1ms进去一次(Delay_ms)
if(s_uiDelayCount > 0)
{
if(--s_uiDelayCount == 0)
{
s_ucTimeOutFlag = 1;
}
}
//定时器:每隔1ms对软件定时器进行减1操作
for(i=0;i < TMR_NUM; i++)
{
bsp_softTimerDec(&s_tTmr[i]);
}
//全局运行时间
g_iRunTime++;
if(g_iRrunTime == 0x7FFFFFFFF)//int32_t类型
{
g_iRunTime = 0;//避免溢出
}
}
/*
功能:启动一个定时器,并设定周期。
形参: _id : 定时器ID,值域[0,TMR_NUM-1]。用户自行维护定时器ID,避免定时器ID冲突。
_Period : 定时周期,单位1ms
*/
void bsp_StartTimer(uint8_t _id, uint32_t _period)
{
if(_id >= TMR_NUM)
{
//参数异常
//执行复位
while(1);
}
s_tTmr[id].Count = _period; //实时定时器初值
s_tTmr[id].PreLoad = _period; //自动重装载值,仅自动模式生效
s_tTmr[id].Flag = 0; //定时时间到达标志
s_tTmr[id].Mode = TMR_ONCE_MODE;//一次性工作模式
}
/*
功能:启动一个自动定时器,并设定周期。
形参: _id : 定时器ID,值域[0,TMR_NUM-1]。用户自行维护定时器ID,避免定时器ID冲突。
_Period : 定时周期,单位1ms
*/
void bsp_StartAutoTimer(uint8_t _id, uint32_t _period)
{
if(_id >= TMR_NUM)
{
//参数异常
//执行复位
while(1);
}
s_tTmr[id].Count = _period; //实时定时器初值
s_tTmr[id].PreLoad = _period; //自动重装载值,仅自动模式生效
s_tTmr[id].Flag = 0; //定时时间到达标志
s_tTmr[id].Mode = TMR_AUTO_MODE;//一次性工作模式
}
/* 停止定时器 _id 停止的ID */
void bsp_StopTimer(unt8_t _id)
{
if(id >= TMR_NUM){while(1);}
s_tTmr[_id].Count = 0;
s_tTmr[_id].Flag = 0;
s_tTmr[_id].Mode = TMR_ONCE_MODE;
}
/* 检查定时器是否超时 */
uint8_t bsp_CheckTimer(uint8_t _id)
{
if(_id >= TMR_NUM){return 0;}
if(s_tTmr[id].Flag == 1)
{
s_tTmr[_id].Flag = 0;
return 1;//时间已到达
}
else
{
return 0;//时间未到达
}
}
void SysTick_Handler()
{
Systick_ISR();
SysTick->SR=0;//清中断标志
}
总体的.c接口文件
//该代码为软件定时器创建代码
//定义软件定时器结构体变量
#include "DE_FIFO.h"
static xdata SOFT_TMR s_tTmr[TMR_NUM];
static volatile unsigned int xdata s_uiDelayCount = 0;
static volatile unsigned char xdata s_ucTimeOutFlag = 0;
volatile unsigned short xdata u16_SysTickCnt = 0;
//基于systick的中断的定时初始化清空
void bsp_InitTimer(void)
{
unsigned int i;
//清空软件定时器
for(i=0;i<TMR_NUM;i++)
{
s_tTmr[i].Count = 0;
s_tTmr[i].PreLoad = 0;
s_tTmr[i].Flag = 0;
s_tTmr[i].Mode = TMR_ONCE_MODE;
}
// SysTick_Config(FREQ_SYS / 1000);//设定滴答定时器
}
//每隔1ms对所有定时器变量-1.必须被SysTick_ISR周期调用
static void bsp_SoftTimeDec(SOFT_TMR *_tmr)
{
if(_tmr->Count > 0)//启用了定时器
{
//如果定时器变量减到1则设置定时器到达标志
if(--_tmr->Count == 0)
{
_tmr->Flag = 1;
//如果是自动模式,则自动重装计数器
if(_tmr->Mode == 1)
{
_tmr->Count = _tmr->PreLoad;
}
}
}
}
void SysTick_ISR(void)
{
unsigned short i;
//每隔1ms进去一次(Delay_ms)
if(s_uiDelayCount > 0)
{
if(--s_uiDelayCount == 0)
{
s_ucTimeOutFlag = 1;
}
}
//定时器:每隔1ms对软件定时器进行减1操作
for(i=0;i < TMR_NUM; i++)
{
bsp_SoftTimeDec(&s_tTmr[i]);
}
/*
//全局运行时间
g_iRunTime++;
if(g_iRrunTime == 0x7FFFFFFFF)//int32_t类型
{
g_iRunTime = 0;//避免溢出
}
*/
}
/*
功能:启动一个定时器,并设定周期。
形参: _id : 定时器ID,值域[0,TMR_NUM-1]。用户自行维护定时器ID,避免定时器ID冲突。
_Period : 定时周期,单位1ms
*/
void bsp_StartTimer(unsigned char _id, unsigned int _period)
{
if(_id >= TMR_NUM)
{
//参数异常
//执行复位
while(1);
}
s_tTmr[_id].Count = _period; //实时定时器初值
s_tTmr[_id].PreLoad = _period; //自动重装载值,仅自动模式生效
s_tTmr[_id].Flag = 0; //定时时间到达标志
s_tTmr[_id].Mode = TMR_ONCE_MODE;//一次性工作模式
}
/*
功能:启动一个自动定时器,并设定周期。
形参: _id : 定时器ID,值域[0,TMR_NUM-1]。用户自行维护定时器ID,避免定时器ID冲突。
_Period : 定时周期,单位1ms
*/
/*
void bsp_StartAutoTimer(unsigned char _id, unsigned int _period)
{
if(_id >= TMR_NUM)
{
//参数异常
//执行复位
while(1);
}
s_tTmr[_id].Count = _period; //实时定时器初值
s_tTmr[_id].PreLoad = _period; //自动重装载值,仅自动模式生效
s_tTmr[_id].Flag = 0; //定时时间到达标志
s_tTmr[_id].Mode = TMR_AUTO_MDOE;//一次性工作模式
}
*/
/* 停止定时器 _id 停止的ID */
void bsp_StopTimer(unsigned char _id)
{
if(_id >= TMR_NUM){while(1);}
s_tTmr[_id].Count = 0;
s_tTmr[_id].Flag = 0;
s_tTmr[_id].Mode = TMR_ONCE_MODE;
}
/* 检查定时器是否超时 */
unsigned char bsp_CheckTimer(unsigned char _id)
{
if(_id >= TMR_NUM){return 0;}
if(s_tTmr[_id].Flag == 1)
{
s_tTmr[_id].Flag = 0;
return 1;//时间已到达
}
else
{
return 0;//时间未到达
}
}
/*中断处理
void SysTick_Handler()
{
Systick_ISR();
SysTick->SR=0;//清中断标志
}
*/
总体的.h接口文件
#define TMR_NUM 15 //software timmer
#define uint8_t unsigned char xdata
#define uint16_t unsigned int xdata
#define uint32_t unsigned int xdata
typedef enum
{
TMR_ONCE_MODE = 0,
TMR_AUTO_MDOE = 1
}TMR_MDDE_E;
typedef struct
{
unsigned char Mode;
unsigned char Flag;
unsigned int Count;
unsigned int PreLoad;
}SOFT_TMR;
void bsp_InitTimer(void);
void SysTick_ISR(void);
void bsp_StartTimer(unsigned char _id, unsigned int _period);
void bsp_StartAutoTimer(unsigned char _id, unsigned int _period);
void bsp_StopTimer(unsigned char _id);
unsigned char bsp_CheckTimer(unsigned char _id);
void bsp_SoftTimeDec(SOFT_TMR *_tmr);
//调用放在timer中断或者systick中断
void timmer_iSR()//自动重装载模式
{
SysTick_ISR();//软件定时器
}