我也来分享一个我使用的软定时器
因为在实际应用中可能需要大量的定时器,需要不同的定时时间,但硬件定时器数量较少,不能满足需求,
所以我写了一个的定时器的子程序,供参考一下,
也请各位大侠多多指教!废话不多说,上代码{:lol:}
定时器h和C文件,此部分参考了STC官网程序
time.h文件
#ifndef TIME
#define TIME
#include "../comm/STC32G.h"
#define MAIN_Fosc 24000000UL//定义主时钟
#define Timer0_Reload (MAIN_Fosc / 1000) //Timer 0 中断频率, 1000次/秒
#define Timer1_Reload (MAIN_Fosc / 2000) //Timer 1 中断频率, 2000次/秒
#define Timer2_Reload (MAIN_Fosc / 3000) //Timer 2 中断频率, 3000次/秒
#define Timer3_Reload (MAIN_Fosc / 4000) //Timer 3 中断频率, 4000次/秒
#define Timer4_Reload (MAIN_Fosc / 5000) //Timer 4 中断频率, 5000次/秒
//-------------------------------引脚定义----------------------------------
//-------------------------------变量声明----------------------------------
extern unsigned int Flag_1ms; //1ms时基
extern unsigned int Flag_10ms; //10ms时基
extern unsigned int Flag_100ms; //100ms时基
extern bit flag1ms; //1ms时基位变量
extern bit flag10ms ; //10ms时基位变量
extern bit flag100ms; //100ms时基位变量
//-------------------------------函数声明----------------------------------
void Timer0_init(void); //定时器0初始化
void Timer1_init(void); //定时器1初始化
void Timer2_init(void); //定时器2初始化
void Timer3_init(void); //定时器3初始化
void Timer4_init(void); //定时器4初始化
#endiftime.c文件
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.STCMCUDATA.com---------------------------------------*/
/* --- QQ:800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */
/*---------------------------------------------------------------------*/
/*************功能说明 **************
本例程基于STC32G为主控芯片的实验箱进行编写测试。
使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
本程序演示5个定时器的使用, 本例程均使用16位自动重装.
定时器0做16位自动重装, 中断频率为1000HZ,中断函数从P6.7取反输出500HZ方波信号.
定时器1做16位自动重装, 中断频率为2000HZ,中断函数从P6.6取反输出1000HZ方波信号.
定时器2做16位自动重装, 中断频率为3000HZ,中断函数从P6.5取反输出1500HZ方波信号.
定时器3做16位自动重装, 中断频率为4000HZ,中断函数从P6.4取反输出2000HZ方波信号.
定时器4做16位自动重装, 中断频率为5000HZ,中断函数从P6.3取反输出2500HZ方波信号.
下载时, 选择时钟 24MHZ (用户可自行修改频率).
******************************************/
//下面程序修改自STC官网例程,主要修改了定时器0的中断函数,使用了定时器0的时基作为软定时器的基准
#include "time.h"
//========================================================================
// 函数: void Timer0_init(void)
// 描述: timer0初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer0_init(void)
{
TR0 = 0; //停止计数
#if (Timer0_Reload < 64) // 如果用户设置值不合适, 则不启动定时器
#error "Timer0设置的中断过快!"
#elif ((Timer0_Reload/12) < 65536UL) // 如果用户设置值不合适, 则不启动定时器
ET0 = 1; //允许中断
//PT0 = 1; //高优先级中断
TMOD &= ~0x03;
TMOD |= 0;//工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
//T0_CT = 1;//计数
T0_CT = 0;//定时
//T0CLKO = 1; //输出时钟
T0CLKO = 0; //不输出时钟
#if (Timer0_Reload < 65536UL)
T0x12 = 1;//1T mode
TH0 = (unsigned char)((65536UL - Timer0_Reload) / 256);
TL0 = (unsigned char)((65536UL - Timer0_Reload) % 256);
#else
T0x12 = 0;//12T mode
TH0 = (unsigned char)((65536UL - Timer0_Reload/12) / 256);
TL0 = (unsigned char)((65536UL - Timer0_Reload/12) % 256);
#endif
TR0 = 1; //开始运行
#else
#error "Timer0设置的中断过慢!"
#endif
}
//========================================================================
// 函数: void Timer1_init(void)
// 描述: timer1初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer1_init(void)
{
TR1 = 0; //停止计数
#if (Timer1_Reload < 64) // 如果用户设置值不合适, 则不启动定时器
#error "Timer1设置的中断过快!"
#elif ((Timer1_Reload/12) < 65536UL) // 如果用户设置值不合适, 则不启动定时器
ET1 = 1; //允许中断
//PT1 = 1; //高优先级中断
TMOD &= ~0x30;
TMOD |= (0 << 4); //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装
//T1_CT = 1;//计数
T1_CT = 0;//定时
//T1CLKO = 1; //输出时钟
T1CLKO = 0; //不输出时钟
#if (Timer1_Reload < 65536UL)
T1x12 = 1;//1T mode
TH1 = (unsigned char)((65536UL - Timer1_Reload) / 256);
TL1 = (unsigned char)((65536UL - Timer1_Reload) % 256);
#else
T1x12 = 0;//12T mode
TH1 = (unsigned char)((65536UL - Timer1_Reload/12) / 256);
TL1 = (unsigned char)((65536UL - Timer1_Reload/12) % 256);
#endif
TR1 = 1; //开始运行
#else
#error "Timer1设置的中断过慢!"
#endif
}
//========================================================================
// 函数: void Timer2_init(void)
// 描述: timer2初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer2_init(void)
{
T2R = 0; //停止计数
#if (Timer2_Reload < 64) // 如果用户设置值不合适, 则不启动定时器
#error "Timer2设置的中断过快!"
#elif ((Timer2_Reload/12) < 65536UL) // 如果用户设置值不合适, 则不启动定时器
ET2 = 1; //允许中断
//T2_CT = 1;//计数
T2_CT = 0;//定时
//T2CLKO = 1; //输出时钟
T2CLKO = 0; //不输出时钟
#if (Timer2_Reload < 65536UL)
T2x12 = 1; //1T mode
T2H = (unsigned char)((65536UL - Timer2_Reload) / 256);
T2L = (unsigned char)((65536UL - Timer2_Reload) % 256);
#else
T2x12 = 0; //12T mode
T2H = (unsigned char)((65536UL - Timer2_Reload/12) / 256);
T2L = (unsigned char)((65536UL - Timer2_Reload/12) % 256);
#endif
T2R = 1; //开始运行
#else
#error "Timer2设置的中断过慢!"
#endif
}
//========================================================================
// 函数: void Timer3_init(void)
// 描述: timer3初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer3_init(void)
{
T3R = 0; //停止计数
#if (Timer3_Reload < 64) // 如果用户设置值不合适, 则不启动定时器
#error "Timer3设置的中断过快!"
#elif ((Timer3_Reload/12) < 65536UL) // 如果用户设置值不合适, 则不启动定时器
ET3 = 1; //允许中断
//T3_CT = 1;//计数
T3_CT = 0;//定时
//T3CLKO = 1; //输出时钟
T3CLKO = 0; //不输出时钟
#if (Timer3_Reload < 65536UL)
T3x12 = 1; //1T mode
T3H = (unsigned char)((65536UL - Timer3_Reload) / 256);
T3L = (unsigned char)((65536UL - Timer3_Reload) % 256);
#else
T3x12 = 0; //12T mode
T3H = (unsigned char)((65536UL - Timer3_Reload/12) / 256);
T3L = (unsigned char)((65536UL - Timer3_Reload/12) % 256);
#endif
T3R = 1; //开始运行
#else
#error "Timer3设置的中断过慢!"
#endif
}
//========================================================================
// 函数: void Timer4_init(void)
// 描述: timer4初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void Timer4_init(void)
{
T4R = 0; //停止计数
#if (Timer4_Reload < 64) // 如果用户设置值不合适, 则不启动定时器
#error "Timer4设置的中断过快!"
#elif ((Timer4_Reload/12) < 65536UL) // 如果用户设置值不合适, 则不启动定时器
ET4 = 1; //允许中断
//T4_CT = 1;//计数
T4_CT = 0;//定时
//T4CLKO = 1; //输出时钟
T4CLKO = 0; //不输出时钟
#if (Timer4_Reload < 65536UL)
T4x12 = 1; //1T mode
T4H = (unsigned char)((65536UL - Timer4_Reload) / 256);
T4L = (unsigned char)((65536UL - Timer4_Reload) % 256);
#else
T4x12 = 0; //12T mode
T4H = (unsigned char)((65536UL - Timer4_Reload/12) / 256);
T4L = (unsigned char)((65536UL - Timer4_Reload/12) % 256);
#endif
T4R = 1; //开始运行
#else
#error "Timer4设置的中断过慢!"
#endif
}
//========================================================================
// 函数: void timer0_int (void) interrupt TIMER0_VECTOR
// 描述:timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
bit flag1ms=0;//1ms时基位变量
bit flag10ms=0;//10ms时基位变量
bit flag100ms=1;//100ms时基位变量
unsigned int Flag_1ms=0;//1ms时基
unsigned int Flag_10ms=0;//10ms时基
unsigned int Flag_100ms=0;//100ms时基
void timer0_int (void) interrupt 1
{
static unsigned char count10=0;//软定时器10ms计数值
static unsigned char count100=0;//软定时器100ms计数值
Flag_1ms=0xffff;
flag1ms=1;
count10++;
count100++;
if (count10>=10)
{
Flag_10ms=0xffff;
count10=0;
flag10ms=1;
}
if (count100>=100)
{
Flag_100ms=0xffff;
count100=0;
flag100ms=1;
}
}
//========================================================================
// 函数: void timer1_int (void) interrupt TIMER1_VECTOR
// 描述:timer1中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer1_int (void) interrupt 3
{
P76 = ~P76;
}
//========================================================================
// 函数: void timer2_int (void) interrupt TIMER2_VECTOR
// 描述:timer2中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer2_int (void) interrupt 12
{
P77 = ~P77;
}
//========================================================================
// 函数: void timer3_int (void) interrupt TIMER3_VECTOR
// 描述:timer3中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer3_int(void) interrupt 19
{
P45 = ~P45;
}
//========================================================================
// 函数: void timer4_int (void) interrupt TIMER4_VECTOR
// 描述:timer4中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer4_int(void) interrupt 20
{
P46 = ~P46;
}
下面是软定时器函数
delay.h
#ifndef DELAY
#define DELAY
#include "time.h"
/*******************************************************************
* *
* 软定时器的实现 *
* *
* 1、定义了48个定时器 *
* 2、定时器定义如下 *
//1、定义的定时器0~15为1ms定时器 ,定时范围为0~32768ms
//2、定义的定时器16~31为10ms定时器, 定时范围为0~327680ms
//3、定义的定时器32~47为100ms定时器,定时范围为0~3276800ms
//4、定时器设定时间最大32768,不要用靠近的 定时器,
//比如定时100ms使用1ms定时器而不要使用100ms定时器,不然有定时误差
* 3、使用的是stc32的定时器0,基础时基为1ms *
* *
*********************************************************************/
//-------------------------------引脚定义----------------------------------
//-------------------------------变量声明----------------------------------
//-------------------------------函数声明----------------------------------
void TMR(unsigned char _id,unsigned int Presets);//设定定时器id和此定时器需要的定时时间
unsigned int TD(unsigned char _id); //返回定时器当前计数值
void Init_T(unsigned char _id);//定时器初始化
bit Tim(unsigned char _id); //定时器状态值
#endifdelay.c
#include "delay.h"
/*******************************************************************
* *
* 软定时器的实现 *
* *
* 1、定义了48个定时器 *
* 2、定时器定义如下 *
//1、定义的定时器0~15为1ms定时器 ,定时范围为0~32768ms
//2、定义的定时器16~31为10ms定时器, 定时范围为0~327680ms
//3、定义的定时器32~47为100ms定时器,定时范围为0~3276800ms
//4、定时器设定时间最大32768,不要用靠近的 定时器,
//比如定时100ms使用1ms定时器而不要使用100ms定时器,不然有定时误差
* 3、使用的是stc32的定时器0,基础时基为1ms *
* *
*********************************************************************/
//使用位段功能,大大减少内存占用,使用结构体改变定义不影响后面程序
typedefstruct
{
unsigned int current:15;//低15位作为计数值
unsigned int state:1;//最高位作为标志位
} Timer_TypeDef;
Timer_TypeDefT;
//1、定义的定时器0~15为1ms定时器 ,定时范围为0~32768ms
//2、定义的定时器16~31为10ms定时器, 定时范围为0~327680ms
//3、定义的定时器32~47为100ms定时器,定时范围为0~3276800ms
//4、定时器设定时间最大32768,不要用靠近的 定时器,
//比如定时100ms使用1ms定时器而不要使用100ms定时器,不然有定时误差
/**********************************************************************
//函数名称:TMR(unsigned char _id,uint16_t Presets)
//函数功能:设定定时器id和此定时器需要的定时时间
//入口参数:定时器id,需要定时时间
//返回参数:无
//当前版本:V1.0
//修改日期:
//当前作者:
//其它备注:
**********************************************************************/
void TMR(unsigned char _id,unsigned int Presets)//设定定时器id和此定时器需要的定时时间
{
if(_id<16) //时基是1ms
{
if((Flag_1ms & (1<<_id)) && T.state==0)//相比下面语句精简一点,下同
{
Flag_1ms &=~(1<<_id);//对应标志位清零
T.current++;//软定时器计数值+1
if(T.current<Presets) return;
T.state=1; //软定时器定时时间到
}
}
if(_id<32 && _id>=16) //时基是10ms
{
if((Flag_10ms & (1<<(_id-16))) && T.state==0)
{
Flag_10ms &=~(1<<(_id-16));//对应标志位清零
T.current++;//软定时器计数值+1
if(T.current>=Presets)
T.state=1;//软定时器定时时间到
}
}
if(_id<48 && _id>=32) //时基是100ms
{
if((Flag_100ms & (1<<(_id-32))) && T.state==0)
{
Flag_100ms &=~(1<<(_id-32));//对应标志位清零
T.current++;//软定时器计数值+1
if(T.current<Presets) return;
T.state=1;//软定时器定时时间到
}
}
}
/**********************************************************************
//函数名称: unsigned int TD(unsigned char _id)
//函数功能: 返回定时器当前值
//入口参数: 定时器的ID值
//返回参数: 定时器已过计数值
//当前版本: V1.0
//修改日期:
//当前作者:
//其它备注:
**********************************************************************/
unsigned int TD(unsigned char _id)
{
return T.current;
}
/**********************************************************************
//函数名称: void Init_T(unsigned char _id)
//函数功能:初始化定时器
//入口参数:定时器id
//返回参数:无
//当前版本:V1.0
//修改日期:
//当前作者:
//其它备注:
**********************************************************************/
void Init_T(unsigned char _id)
{
T.current=0;
T.state=0;
}
/**********************************************************************
//函数名称:bit Tim(unsigned char _id)
//函数功能:定时器状态值
//入口参数:定时器id
//返回参数:定时器结果,1为定时器时间到,0为时间未到
//当前版本:V1.0
//修改日期:
//当前作者:
//其它备注:
**********************************************************************/
bit Tim(unsigned char _id)
{
if(T.state==1)
return 1;
else
return 0;
}至于使用就简单了:
if(A)TMR(0,1234);//如果A条件满足,执行软定时器0
if(Tim(0))//软定时器设定时间到
{
巴拉巴拉;
Init(0);//初始化软定时器0,下次可以接着用
}
看来需要用这个的不多啊 这有点类似PLC的定时器 软件定时器,我就用一个timer0,1ms中断,就可以做N多定时器,我一般用倒计时,为0则定时到。
有人对结构体感冒,我就用普通数组吧,大约如下:
#define SoftTimerNum 32; //软件定时器个数
u8xdata TimerFlag; //软件定时器标志, 0: 无事件发生,1:定时到
u16xdata SoftTimer; //软件定时器倒计时
使用时,比如用SoftTimer;
SoftTimer = 1000; //定时1000ms
查询完成:
if(TimerFlag == 1)//定时到
{
//处理代码
}
Timer0 1ms中断里处理:
for(i=0;i<SoftTimerNum; i++)
{
if(SoftTimer != 0) //软件定时器倒计时
{
if(--SoftTimer == 0) TimerFlag = 1; //定时完成
}
}
梁工 发表于 2023-5-11 15:37
软件定时器,我就用一个timer0,1ms中断,就可以做N多定时器,我一般用倒计时,为0则定时到。
有人对结构体 ...
查询完成:
if(TimerFlag == 1)//定时到
{
//处理代码
}
这段怎么用呢,那不是32个标志位都会执行这个代码,
还有个问题,我要定时不同的时间,if(SoftTimer != 0) //软件定时器倒计时
{
if(--SoftTimer == 0) TimerFlag = 1; //定时完成
}
那这段不同的时间都要写一次吗 天源电子 发表于 2024-2-4 12:55
查询完成:
if(TimerFlag == 1)//定时到
{
每一个定时都是独立的,你要启用哪个定时,就装一个定时值。
比如用SoftTimer,启用时装载定时值:
SoftTimer = 1000; //定时1000ms
在定时到时要处理的任务,在任务重查询:
if(TimerFlag == 1)//定时到
{
TimerFlag = 0;
//处理代码
} 梁工 发表于 2023-5-11 15:37
软件定时器,我就用一个timer0,1ms中断,就可以做N多定时器,我一般用倒计时,为0则定时到。
有人对结构体 ...
梁工,这种的话木有定时器计数值的清零和定时时间的获取吧 jwd 发表于 2024-2-4 13:16
梁工,这种的话木有定时器计数值的清零和定时时间的获取吧
源码都给了 想实现什么自己往上加呗 jwd 发表于 2024-2-4 13:16
梁工,这种的话木有定时器计数值的清零和定时时间的获取吧
要清零就直接写0(就是提前主动结束定时器),定时时间的获取是指什么? 梁工 发表于 2024-2-4 15:56
要清零就直接写0(就是提前主动结束定时器),定时时间的获取是指什么? ...
类似plc里面的定时器,当某个条件满足时才开始启动软定时器,当条件断开后软定时器需要复位,计数值需要清零;定时时间是当启动某个软定时器后,我可能需要在定时到一定时间后开始某些动作,但是此时此软件定时器还没有到达设定的时间,所以此时标志位不会置位