需要一个基于单片机89S51的可编程定时器的程序,定时器由4个8段数码管显示,可以设置分和秒定时。

可以同时对四路控制对象进行定时控制,外部控件可以用于选择控制对象,设置定时,对定时进行暂停,重置等控制。最好附带点解说,能做的可以发送到我邮箱[email protected]

第1个回答  2011-06-01
外部控件是什么样的,你的硬件设计图有吗?
#include <AT89X52.H>

//宏定义
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long int

/*****************************************************************************
* TH0和TL0是计数器0的高8位和低8位计数器,计算办法:TL0=(65536-C)%256; *
* TH0=(65536-C)/256,其中C为所要计数的次数即多长时间产生一次中断;TMOD是计数器*
* 工作模式选择,0X01表示选用模式1,它有16位计数器,最大计数脉冲为65536,最长时 *
* 间为1ms*65536=65.536ms *
******************************************************************************/
#define V_TMOD 0x01 //工作方式1
#define V_TH0 0x3C //50ms延时常数 C=50000 //0XDC
#define V_TL0 0xB0 //50ms延时常数 C=50000 /0X58
//#define V_TH1 0xFF //5ms延时常数 C=5000 //0XDC
//#define V_TL1 0xFB //5ms延时常数 C=5000 /0X58
#define V_TH1 0xDC //1ms延时常数 C=1000 //0XDC
#define V_TL1 0x58 //1ms延时常数 C=1000 /0X58

#define MAXFUN 6 //功能切换,表示最多的功能状态,

sbit k10=P1^0;
//sbit BEEP = P3^7; //蜂鸣器驱动线----------------请修改为sbit BEEP = P0^4;
uchar bee; //蜂鸣器01开关

uchar key; //键顺序吗
uchar fun=10; //功能状态, <= MAXFUN
uchar it0=0,it1; //Timer0中断计数

uchar text=0; //数字
//uchar text_ctrl[4]={0xFE,0xFD,0xFB,0xF7}; //位选通值, 11111110, 11111101, 11111011, 11110111
uchar text_ctrl[4]={0xE,0xD,0xB,0x7}; //位选通值, 00001110, 00001101, 00001011, 00000111
//uchar text_code[11]={ 0x28, 0x7E, 0xA2, 0x62, 0x74, 0x61, 0x21, 0x7A, 0x20, 0x60,0xff};//0,1,2,3,4,5,6,7,8,9,关显示,数码管码表,高电平有效
//uchar text_code[17]= {0x28,0x7e,0xa2,0x62,0x74,0x61,0x21,0x7a,0x20,0x60,0x30,0x25,0xa9,0x26,0xa1,0xb1};//数码管代码
uchar text_code[11]={ 0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6,0xff};//0,1,2,3,4,5,6,7,8,9,关显示,数码管码表,高电平有效
uchar text_index=0; //当前显示第几个

uchar dis_buf[4]; //显示缓存
uchar refresh=0; //刷新否 T1蜂鸣
uchar min=0; //minutes
uchar sec=0; //scconds
uchar hour=0; //scconds
uchar onsetup=0;
uchar keydown0=0,keydown1=0;

uchar data PWM=0xFf ; //PWM值增加,则占空比减小,LED 灯渐暗。

/*****************************************************/
// 延时子程序
/*****************************************************/
void delay0(uchar x) //x*0.14MS
{
uchar i;
while(x--)
for (i = 0; i<13; i++) {}
}
/*****************************************************/
//T1蜂鸣
/*****************************************************/
void beepT1()
{
if(refresh >0 )
{
refresh++;
bee=!bee;
if(refresh>=30)
refresh = 0;
}
}
/*****************************************************/
//文字输出
/*****************************************************/
void textout()
{
//P0 = 0xff; // 先关闭所有数码管
P2 = dis_buf[text_index]; //传入数字的码
bee = bee<<4;
P0 = text_ctrl[text_index]|bee; //选择位
//P0 = bee; //选择位
text_index++; //下一位
if( text_index >=4 )
text_index = 0;
}

/*****************************************************/
//键扫描子程序
/*****************************************************/
void keyscan(void)
{
uchar temp;

key = -1; //不按键

P1=0x0F; //低四位输入
delay0(12);
temp=P1; //读P1口
temp=temp&0x0F;
temp=~(temp|0xF0);
if(temp==1)
key=0;
else if(temp==2)
key=1;
else if(temp==4)
key=2;
else if(temp==8)
key=3;
else
key=16;

P1=0xF0; //高四位输入
delay0(12);
temp=P1; //读P1口
temp=temp&0xF0;
temp=~((temp>>4)|0xF0);
if(temp==1)
key=key+0;
else if(temp==2)
key=key+4;
else if(temp==4)
key=key+8;
else if(temp==8)
key=key+12;
else
key=16;

if( key!= -1)
fun = key;
//key =0;
//dis_buf=text_code[key]; //查表得键值
}

/*****************************************************/
//判断键是否按下
/*****************************************************/
int keydown(void)
{
P1=0xF0;
if(P1!=0xF0)
{
keyscan();
//delay0(250);
return 1;
//
//beep();
// while(P1!=0xF0); //等待键释放
}
return 0;
}
/*****************************************************/
//设置显示缓存
/*****************************************************/
void settext(uchar text0,uchar text1,uchar text2,uchar text3)
{
dis_buf[0]=text_code[text0];
dis_buf[1]=text_code[text1];
dis_buf[2]=text_code[text2];
dis_buf[3]=text_code[text3];
}
/*****************************************************/
//fun10
//秒表 mm:ss
/*****************************************************/
void fun10()
{
it0++;
if( it0==20 ) //1s
{
it0=0;
sec++;
if(sec==60)
{
sec = 0;
min++;

if(min==60)
{
min =0;
}
}
refresh = 1;
dis_buf[1] = text_code[min%10];
dis_buf[0] = text_code[min/10];
dis_buf[3] = text_code[sec%10];
dis_buf[2] = text_code[sec/10];
}
}

/*****************************************************/
//fun11
//时钟 hh:mm
/*****************************************************/
void fun11()
{
it0++;
if( it0==20 ) //1s
{
it0=0;
sec++;
if(sec==60)
{
sec = 0;
min++;
if(min==60)
{
min =0;
hour++;
if(hour==12)
{
hour =0;
}
//dis_buf[1] = text_code[hour%10];
//dis_buf[0] = text_code[hour/10];
}
refresh = 1;

}dis_buf[1] = text_code[hour%10];
dis_buf[0] = text_code[hour/10];
dis_buf[3] = text_code[min%10];
dis_buf[2] = text_code[min/10];
}
}
/*****************************************************/
//fun12
//倒计时
/*****************************************************/
void fun12()
{
it0++;
if( it0==20 ) //0.1s
{
it0=0;
sec--; //sec must >=1
if(sec==0)
{
sec = 60;
min--;
//dis_buf[1] = text_code[min%10];
//dis_buf[0] = text_code[min/10];
if(min==0)
{
min =60;
}
}
refresh = 1;
dis_buf[1] = text_code[min%10];
dis_buf[0] = text_code[min/10];
dis_buf[3] = text_code[sec%10];
dis_buf[2] = text_code[sec/10];
}
}
/*****************************************************/
//fun13
//设置时间:hh:mm
/*****************************************************/
void fun13()
{
onsetup =1;
sec=0;
min=0;
hour=0;
dis_buf[1] = text_code[min%10];
dis_buf[0] = text_code[min/10];
dis_buf[3] = text_code[sec%10];
dis_buf[2] = text_code[sec/10];
}
/*****************************************************/
//fun3
//设置时间:hh:mm
/*****************************************************/
void fun130()
{
if( keydown1!= keydown0)
{
keydown0 = keydown1;
if(keydown1==0 ) return;//按键弹起

if(onsetup==1)
hour = key*10;
else if(onsetup==2)
hour += key;
else if(onsetup==3)
min = key*10;
else if(onsetup==4)
min += key;
onsetup++;

dis_buf[1] = text_code[hour%10];
dis_buf[0] = text_code[hour/10];
dis_buf[3] = text_code[min%10];
dis_buf[2] = text_code[min/10];
}
}
/*****************************************************/
//fun14
//设置
/*****************************************************/
void fun14()
{
sec=0;
min=0;
hour=0;
}

/*****************************************************/
// 定时器0中断服务程序, 用于数码管的动态扫描
//T0定时器,50ms激发一次,间隔1秒执行一次输出(需要20次)
/*****************************************************/
void timer0() interrupt 1
{
//TR1=0 ;
TH0=V_TH0; //1ms延时常数
TL0=V_TL0; //频率调节
//TH1=PWM ;
//TR1=1 ;

keydown1 = keydown();
//if( keydown1!= keydown0)
{

if( fun <=9 )
fun130();
else
switch(fun)
{
case 10:fun10();break;
case 11:fun11();break;
case 12:fun12();break;
case 13:fun13();break;
case 14:fun14();break;
default:break;
}
}

}

/*****************************************************/
// 定时器1中断服务程序, 用于数码管的动态扫描
//T1定时器,5ms激发一次,间隔5ms执行一次输出
/*****************************************************/
void timer1() interrupt 3
{
//TR1=0;
//TH1=PWM ;
//处理一行

TH1 = V_TH1;
TL1 = V_TL1;
it1++;
//if( it1==200 )
{
it1=0;
beepT1();
textout();
}
}
/*****************************************************/
//系统初始化
// 函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/
/*****************************************************/
void init(void)
{
//变量初始化
bee=1;
P0 = 0xFF;
P2 = 0xFF;
text_index = 0;

dis_buf[0]=text_code[0];
dis_buf[1]=text_code[0];
dis_buf[2]=text_code[0];
dis_buf[3]=text_code[0];

//定时器初始化/
TMOD=V_TMOD;
TH0=V_TH0; //延时常数
TL0=V_TL0; //延时常数

TH1=PWM; //脉宽调节
TL1=0;

IE = 0x82;
ET0=1; //定时/计数器T0中断允许
ET1=1; //定时/计数器T1中断允许
TR0=1 ; //T0启动
TR1=1 ; //T1启动*/
}

/*****************************************************/
//主程序
//处理按键时加上了按键消抖
/*****************************************************/
void main(void)
{
init(); //系统初始化
while(1);
//连run()都没了
}