导航:首页 > 编程语言 > 89c51单片机时钟程序

89c51单片机时钟程序

发布时间:2023-11-26 21:05:02

❶ 89c51单片机的数字钟程序

/*********************************************
ILONG编做
【注意P3口输出模拟和在{实验板}上不一样。实验板不用取反】
【目的】:用20次T0定时产生1s.进而形成 HH-mm-ss时间
【参数说明】:
40H~47H :显示管,每位暂存器,存放要显示的数码的地址。可根据地址加1,实现该位数加1;
并且低4位可以代表管子要显示的值(42H、45H除外)。
48H :要显示的位值(0~7,由译码器翻译出)
49H :每位每次刷出时要显示的时间0~256us
4A :20次定时,的次数计数器
4BH,4CH :小时十位进位刷0,时,小时两位数的暂存
4DH :调试时,要调整类型,每次INT0中断自增一次
50H~5FH :0~F 16个数的码值
60H :"-"的码值
61H :"空" 的码值
62H,63H :要闪的两位地址暂存 (好像没用着)
R0 :存放 每位暂存器 的地址,用于 刷新位时 移位
00H(位) :是否有INT0(调整)中断
01H(位) :是闪亮,还是闪空,即:闪烁时的亮暗状态
【存在问题】:
1,调整时间时,分钟位开始乱码。
2,调整时间时,必须亮的时候才能调
3,时间差:慢于实际时间
2011.10.21 ilong(crazy night)
*********************************************/
SJMP 0x0030
ORG 0x0030
MAIN:
//启动外部中断
SETB IT0
SETB IE0
SETB EX0
SETB PX0
SETB IT1
SETB IE1
SETB EX1
SETB PX1
SETB EA
CLR 00H //没有调整中断
CLR 01H //闪空
MOV 4DH,#04H //0xFC
MOV P3,#0FH
MOV 62H,46H //从分开始闪
MOV 63H,47H
//十位数********************
MOV 50H,#3FH
MOV 51H,#06H
MOV 52H,#5BH
MOV 53H,#4FH
MOV 54H,#66H
MOV 55H,#6DH
MOV 56H,#7DH
MOV 57H,#07H
MOV 58H,#7FH
MOV 59H,#6FH
MOV 5AH,#77H
MOV 5BH,#7CH
MOV 5CH,#39H
MOV 5DH,#5EH
MOV 5EH,#79H
MOV 5FH,#71H
MOV 60H,#40H
MOV 61H,#00H
//八位管的暂存 从左到右40-47
MOV 40H,#50H
MOV 41H,#50H
MOV 42H,#60H
MOV 43H,#50H
MOV 44H,#50H
MOV 45H,#60H
MOV 46H,#50H
MOV 47H,#50H
MOV 48H,#00H //扫描位暂存
MOV R0,#40H //扫描值地址
MOV 4AH,00H //20次定时 计数
LCALL TIMER_GO20 //开启并初始定时器
//主函数进程,就是扫描码管值并显示,其他为中断操作***************************************************
SCAN: //显示器扫描输出*************************************
MOV P2,48H //选择显示位(从左到右0-7)
MOV A,@R0 //获取该位的数码值 地址
MOV R1,A
MOV A,@R1 //获取该位码值
//CPL A //根据数码管是共阴、共阳 是否取反
MOV P0,A //从P0输出每位的码值,注意:该端口时下面的“清屏”一起改
LCALL DELAY //进入每位延时
MOV P0,#0FFH //清屏
INC 48H //暂存器后移
INC R0 //位后移
MOV A,48H //通过 (48H)的值+08H 判断是否到了 位尾
ADD A,#08H
JB 0D6H,RER //D6H(位)为AC(辅助进位:半进位)。为1时说明(48H)的值+08H=F,即(48H)=8,此时跳向RER
SJMP SCAN
RER: //扫描重置
CLR 0D6H //重置 AC(辅助进位:半进位)
MOV 48H,#00H
MOV R0,#40H
SJMP SCAN
//End 主函数*********************************************************************************************
DELAY: //延时,用于扫描7段管时,在每一位停留的时间.时间太短,回使不该亮的段也有些亮
MOV 49H,#25H //49H的值不可以等于FF,因为FF取反后49H为0,不会延迟了
MOV A,0FEH //用取反设置循环次数,
CPL A
MOV 49H,A
ADD_1:
INC 49H
MOV R1,49H //因为DJNZ判断完后要把判断的地址减去1,所以为了DJNZ不对49H的内容造成影响,把49H的值装到R1中去判断
DJNZ R1,ADD_1
RET
//20次定时*********************************************************************************************************
TIMER_GO20:
//用4AH 设置循环次数*********************************
MOV 4AH,#15H //20(=0x15)次定时
MOV A,4AH //用取反设置定时次数,
CPL A
MOV 4AH,A
SJMP TIMER_S
TIMER_GO5: //与TIMER_GO20类似,只是这里只让定时5次一循环。用于调整闪烁
MOV 4AH,#05H //5(=0x05)次定时
MOV A,4AH //用取反设置定时次数,
CPL A
MOV 4AH,A
TIMER_S://未重置(4AH)的调用,
//设置启动T0
MOV TMOD,#01H //设置模式:T0模式1
MOV TH0,#3CH //T0初值高8位
MOV TL0,#0AH //T0初值低8位
//CLR TF0 //未知问题
SETB ET0 //T0允许中断
SETB EA //CPU允许中断
SETB TR0 //启动T0
RET
T0_INT: //T0中断程序段
CPL P1.7 //测试端口:T0重新定时一次发生一次跳转
LCALL TIMER_S //T0重新定时,继续跑。但:不会初始化20次计数
INC 4AH //T0定时次数加1
MOV A,4AH
JNZ CY_20 //50H加到FF再加就到0了。不为0回去接着执行主程序;为0 则20次定时 溢出即:00H(位)为1
CPL P1.6 //测试端口每秒发生一次跳转
JB 00H,GO_BLINK //如果00H(位)被置1,则不再执行时间系统加1。用于调整时显示闪烁
LCALL CLOCK_GO //时间系统加1秒
LCALL TIMER_GO20 //20次重新开始
SJMP CY_20
GO_BLINK:
LCALL TIMER_GO5 //5次重新开始,
LCALL BLINK
CY_20: RET
//时间系统进位设置*******************************************************************************************
CLOCK_GO:
INC 47H //秒加1
//个位秒 进位 十位
MOV A,#5AH //主要是看"#5A"中的“A”,
SUBB A,47H
JNZ SS_OUT //如果(47H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 47H,#50H
INC 46H
SS_OUT:
//秒 进位 分
MOV A,#56H //
SUBB A,46H
JNZ SM_OUT //如果(46H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 46H,#50H
CLOCK_GO_M:INC 44H
//分调整用
SM_OUT:
//分个位 进位 分
MOV A,#5AH //
SUBB A,44H
JNZ MM_OUT //如果(44H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 44H,#50H
INC 43H
MM_OUT:
//分 进位 时
MOV A,#56H //
SUBB A,43H
JNZ MH_OUT //如果(43H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 43H,#50H
CLOCK_GO_H:INC 41H
//时调整用
MH_OUT:
//时个位 进位 时
MOV A,#5AH //
CLR CY //排除借位影响
SUBB A,41H
JNZ HH_OUT //如果(41H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 41H,#50H
INC 40H
HH_OUT:
//时十位置0
MOV 4BH,40H //为了不影响暂存器数据,把40H、41H转到4BH、4CH中进行 操作
MOV 4CH,41H
MOV A,4BH
SWAP A //获得小时十位数,并放到A的高4位上
ANL A,#0F0H //清0低4位
ANL 4CH,#0FH //小时个位 高4位清0
ADD A,4CH //小时的十位与个位相加(高4位来自小时的十位暂存器40H,低四位来自小时个位的寄存器41H)
SUBB A,#24H
JNZ HD_OUT //如果(46H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 41H,#50H //个位 清零
MOV 40H,#50H //十位清零
HD_OUT:
CG_OUT: RET
//END 时间系统进位设置*******************************************************************************************
//INTO中断程序段*********************************************************************************
INT0_INT:
SETB 00H
CPL P1.5
CPL P1.5
CLR 01H //使得在换位闪烁时不会把上位的数带给下一位,
HMS_BACK: //在每次换位时都要把,被放到暂存上的值那回去,使其显示出来
MOV A,4DH
CJNE A,#02H,BSH_S //back second OR hour _select
LCALL LIGHT_M
SJMP B_END
BSH_S: //恢复秒小时选择
JB CY,B_H
SJMP B_S
B_S: LCALL LIGHT_S //把调好的数据装回暂存器
SJMP B_END
B_H: LCALL LIGHT_H
B_END:
// CLR TR0 //定时器0,停止计时
DEC 4DH //调整类型(时、分、秒)改变
MOV A,4DH
JNZ INT0_OUT //是否恢复时钟
CLR 00H //置0,调整中断(ilong 定义)
CLR 01H
MOV 4DH,#04H //初始化调整类型

INT0_OUT:
RET
////闪烁*****************************************************************
BLINK:
CPL P1.1
CPL 01H
MOV A,4DH
CJNE A,#02H,SH_S
SJMP MM_SET
SH_S: //闪烁秒小时选择
JB CY,HH_SET
SJMP SS_SET
SS_SET: //秒钟设置****************
JB 01H,DACK_S
LIGHT_S:
MOV 46H,4EH
MOV 47H,4FH
SJMP BLINK_OUT
DACK_S:
MOV 4EH,46H
MOV 4FH,47H
MOV 46H,#61H
MOV 47H,#61H
RET
MM_SET: // 分钟设置**************
JB 01H,DACK_M
LIGHT_M:
MOV 43H,4EH
MOV 44H,4FH
SJMP BLINK_OUT
DACK_M:
MOV 4EH,43H
MOV 4FH,44H
MOV 43H,#61H
MOV 44H,#61H
RET
HH_SET: //小时设置****************
JB 01H,DACK_H
LIGHT_H:
MOV 40H,4EH
MOV 41H,4FH
SJMP BLINK_OUT
DACK_H:
MOV 4EH,40H
MOV 4FH,41H
MOV 40H,#61H
MOV 41H,#61H
BLINK_OUT:RET
//INT1中断程序段***************************************************************
INT1_INT:
//lcall HMS_BACK
//clr tr0
CPL P1.4
MOV A,4DH
CJNE A,#02H,ADDSH_S //ADD Hour OR ADD second OR _select
SJMP ADD_M
ADDSH_S: //调整秒小时选择
JB CY,ADD_H
SJMP ADD_S
ADD_S: LCALL CLOCK_GO
SJMP ADD_END
ADD_M: LCALL CLOCK_GO_M
SJMP ADD_END
ADD_H: LCALL CLOCK_GO_H
ADD_END:
// LCALL CLOCK_GO
RET
/*********************************************************************************
最后放中断保险些
*********************************************************************************/
//T0中断程序***************
ORG 000BH
LCALL T0_INT
RETI
//INT0中断*****************
ORG 0003H
LCALL INT0_INT
RETI
//INT1中断*****************
ORG 0013H
LCALL INT1_INT
RETI
END

❷ 用C语言编写AT89C51单片机程序,设计一个智能数字钟。

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char

sbit QB1=P1^0;
sbit QB2=P1^1; //数码管段选
sbit QB3=P1^2;
sbit QB4=P1^3;
sbit QB5=P1^4;
sbit QB6=P1^5;
sbit fm=P1^6; //蜂鸣器
sbit s1=P2^4; //s5按键,切换显示
sbit s2=P2^3; //s2按键,设置调时
sbit s3=P2^2; //s3按键,加1
sbit s4=P2^1; //s4按键,减1

sbit led1=P0^0;
sbit led2=P0^1;
sbit led3=P0^2;

uchar count;
uchar sec,minu,hour,day,week,mon;
uchar n_sec,n_minu,n_hour;
uint year;
uchar set_2=1,set_1=1;
uchar hs,hg,mis,mig,ss,sg;
uchar nhs,nhg,nms,nmg,nss=0,nsg=0;
uchar ms,mg,ds,dg,w;
uchar code table[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,
0X90,0X88,0X83,0XC6,0XA1,0X8E,0X86,0xbf}; //0~F,-,共阳
//uchar code tableyi[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
//0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};//0-F,-,共阴
uchar code table_d[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef}; //0~9数组,带小数点

uchar table1[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; //闰年
uchar table2[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; //非闰年

void delay(uint); //延时函数
void timer0(); //走时中断函数
void jishi(); //计时函数
void key_change(); //切换显示按键函数
void key_set(); //设置时间按键函数
void disp(uchar,uchar,uchar,uchar,uchar,uchar); //显示函数
void zd_clock(); //整点报时函数
void nz_clock(); //闹钟函数
uchar incone(uchar); //加1函数
uchar decone(uchar); //减1函数
void set_time(); //设置时间函数
void set_clock(); //设置闹钟函数
void set_mdw(); //设置月日星期函数

void main() //主函数
{
EA=1;
ET0=1;
TR0=1;
TMOD=0x01;
TH0=0x4c; //50ms初值 晶振11.0592
TL0=0x00;
hour=23;minu=59;sec=49; //赋初值:11点59分0秒
n_hour=12;n_minu=56;n_sec=0; //闹钟赋初值12点1分0秒
year=2008;mon=5;day=14;week=3;//年月日星期赋初值2008年5月11日星期天;祝天下所有母亲节日快乐
while(1)
{
hs=hour/10; //时分秒HH.MM.SS
hg=hour%10;
mis=minu/10;
mig=minu%10;
ss=sec/10;
sg=sec%10;

ms=mon/10; //月日-星期MM.DD.-W
mg=mon%10;
ds=day/10;
dg=day%10;
w=week;

nhs=n_hour/10; //闹钟定时HH.MM.SS
nhg=n_hour%10;
nms=n_minu/10;
nmg=n_minu%10;
nss=n_sec/10;
nsg=n_sec%10;

key_change(); //s4按键扫描
key_set(); //s2按键扫描
set_time(); //设置时间
set_mdw(); //设置月日星期
set_clock(); //设置闹钟
if(set_1==1) //正常走时显示
{
disp(hs,hg,mis,mig,ss,sg);
}
if(set_1==2) //设置时间,LED1闪亮
{
disp(hs,hg,mis,mig,ss,sg);
if(sec%2==0)
{led2=1;led3=1;led1=~led1;}
// else
// {led1=1;}
}
if(set_1==3) //正常显示月日-星期
{
disp(ms,mg,ds,dg,16,w);
}
if(set_1==4) //设置月日-星期,LED2闪亮
{
disp(ms,mg,ds,dg,16,w);
if(sec%2==0)
{led1=1;led3=1;led2=~led2;}

// else
// {led2=1;}
}

if(set_1==5) //正常显示定时
{
disp(nhs,nhg,nms,nmg,nss,nsg);
}
if(set_1==6) //设置闹钟定时,LED3闪亮
{
disp(nhs,nhg,nms,nmg,nss,nsg);
if(sec%2==0)
{led1=1;led2=1;led3=~led3;}

// else
// {led3=1;}
}

zd_clock(); //整点报时
nz_clock(); //闹钟
}

}

void timer0() interrupt 1 //50ms中断函数

{
TMOD=0x01;
TH0=0x4c; //50ms初值 晶振11.0592
TL0=0x00;
count++;
if(count==20)
{
count=0;
sec++;
jishi(); //调计时函数
}
}

void jishi() //计时函数
{
if(sec==60)
{
sec=0;
minu++;
if(minu==60)
{
minu=0;
hour++;
if(hour==24)
{ hour=0;
day++;
week++;
if(week==8)
{week=0;}
if(year%4==0&&year%100!=0||year%400==0) //闰年
{
if(day==table1[mon]+1)
{
day=0;
mon++;
if(mon==13)
{mon=0;year++;}
}
}
else //非闰年
{
if(day==table2[mon]+1)
{
day=0;
mon++;
if(mon==13)
{mon=0;year++;}
}
}

}
}
}
}

void key_change() //s1按键扫描
{
if(s1==0)
{
delay(200);
if(s1==0)
{
set_1++;
while(!s1);
if(set_1==7)
{set_1=1;}
}
}
}

void key_set() //s2按键扫描
{
if(s2==0)
{
delay(10);
if(s2==0)
{
set_2++;
while(!s2);
if(set_2==4)
{set_2=1;}
}
}
}
void disp(uchar a1,uchar a2,uchar a3,uchar a4,uchar a5,uchar a6) //显示函数
{
QB1=1;
QB2=0;
QB3=0;
QB4=0;
QB5=0;
QB6=0;
P3=table[a1]; //段码送P0口
delay(10); //延时一小会
QB1=0;
QB2=1;
QB3=0;
QB4=0;
QB5=0;
QB6=0;
P3=table[a2]; //第2个数码管显示,带小数点
delay(10);
QB1=0;
QB2=0;
QB3=1;
QB4=0;
QB5=0;
QB6=0;

P3=table[a3]; //第3个数码管显示
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=1;
QB5=0;
QB6=0;

P3=table[a4]; //第4个数码管显示,带小数点
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=0;
QB5=1;
QB6=0;

//第5个数码管显示
P3=table[a5];
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=0;
QB5=0;
QB6=1;

P3=table[a6]; //第6个数码管显示
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=0;
QB5=0;
QB6=0;

}

void zd_clock() //整点报时函数
{
if(minu==59&&(sec==53||sec==55||sec==57))
{
fm=0;
delay(5);
fm=1;
delay(5);
}
fm=0;
if(minu==59&&sec==59)
{
fm=0;
delay(5);
fm=1;
delay(5);
fm=0;
}
}

void nz_clock() //闹钟函数
{
if(hour==n_hour&&minu==n_minu&&sec==n_sec)
//if((sec%2==0)&&sec<30)
{
fm=0;
delay(1);
fm=1;
delay(1);
}
}

void set_time() //设置时间函数
{
if(set_1==2)
{
if(set_2==1)
{
hour=incone(hour);
if(hour==24)
{hour=0;}
// if(hour<0)
// {hour=23;}
hour=decone(hour);

}
if(set_2==2)
{
minu=incone(minu);
if(minu==60)
{minu=0;}
// if(minu<0)
// {minu=59;}
minu=decone(minu);

}
}
}

void set_mdw() //设置月日星期函数
{
if(set_1==4)
{
if(set_2==1)
{
mon=incone(mon);
if(mon==13)
{mon=1;}
mon=decone(mon);
// if(mon==0)
// {mon=12;}
}
if(set_2==2)
{
day=incone(day);
if(day==32)
{day=0;}
day=decone(day);
// if(day==0)
// {day=0;}
}
if(set_2==3)
{
week=incone(week);
if(week==8)
{week=0;}
week=decone(week);
// if(week==0)
// {week=7;}
}
}
}

void set_clock() //设置闹钟函数
{
if(set_1==6)
{
if(set_2==1)
{
n_hour=incone(n_hour);
if(n_hour==24)
{n_hour=0;}
n_hour=decone(n_hour);
if(n_hour==0)
{n_hour=0;}
}
if(set_2==2)
{
n_minu=incone(n_minu);
if(n_minu==60)
{n_minu=0;}
n_minu=decone(n_minu);
if(n_minu==0)
{n_minu=0;}
}
}

}

uchar incone(uchar n) //加1函数
{
if(s3==0)
{ delay(200);
if(s3==0)
{
n++;
while(!s3);
}
}
return(n);
}

uchar decone(uchar m) //减1函数
{
if(s4==0)
{
delay(200);
if(s4==0)
{
m--;
while(!s4);
if(m<0)
{m=0;}
}
}
return(m);
}

void delay(uint k) //延时函数
{
uint i,j;
for(i=k;i>0;i--)
for(j=80;j>0;j--);
}

阅读全文

与89c51单片机时钟程序相关的资料

热点内容
中间夹菜单里面不能显示压缩文件 浏览:952
如何指导小学生参加编程比赛 浏览:275
物业的招标文件有哪些 浏览:452
保存游戏文件名非法或只读 浏览:258
js怎么做图片时钟 浏览:451
华为应用里面有了app说明什么 浏览:801
数据库中xy是什么意思 浏览:893
u盘打不开提示找不到应用程序 浏览:609
网站功能介绍怎么写 浏览:954
word在试图打开文件时错误 浏览:108
主板无vga插槽怎么连接编程器 浏览:521
录视频文件在哪里删除 浏览:881
word2013如何插入文件 浏览:233
proe教程百度网盘 浏览:197
如何控制远程linux服务器 浏览:740
it教学app有哪些 浏览:34
怎么在ps抠的图变成矢量文件 浏览:405
口袋妖怪银魂安卓v11 浏览:1
网站上芒果tv的账号都是什么 浏览:104
带公式的表格如何刷新数据 浏览:81

友情链接