×
单片机 > 单片机程序设计 > 详情

51单片机自定义多个软件定时器

发布时间:2020-05-28 发布时间:
|

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;

}


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
C51 特殊功能寄存器SFR的名称和地址