51单片机只有两个硬件定时/计数器,有时候我们要用多个定时器,可以自己写软件定时器,就可以有多个定时器用了,下面代码用一个硬件定时器实现了四个定时器,实现四个LED以不同频率闪烁,为了验证定时效果,四个LED闪烁频率依次2倍关系,实际可以任意定义。
/*----------------------------------------------------
名称:用定时器控制led亮灭
单片机:stc12c2052
晶振:12M
说明:四个led,四种频率亮。
------------------------------------------------------*/
#include
//头文件
#define MY_TIMER_MAX (4) //最多四个定时器
#define NULL (0)
typedef void (*pFun)(void); //callback 函数指针类型
typedef struct myTimer{
char on; //开关
char is_period; //是否周期循环
unsigned short int time_out; //定时时间,单位ms
unsigned short int count; //定时计数用
}MY_TIMER;
pFun callback[MY_TIMER_MAX] = {NULL}; //定时器回调函数数组
MY_TIMER myTimerList[MY_TIMER_MAX] = {0}; //定时器结构数组
int gMyTimerMessage[MY_TIMER_MAX] = {0}; //定时器消息数组
sbit LED1=P1^0;
sbit LED2=P1^1;
sbit LED3=P1^2;
sbit LED4=P1^3;
#define ALL_ON {LED1=0;LED2=0;LED3=0;LED4=0;} //灯全开
//创建定时器,简化版本。
int CreatTimer(int index,unsigned short int time_out,char is_period,pFun callbackFun)
{
if(index >= MY_TIMER_MAX) return -1;
myTimerList[index].on = 1;
myTimerList[index].is_period = is_period;
myTimerList[index].time_out = time_out;
myTimerList[index].count = 0;
callback[index] = callbackFun;
return index;
}
//四个LED控制函数,on初始是0,第一次调用on变为1,是关灯。
void led_1_ctrl(void)
{
static char on = 0;
on = !on;
LED1 = on;
}
void led_2_ctrl(void)
{
static char on = 0;
on = !on;
LED2 = on;
}
void led_3_ctrl(void)
{
static char on = 0;
on = !on;
LED3 = on;
}
void led_4_ctrl(void)
{
static char on = 0;
on = !on;
LED4 = on;
}
void Init_Timer0(void) //初始化定时器0
{
TMOD=0x01; //定时器0,使用模式1,16位定时器
TH0=(65536-1000)/256; //给定初值
TL0=(65536-1000)%256;
EA=1; //打开总中断
ET0=1; //打开定时器中断
TR0=1; //开定时器
}
void main() //主函数
{
unsigned int i;
ALL_ON;
CreatTimer(0,250,1,led_1_ctrl);
CreatTimer(1,500,1,led_2_ctrl);
CreatTimer(2,1000,1,led_3_ctrl);
CreatTimer(3,2000,1,led_4_ctrl);
Init_Timer0();//初始化定时器0
while(1)
{
for(i = 0; i
= myTimerList[i].time_out) //定时到
{
gMyTimerMessage[i] = 1; //发消息
if(myTimerList[i].is_period) //是否周期循环
{
myTimerList[i].count = 0; //计数重置
}
else
{
myTimerList[i].on = 0; //关掉定时器
}
}
}
}
EA = 1;
}