① 基于单片机的数字时钟怎么做
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit la=P2^6;
sbit wela=P2^7;
sbit rs=P3^5;
sbit lcden=P3^4;
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
sbit rd=P3^7;
uchar count,s1num;
char miao,shi,fen;
uchar code table[]=" 2007-7-30 MON";
uchar code table1[]=" 00:00:00";
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{
rs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
uchar num;
la=0;
wela=0;
lcden=0;
// fen=59;
// miao=53;
// shi=23;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<12;num++)
{
write_date(table1[num]);
delay(5);
}
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void write_sfm(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void keyscan()
{
rd=0;
if(s1==0)
{
delay(5);
if(s1==0)
{ s1num++;
while(!s1);
if(s1num==1)
{
TR0=0;
write_com(0x80+0x40+10);
write_com(0x0f);
}
}
if(s1num==2)
{
write_com(0x80+0x40+7);
}
if(s1num==3)
{
write_com(0x80+0x40+4);
}
if(s1num==4)
{
s1num=0;
write_com(0x0c);
TR0=1;
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
if(s1num==1)
{
miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi++;
if(shi==24)
shi=0;
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
if(s1num==1)
{
/* if(miao==0)
{
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}*/
miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
}
}
void main()
{
init();
while(1)
{
keyscan();
}
// while(1);
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==18)
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
write_sfm(4,shi);
}
write_sfm(7,fen);
}
write_sfm(10,miao);
}
}
这个是数字时钟的源程序,用12864夜晶显示。
② 利用单片机(STC89C52)设计倒计时数字钟
#include<reg51.h>
#define uchar unsigned char
uchar code ledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//0-9
unsigned char sec=0,min=0,hour=24,scanled;
unsigned char key,mode,time;
unsigned char disdat[8];
unsigned char alarm[3]={23,59,0},dly;
sbit keyhu=P1^0;
sbit keyhd=P1^1;
sbit keymu=P1^2;
sbit keymd=P1^3;
sbit keysu=P1^4;
sbit keysd=P1^5;
sbit keyst=P1^6;
sbit fmq=P3^0;
bit flag=0;
void delay(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<120;j++);
}
void dischg()
{
disdat[0]=sec%10;
disdat[1]=sec/10;
disdat[2]=min%10;
disdat[3]=min/10;
disdat[4]=hour%10;
disdat[5]=hour/10;
}
void t0isr() interrupt 1//秒计时
{
TH0=0x3c;
TL0=0xb0;
time++;
switch(mode)
{
case 0:
if(time==20)
{
time=0;
sec++;
if(sec>59)
{
sec=0;
min++;
if(min>59)
{
min=0;
hour++;
if(hour>23)hour=0;
}
}
}
break;
case 1:
if(time==20)
{
time=0;
if(sec>0 && flag==0)sec--;
else if(min>0 && flag==0){sec=59;min--;}
else if(hour>0 && flag==0){sec=59;min=59;hour--;}
if((hour == alarm[0]) && (min == alarm[1]) && (sec == alarm[2])){fmq=1;flag=1;dly++;}
}
break;
}
if(dly>=2){fmq=0;flag=0;TR0=0;dly=0;}
dischg();
}
void t1isr() interrupt 3//显示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case 0:
P2=0x20;
P0=~ledtab[disdat[5]];
break;
case 1:
P2=0x10;
P0=~ledtab[disdat[4]]&0x7f;
break;
case 2:
P2=0x08;
P0=~ledtab[disdat[3]];
break;
case 3:
P2=0x04;
P0=~ledtab[disdat[2]]&0x7f;
break;
case 4:
P2=0x02;
P0=~ledtab[disdat[1]];
break;
case 5:
P2=0x01;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
TR1=1;
TR0=0;
ET0=1;
ET1=1;
EA=1;
fmq=0;
scanled=0;
time=0;
mode=1;
dischg();
while(1)
{
if(keyhu==0)
{
while(keyhu==0);
TR0=0;
hour++;
hour%=24;
}
if(keyhd==0)
{
while(keyhd==0);
TR0=0;
if(hour>0)hour--;
if(hour==0)hour=23;
}
if(keymu==0)
{
while(keymu==0);
TR0=0;
min++;
min%=60;
}
if(keymd==0)
{
while(keymd==0);
TR0=0;
if(min>0)min--;
if(min==0)min=59;
}
if(keysu==0)
{
while(keysu==0);
TR0=0;
sec++;
sec%=60;
}
if(keysd==0)
{
while(keysd==0);
TR0=0;
if(sec>0)sec--;
if(sec==0)sec=59;
}
if(keyst==0)
{
while(keyst==0);
TR0=~TR0;
}
dischg();
}
}
③ 求单片机数字钟的设计程序及电路仿真图!急!急!急!急!
呵呵呵,你走运了,我做过课后作业,有问题以再问我
带调时间的数字钟
定时器1s触发中断一次,计时+1,主程序负责传输时间到led及检测按键,其他见注释。
左面有器件列表,这个是protenus仿真
ORG 0000H
AJMP MAIN
ORG 000BH
LJMP T0INT
ORG 001BH
LJMP T1INT
ORG 0100H
MAIN: MOV TMOD,#51H ;T0定时器方式1,T1计数器方式1
MOV TCON,#54H ;开定时计数器,T1边沿触发
MOV TH0,#4BH ;(65536-19453)*1.085=50MS,晶振11.0592MHZ
MOV TL0,#0FFH ;去掉了装载亩扰初值用的机器周期
MOV TH1,#0FFH ;满10溢出,1S
MOV TL1,#0F6H
MOV IE,#8AH ;开中断
MOV R7,#04H ;预置13:58:00 的时
MOV R2,#13H
MOV A,R2
LCALL DISPLAY
MOV R7,#02H ;预置13:58:00 的分
MOV R1,#58H
MOV A,R1
LCALL DISPLAY
CHECKKEY:LCALL KEY1
LCALL KEY2
LCALL KEY3
LCALL KEY4
AJMP CHECKKEY
;;;;;;;;;;中断;;;;;;;;;;;;;;;;;;;;;;
T0INT: MOV TH0,#4BH
MOV TL0,#0FDH
CPL P2.0
RETI
T1INT: MOV TH1,#0FFH
MOV TL1,#0F6H
PUSH ACC
CPL P2.1
MOV A,R0 ;R0计秒钟,通过A调整为BCD码
ADD A,#1
DA A
MOV R0,A
CJNE R0,#60H,MIAO
MOV R0,#00H
MOV A,R1 ;R1计分钟,通过A调整为BCD码
ADD A,#1
DA A
MOV R1,A
CJNE R1,#60H,FEN
MOV R1,#00H
MOV A,R2 ;R2计时钟,通过A调整为BCD码
ADD A,#1
DA A
MOV R2,A
CJNE R2,#24H,SHI
MOV R2,#00H
SHI: MOV R7,#04H
MOV A,R2
LCALL DISPLAY
FEN: MOV R7,#02H
MOV A,R1
LCALL DISPLAY
MIAO: MOV R7,#01H
MOV A,R0
LCALL DISPLAY
POP ACC
RETI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;显示
;A--显示BCD码,R7--选择数码管
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DISPLAY:MOV P1,R7
MOV SCON,#0
MOV SBUF,A
JNB TI,$
CLR TI
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;按键检测与执行程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
KEY1: JB P0.0,DONE1 ;检测P0.0口按键,若没按下,则结束
LCALL DELAY ;延时去抖
JB P0.0,DONE1 ;再次检测,若没按下,则结束
JNB P0.0,$ ;等待按键松开
CPL EA ;开关定时中断
DONE1: RET
KEY2: JB EA,DONE2 ;若EA=1,则调时间按键无效
JB P0.1,DONE2 ;检测P0.0口按键,枣敬若没按下凳耐慎,则结束
LCALL DELAY ;延时去抖
JB P0.1,DONE2 ;再次检测,若没按下,则结束
MOV A,R2 ;R2计时钟+1,通过A调整为BCD码
ADD A,#1
DA A
CJNE A,#24H,CHECK2
MOV A,#00H
CHECK2: MOV R2,A
MOV R7,#04H ;显示改后的时间
MOV A,R2
LCALL DISPLAY
DONE2: RET
KEY3: JB EA,DONE3
JB P0.2,DONE3
LCALL DELAY
JB P0.2,DONE3
MOV A,R1 ;R1计分钟+1,通过A调整为BCD码
ADD A,#1
DA A
CJNE A,#60H,CHECK3
MOV A,#00H
CHECK3: MOV R1,A
MOV R7,#02H ;显示改后的时间
MOV A,R1
LCALL DISPLAY
DONE3: RET
KEY4: JB EA,DONE4
JB P0.3,DONE4
LCALL DELAY
JB P0.3,DONE4
MOV A,R0 ;R0计秒钟+1,通过A调整为BCD码
ADD A,#1
DA A
CJNE A,#60H,CHECK4
MOV A,#00H
CHECK4: MOV R0,A
MOV R7,#01H ;显示改后的时间
MOV A,R0
LCALL DISPLAY
DONE4: RET
;;;;;;;;DELAY;;;;;;;;;;;;;;;;;;
DELAY: MOV R4,#0FFH
DL: MOV R5,#0FFH
DJNZ R5,$
DJNZ R4,DL
RET
④ 51单片机做数字电子钟
这么复杂的东西给这么少分 晕死了 你也太小气了吧,分多的话还可能帮你动动脑
⑤ 基于单片机的数字时钟设计方案
数字钟〔★〕这里用了两种编租肆写方法(即汇编语言与C语言)
(1. 开机时,显示12:00:00的时间开始计时;
(2. P0.0/AD0控制“秒”的调整,每按一次加1秒;
(3. P0.1/AD1控制“分”的调整,每按一次加1分;
(4. P0.2/AD2控制“时”的调整,每按一次加1个小时;
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的P1.0-P1.7端口用8芯排线连接到“动态数码显示”区域中的A-H端口上;
(2. 把“单片机系统:区域中的P3.0-P3.7端口用8芯排线连接到“动态数码显示”区域中的S1-S8端口上;
(3. 把“单片陵型碧机系统”区域中的P0.0/AD0、P0.1/AD1、P0.2/AD2端口分别用导线连接到“独立式键盘”区域中尺举的SP3、SP2、SP1端口上;
4. 相关基本知识
(1. 动态数码显示的方法
(2. 独立式按键识别过程
(3. “时”,“分”,“秒”数据送出显示处理方法
5. 程序框图
6. 汇编源程序
SECOND EQU 30H
MINITE EQU 31H
HOUR EQU 32H
HOURK BIT P0.0
MINITEK BIT P0.1
SECONDK BIT P0.2
DISPBUF EQU 40H
DISPBIT EQU 48H
T2SCNTA EQU 49H
T2SCNTB EQU 4AH
TEMP EQU 4BH
ORG 00H
LJMP START
ORG 0BH
LJMP INT_T0
START: MOV SECOND,#00H
MOV MINITE,#00H
MOV HOUR,#12
MOV DISPBIT,#00H
MOV T2SCNTA,#00H
MOV T2SCNTB,#00H
MOV TEMP,#0FEH
LCALL DISP
MOV TMOD,#01H
MOV TH0,#(65536-2000) / 256
MOV TL0,#(65536-2000) MOD 256
SETB TR0
SETB ET0
SETB EA
WT: JB SECONDK,NK1
LCALL DELY10MS
JB SECONDK,NK1
INC SECOND
MOV A,SECOND
CJNE A,#60,NS60
MOV SECOND,#00H
NS60: LCALL DISP
JNB SECONDK,$
NK1: JB MINITEK,NK2
LCALL DELY10MS
JB MINITEK,NK2
INC MINITE
MOV A,MINITE
CJNE A,#60,NM60
MOV MINITE,#00H
NM60: LCALL DISP
JNB MINITEK,$
NK2: JB HOURK,NK3
LCALL DELY10MS
JB HOURK,NK3
INC HOUR
MOV A,HOUR
CJNE A,#24,NH24
MOV HOUR,#00H
NH24: LCALL DISP
JNB HOURK,$
NK3: LJMP WT
DELY10MS:
MOV R6,#10
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
DISP:
MOV A,#DISPBUF
ADD A,#8
DEC A
MOV R1,A
MOV A,HOUR
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
MOV A,#10
MOV @R1,A
DEC R1
MOV A,MINITE
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
MOV A,#10
MOV @R1,A
DEC R1
MOV A,SECOND
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
RET
INT_T0:
MOV TH0,#(65536-2000) / 256
MOV TL0,#(65536-2000) MOD 256
MOV A,#DISPBUF
ADD A,DISPBIT
MOV R0,A
MOV A,@R0
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P1,A
MOV A,DISPBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P3,A
INC DISPBIT
MOV A,DISPBIT
CJNE A,#08H,KNA
MOV DISPBIT,#00H
KNA: INC T2SCNTA
MOV A,T2SCNTA
CJNE A,#100,DONE
MOV T2SCNTA,#00H
INC T2SCNTB
MOV A,T2SCNTB
CJNE A,#05H,DONE
MOV T2SCNTB,#00H
INC SECOND
MOV A,SECOND
CJNE A,#60,NEXT
MOV SECOND,#00H
INC MINITE
MOV A,MINITE
CJNE A,#60,NEXT
MOV MINITE,#00H
INC HOUR
MOV A,HOUR
CJNE A,#24,NEXT
MOV HOUR,#00H
NEXT: LCALL DISP
DONE: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H
TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
END
7. C语言源程序
#include <AT89X51.H>
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
unsigned char dispbitcode[]={0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f};
unsigned char dispbuf[8]={0,0,16,0,0,16,0,0};
unsigned char dispbitcnt;
unsigned char second;
unsigned char minite;
unsigned char hour;
unsigned int tcnt;
unsigned char mstcnt;
unsigned char i,j;
void main(void)
{
TMOD=0x02;
TH0=0x06;
TL0=0x06;
TR0=1;
ET0=1;
EA=1;
while(1)
{
if(P0_0==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_0==0)
{
second++;
if(second==60)
{
second=0;
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
while(P0_0==0);
}
}
if(P0_1==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_1==0)
{
minite++;
if(minite==60)
{
minite=0;
}
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
while(P0_1==0);
}
}
if(P0_2==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_2==0)
{
hour++;
if(hour==24)
{
hour=0;
}
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
while(P0_2==0);
}
}
}
}
void t0(void) interrupt 1 using 0
{
mstcnt++;
if(mstcnt==8)
{
mstcnt=0;
P1=dispcode[dispbuf[dispbitcnt]];
P3=dispbitcode[dispbitcnt];
dispbitcnt++;
if(dispbitcnt==8)
{
dispbitcnt=0;
}
}
tcnt++;
if(tcnt==4000)
{
tcnt=0;
second++;
if(second==60)
{
second=0;
minite++;
if(minite==60)
{
minite=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
}
⑥ 单片机课程设计(数字时钟) 麻烦大家不要发链接 直接帮我把程序写过来。
哈哈有个1602显示的不过程序太长贴不上给你个数码管的吧不行再联系
1302.c
#include<DS1302.h>
#include<key.h>
ucharbit_ser[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
ucharseven_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
/***********************时间显示*****************/
voidtimer0_init(void) //T0初始化函数,用于时间的动态显示
{
TMOD=0x21;
TL0=(65536-5000)%256;
TH0=(65536-5000)/256;
EA=1;
ET0=1;
TR0=1;
}
voidtimer0_isr(void)interrupt1 //T0中断处理函数
{
charflag; //flag用于表示调整时闪烁的亮或灭
TR0=0;
TL0=(65536-5000)%256;
TH0=(65536-5000)/256;
TR0=1;
flag=x/100*0xff; //设置闪烁标志,如果x大于100则flag为0xff,小于100则为0x00
x++;
if(x>200)
x=0;
switch(i)
{
case0:
P2=bit_ser[0];
if(setflag==3) //根据setflag的值判断当前位是否需要闪烁
P0=flag|seven_seg[dis_buffer[0]];
else
P0=seven_seg[dis_buffer[0]];
break;
case1:
P2=bit_ser[1];
if(setflag==3)
P0=flag|seven_seg[dis_buffer[1]];
else
P0=seven_seg[dis_buffer[1]];
break;
case2:
P2=bit_ser[2];
if(setflag==2)
P0=flag|seven_seg[dis_buffer[2]];
else
P0=seven_seg[dis_buffer[2]];
break;
case3:
P2=bit_ser[3];
if(setflag==2)
P0=flag|seven_seg[dis_buffer[3]];
else
P0=seven_seg[dis_buffer[3]];
break;
case4:
P2=bit_ser[4];
if(setflag==1)
P0=flag|seven_seg[dis_buffer[4]];
else
P0=seven_seg[dis_buffer[4]];
break;
case5:
P2=bit_ser[5];
if(setflag==1)
P0=flag|seven_seg[dis_buffer[5]];
else
P0=seven_seg[dis_buffer[5]];
break;
}
i++;
if(i>=6)
{
i=0;
if(j==10)
{
j=0;
if(setflag==0)
DS1302_GetTime(&Time); //如果setflag是0,就从1302中读出时间,因为setflag不是0时,说明处于调整状态,不需要读时间
dis_buffer[5]=Time.Second%10; //把当前时间放入显示缓冲区
dis_buffer[4]=Time.Second/10;
dis_buffer[3]=Time.Minute%10;
dis_buffer[2]=Time.Minute/10;
dis_buffer[1]=Time.Hour%10;
dis_buffer[0]=Time.Hour/10;
}
j++;
}
}
voidmain()
{
Initial_DS1302(Time);
timer0_init();
while(1)
{
set_down();
timer_down();
up_down();
down_down();
beepflag_down();
if(setflag==0&&Time.Hour==romhour&&Time.Minute==romminute&&Beepflag==1) //判断蜂鸣器是否要响
Beep=!Beep;
}
}
//key.c
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
uchari=0,j=0,x=0,setflag,flag_set,flag_timer;//setflag用来表示调整的位置,flag_set和flag_timer分别表示当前处于调整状态还是定时状态
SYSTEMTIMETime={0,20,15,3,30,6,10}; //系统时间的初始值2010年6月30日星期三,15时20分0秒
chardis_buffer[6]; //存放显示数据的缓冲区
sbitBeep_flag=P3^2; //蜂鸣器的接口
sbitkey_timer=P3^4; //定时按钮
sbitkey_set=P3^5; //调整按钮
sbitkey_up=P3^6; //增加按钮
sbitkey_down=P3^7; //减小按钮
charromhour,romminute,romsec; //分别存放定时的时,分,秒
bitBeepflag; //标记闹钟是否开启
//延时函数
voiddelays(ucharx)
{
while(x)x--;
}
//设置键的处理函数
voidset()
{
setflag++;
flag_set=1;
if(setflag>=4)
{
setflag=0;
flag_set=0;
Initial_DS1302(Time);
}
}
//定时间的处理函数
voidtimer()
{
setflag++;
flag_timer=1;
if(setflag==1)
{
Time.Hour=romhour;
Time.Minute=romminute;
Time.Second=romsec;
}
elseif(setflag>=4)
{
setflag=0;
flag_timer=0;
romhour=Time.Hour;
romminute=Time.Minute;
romsec=Time.Second;
}
}
//增加键的处理函数
voip()
{
switch(setflag)
{
case0:
break;
case1:
Time.Second++;
if(Time.Second>=60)
Time.Second=0;
break;
case2:
Time.Minute++;
if(Time.Minute>=60)
Time.Minute=0;
break;
case3:
Time.Hour++;
if(Time.Hour>=24)
Time.Hour=0;
break;
}
}
//减小键的处理函数
voiddown()
{
switch(setflag)
{
case0:
break;
case1:
Time.Second--;
if(Time.Second<0)
Time.Second=59;
break;
case2:
Time.Minute--;
if(Time.Minute<0)
Time.Minute=59;
break;
case3:
Time.Hour--;
if(Time.Hour<0)
Time.Hour=23;
break;
}
}
//设置键的扫描函数
voidset_down()
{
if(key_set==0&&flag_timer==0)
{
delays(100);
if(key_set==0)
{
set();
}
while(!key_set);
}
}
//定时键的扫描函数
voidtimer_down()
{
if(key_timer==0&&flag_set==0)
{
delays(100);
if(key_timer==0)
{
timer();
}
while(!key_timer);
}
}
//增加键的扫描函数
voip_down()
{
if(key_up==0&&setflag!=0)
{
delays(100);
if(key_up==0)
{
up();
while(!key_up);
}
}
}
//减少键的处理函数
voiddown_down()
{
if(key_down==0&&setflag!=0)
{
delays(100);
if(key_down==0)
{
down();
while(!key_down);
}
}
}
//定时开关的扫描处理函数
voidbeepflag_down()
{
if(Beep_flag==0)
{
delays(100);
{
Beepflag=!Beepflag;
while(!Beep_flag);
}
}
}
//ds1302.h
#ifndef_REAL_TIMER_DS1302
#define_REAL_TIMER_DS1302
#include<REG51.h>
sbitDS1302_CLK=P1^1;//实时时钟时钟线引脚
sbitDS1302_IO=P1^2;//实时时钟数据线引脚
sbitDS1302_RST=P1^3;//实时时钟复位线引脚
sbitACC0=ACC^0;
sbitACC7=ACC^7;
sbitBeep=P2^7;
typedefstruct__SYSTEMTIME__
{ charSecond;
charMinute;
charHour;
charWeek;
charDay;
charMonth;
charYear;
}SYSTEMTIME; //定义的时间类型
#defineAM(X) X
#definePM(X) (X+12) //转成24小时制
#defineDS1302_SECOND 0x80//秒寄存器
#defineDS1302_MINUTE 0x82//分寄存器
#defineDS1302_HOUR 0x84
#defineDS1302_WEEK 0x8A
#defineDS1302_DAY 0x86
#defineDS1302_MONTH 0x88
#defineDS1302_YEAR 0x8C
#defineDS1302_RAM(X) (0xC0+(X)*2) //用于计算DS1302_RAM地址的宏
voidDS1302InputByte(unsignedchard) //实时时钟写入一字节(内部函数)
{unsignedchari;
ACC=d;
for(i=8;i>0;i--)
{ DS1302_IO=ACC0; //相当于汇编中的RRC
DS1302_CLK=1;
DS1302_CLK=0;//发一个高跳变到低的脉冲
ACC=ACC>>1;
}
}
unsignedcharDS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{ unsignedchari;
for(i=8;i>0;i--)
{ ACC=ACC>>1; //相当于汇编中的RRC
ACC7=DS1302_IO;
DS1302_CLK=1;
DS1302_CLK=0;//发一个高跳变到低的脉冲
}
return(ACC);
}
voidWrite1302(unsignedcharucAddr,unsignedcharucDa)//ucAddr:DS1302地址,ucData:要写的数据
{ DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr); //地址,命令
DS1302InputByte(ucDa); //写1Byte数据
DS1302_CLK=1;
DS1302_RST=0;//RST0->1->0,CLK0->1
}
unsignedcharRead1302(unsignedcharucAddr) //读取DS1302某地址的数据
{ unsignedcharucData;
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;//enable
DS1302InputByte(ucAddr|0x01);//地址,命令
ucData=DS1302OutputByte();//读1Byte数据
DS1302_CLK=1;//RST0->1->0,CLK0->1
DS1302_RST=0;
return(ucData);
}
voidDS1302_SetProtect(bitflag)//是否写保护
{ if(flag)
Write1302(0x8E,0x80);//WP=1,不能写入
else
Write1302(0x8E,0x00);//WP=0,可以写入
}
voidDS1302_SetTime(unsignedcharAddress,unsignedcharValue)//设置时间函数
{ DS1302_SetProtect(0);
Write1302(Address,((Value/10)<<4|(Value%10)));//高4位为十位,低4位为个位
DS1302_SetProtect(1);
}
//获取时间函数,从DS1302内读取时间然后存入Time内
voidDS1302_GetTime(SYSTEMTIME*Time)
{ unsignedcharReadValue;
ReadValue=Read1302(DS1302_SECOND);
Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//转换成10进制的秒
ReadValue=Read1302(DS1302_MINUTE);
Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_HOUR);
Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_DAY);
Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_WEEK);
Time->Week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_MONTH);
Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_YEAR);
Time->Year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
}
//利用STime初始化DS1302
voidInitial_DS1302(SYSTEMTIMESTime)
{ unsignedcharSecond=Read1302(DS1302_SECOND);
if(Second&0x80) DS1302_SetTime(DS1302_SECOND,0);//如果第七为1(表明没有启动),则启动时钟
DS1302_SetTime(DS1302_SECOND,STime.Second); //设定起始时间
DS1302_SetTime(DS1302_MINUTE,STime.Minute);
DS1302_SetTime(DS1302_HOUR,STime.Hour);
DS1302_SetTime(DS1302_DAY,STime.Day);
DS1302_SetTime(DS1302_MONTH,STime.Month);
DS1302_SetTime(DS1302_YEAR,STime.Year);
DS1302_SetTime(DS1302_WEEK,STime.Week);
}
#endif
⑦ 用单片机设计一个数字时钟
#include <REG51.H>#include <intrins.h> #define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚 sbit DS1302_IO = P1^6; //实时时钟数据线引脚 sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit wireless_1 = P3^0;sbit wireless_2 = P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3; //无线控制sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbit Down = P2^2; //减法按钮sbit out = P2^3; //立刻跳出调整模式按钮sbit DQ = P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value; //温度值uchar TempBuffer[5],week_value[2]; void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///Port Definitions**********************************************************sbit LcdRs = P2^5;sbit LcdRw = P2^6;sbit LcdEn = P2^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口 //内部等待函数**************************************************************************unsigned char LCD_Wait(void){ LcdRs=0; LcdRw=1; _nop_(); LcdEn=1; _nop_(); LcdEn=0; return DBPort; }//向LCD写入命令或数据************************************************************#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input){ LcdEn=0; LcdRs=style; LcdRw=0; _nop_(); DBPort=input; _nop_();//注意顺序 LcdEn=1; _nop_();//注意顺序 LcdEn=0; _nop_(); LCD_Wait(); } //设置显示模式************************************************************#define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关 #define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标 #define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动 void LCD_SetDisplay(unsigned char DisplayMode){ LCD_Write(LCD_COMMAND, 0x08|DisplayMode); } //设置输入模式************************************************************#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default #define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //default void LCD_SetInput(unsigned char InputMode){ LCD_Write(LCD_COMMAND, 0x04|InputMode);} //初始化LCD************************************void LCD_Initial(){ LcdEn=0; LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵 LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标 LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏 LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动} //液晶字符输入的位置************************void GotoXY(unsigned char x, unsigned char y){ if(y==0) LCD_Write(LCD_COMMAND,0x80|x); if(y==1) LCD_Write(LCD_COMMAND,0x80|(x-0x40));} //将字符输出到液晶显示void Print(unsigned char *str){ while(*str!='\0') { LCD_Write(LCD_DATA,*str); str++; }} /***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{ unsigned char Second; unsigned char Minute; unsigned char Hour; unsigned char Week; unsigned char Day; unsigned char Month; unsigned char Year; unsigned char DateString[11]; unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型SYSTEMTIME CurrentTime; #define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84 #define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数){ unsigned char i; ACC = d; for(i=8; i>0; i--) { DS1302_IO = ACC0; //相当于汇编中的 RRC DS1302_CLK = 1; DS1302_CLK = 0; ACC = ACC >> 1; } } unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数){ unsigned char i; for(i=8; i>0; i--) { ACC = ACC >>1; //相当于汇编中的 RRC ACC7 = DS1302_IO; DS1302_CLK = 1; DS1302_CLK = 0; } return(ACC); } void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{ DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr); // 地址,命令 DS1302InputByte(ucDa); // 写1Byte数据 DS1302_CLK = 1; DS1302_RST = 0;} unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{ unsigned char ucData; DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr|0x01); // 地址,命令 ucData = DS1302OutputByte(); // 读1Byte数据 DS1302_CLK = 1; DS1302_RST = 0; return(ucData);} void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组{ unsigned char ReadValue; ReadValue = Read1302(DS1302_SECOND); Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_MINUTE); Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_HOUR); Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_DAY); Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_WEEK); Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_MONTH); Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_YEAR); Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); } void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22 { Time->DateString[0] = '2'; Time->DateString[1] = '0'; Time->DateString[2] = Time->Year/10 + '0'; Time->DateString[3] = Time->Year%10 + '0'; } else { Time->DateString[0] = ' '; Time->DateString[1] = ' '; Time->DateString[2] = ' '; Time->DateString[3] = ' '; } Time->DateString[4] = '/'; if(hide_month<2) { Time->DateString[5] = Time->Month/10 + '0'; Time->DateString[6] = Time->Month%10 + '0'; } else { Time->DateString[5] = ' '; Time->DateString[6] = ' '; } Time->DateString[7] = '/'; if(hide_day<2) { Time->DateString[8] = Time->Day/10 + '0'; Time->DateString[9] = Time->Day%10 + '0'; } else { Time->DateString[8] = ' '; Time->DateString[9] = ' '; } if(hide_week<2) { week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示 } else { week_value[0] = ' '; } week_value[1] = '\0'; Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符} void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2) { Time->TimeString[0] = Time->Hour/10 + '0'; Time->TimeString[1] = Time->Hour%10 + '0'; } else { Time->TimeString[0] = ' '; Time->TimeString[1] = ' '; } Time->TimeString[2] = ':'; if(hide_min<2) { Time->TimeString[3] = Time->Minute/10 + '0'; Time->TimeString[4] = Time->Minute%10 + '0'; } else { Time->TimeString[3] = ' '; Time->TimeString[4] = ' '; } Time->TimeString[5] = ':'; if(hide_sec<2) { Time->TimeString[6] = Time->Second/10 + '0'; Time->TimeString[7] = Time->Second%10 + '0'; } else { Time->TimeString[6] = ' '; Time->TimeString[7] = ' '; } Time->DateString[8] = '\0';} void Initial_DS1302(void) //时钟芯片初始化{ unsigned char Second=Read1302(DS1302_SECOND); if(Second&0x80) //判断时钟芯片是否关闭 { Write1302(0x8e,0x00); //写入允许 Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55 Write1302(0x88,0x07); Write1302(0x86,0x25); Write1302(0x8a,0x07); Write1302(0x84,0x23); Write1302(0x82,0x59); Write1302(0x80,0x55); Write1302(0x8e,0x80); //禁止写入 } } /***********ds18b20子程序*************************/ /***********ds18b20延迟子函数(晶振12MHz )*******/ void delay_18B20(unsigned int i){ while(i--);} /**********ds18b20初始化函数**********************/ void Init_DS18B20(void) { unsigned char x=0; DQ = 1; //DQ复位 delay_18B20(8); //稍做延时 DQ = 0; //单片机将DQ拉低 delay_18B20(80); //精确延时 大于 480us DQ = 1; //拉高总线 delay_18B20(14); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay_18B20(20);} /***********ds18b20读一个字节**************/ unsigned char ReadOneChar(void){ uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 0; // 给脉冲信号 dat>>=1; DQ = 1; // 给脉冲信号 if(DQ) dat|=0x80; delay_18B20(4); } return(dat);} /*************ds18b20写一个字节****************/ void WriteOneChar(uchar dat){ unsigned char i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01; delay_18B20(5); DQ = 1; dat>>=1; }} /**************读取ds18b20当前温度************/ void ReadTemp(void){ unsigned char a=0; unsigned char b=0; unsigned char t=0; Init_DS18B20(); WriteOneChar(0xCC); // 跳过读序号列号的操作 WriteOneChar(0x44); // 启动温度转换 delay_18B20(100); // this message is wery important Init_DS18B20(); WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 delay_18B20(100); a=ReadOneChar(); //读取温度值低位 b=ReadOneChar(); //读取温度值高位 temp_value=b<<4; temp_value+=(a&0xf0)>>4; }void temp_to_str() //温度数据转换成液晶字符显示{ TempBuffer[0]=temp_value/10+'0'; //十位 TempBuffer[1]=temp_value%10+'0'; //个位 TempBuffer[2]=0xdf; //温度符号 TempBuffer[3]='C'; TempBuffer[4]='\0';}void Delay1ms(unsigned int count){ unsigned int i,j; for(i=0;i<count;i++) for(j=0;j<120;j++);} /*延时子程序*/void mdelay(uint delay){ uint i; for(;delay>0;delay--) {for(i=0;i<62;i++) //1ms延时. {;} }}
⑧ 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--);
}
⑩ 求单片机 数字钟 c语言代码注释
#include<reg51.h>
unsigned char code su[11]={0x3f,0x06,0x5b,0X4F,0x66,0X6D,0x7d,0x07,0x7f,0x6f,0x40};//数码管显示
unsigned char xian[8]={0,0,10,0,0,10,0,0};
unsigned char sen=0,min=0,hou=0,sen2=0,min2=0,hou2=0,sen3=59,min3=59,hou3=23,num;//变量定义
//--------引脚定义
sbit ks=P1^4; //秒按键
sbit km=P1^5; //分按键
sbit kh=P1^6; //时按键
sbit ds=P1^7;
sbit bb=P3^4;
//-------8个数码管位显示接口
sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;
sbit P24=P2^4;
sbit P25=P2^5;
sbit P26=P2^6;
sbit P27=P2^7;
bit jp1,jp2,jp3;//位定义
int n=0,jp4;
//----演示程序
void daly()
{
unsigned char j;
for(j=60;j;j--);//for循环
}
//------数码管显示
void show()
{
xian[0]=hou/10; //时的十位
xian[1]=hou%10; //时的个位
xian[3]=min/10; //分的十位
xian[4]=min%10; //分的个位
xian[6]=sen/10; //秒的十位
xian[7]=sen%10; //秒的个位
P0=su[xian[7]]; //八段数码管显示秒的个位
P20=0; //动态显示,打开第一个数码管
daly(); //延时
P20=1; //动态显示,关闭第一个数码管
P0=su[xian[6]];//八段数码管显示秒的十位
P21=0;//动态显示,打开第二个数码管
daly();//延时
P21=1;//动态显示,打开第二个数码管
//--------------------
P0=su[xian[5]];//注:你xian[3]xian[5]都为从定义
P22=0;
daly();
P22=1;
//-------------分个位的显示
P0=su[xian[4]];
P23=0;
daly();
P23=1;
//-----------
P0=su[xian[3]];//注:你xian[3]xian[5]都为从定义
P24=0;
daly();
P24=1;
//------------分十位的显示
P0=su[xian[2]];
P25=0;
daly();
P25=1;
//-------------时个位的显示
P0=su[xian[1]];
P26=0;
daly();
P26=1;
//-----------时十位的显示
P0=su[xian[0]];
P27=0;
daly();
P27=1;
}
//---------按键程序
void key()
{
if((ks==0)&&(jp1==0))
{
jp1=1;//秒按键生效
daly();//消抖
if(ks==0) sen++; //秒加1
}
else if((ks==1)&&(jp1==1)) jp1=0;//秒按键未生效
if(sen==60)//等于60时
{
min++;//分加1
sen=0;//秒清零
}
if((km==0)&&(jp2==0))
{
jp2=1;//分按键生效
daly();//消抖
if(km==0) min++;//分加1
}
else if((km==1)&&(jp2==1)) jp2=0;//分按键未生效
if(min==60)//等于60时
{
hou++;//时加1
min=0;//分清零
}
if((kh==0)&&(jp3==0))
{
jp3=1;//时按键生效
daly(); //消抖
if(kh==0) hou++;//时加1
}
else if((kh==1)&&(jp3==1)) jp3=0;//时按键未生效
if(hou==24) hou=0;//时为24时,清零
if(ds==0)//定时操作
{
daly();//消抖
while(ds==0);
daly();
if(ds==1) jp4++;//定时按键生效,加一
if(jp4>1) jp4=0;//JP4只能是一。
/*注:就本人感觉而言这两句就是废话,一句就能完事:if(ds==1) jp4=1;*/
}
}
//-------从功能上看这是定时
dings()
{
EA=0; //关闭中断
TR0=0;//T0停止计数
hou2=hou;//把现有的时分秒,保留储存在hou2,min2,sen2
min2=min;
sen2=sen;
hou=0; //清零
min=0;
sen=0;
while(jp4==1) //等待直到按键生效
{
hou3=hou; //把现有的时分秒,保留储存在hou3,min3,sen3
min3=min;
sen3=sen;
show(); //现实
key();//按键扫描
hou3=hou;//把按键后更改的时分秒,也就是定时时间,保留储存在hou3,min3,sen3
min3=min;
sen3=sen;
}
hou=hou2;//把远有的时间分别还原
min=min2;
sen=sen2;
EA=1;//开中断
TR0=1;//T0计数
}
void main()
{
TMOD=0x01;//定时器0方式1
TH0=45535>>8;//赋初值
TL0=45535;
EA=1; //允许中断
ET0=1;//T0中断使能
EX1=1;//外部中断1
TR0=1;//T0开始计数
hou3=99;
min3=99;
sen3=99;
while(1)
{
show();//显示
key();//按键程序
dings();//定时操作
if(((hou*60+min))*60+sen>=((hou3*60+min3))*60+sen3 )//判断是否到了定时时间
{
bb=0;//蜂鸣器鸣叫(也可能是其他音乐芯片)
num++;
if(num>=500) //鸣叫延时
{
bb=1; //蜂鸣器关闭
num=0; //延时计数清零
jp4=0;//位清零
hou3=99;//重新赋值
min3=99;
sen3=99;
}
}
}
}
void_time0_(void)interrupt 1
{
TL0=45535; //定时器0重新赋值
TH0=45535>>8;
if(++n==50) //1秒
{
n=0;
sen++; //秒加1
if(sen==60) //加到60
{
min++;
sen=0;
}//分加1
if(min==60)//加到60
{
hou++;
min=0;
}//时加1
if(hou==24) hou=0;//24时,时变成0
}
}
说实话,这个程序编写的很烂。