‘壹’ 基于单片机的数字时钟设计开题报告
//我这里有一个定时的闹钟,你把蜂鸣器的中断改为LED就行了,可以通过P2^0--P2^3实现秒表的显示和以及调时调分和调节闹钟以及闹钟的开关,有问题可以给我留言QQ834589429
#include<reg52.h>//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
codeunsignedchartab[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//共阴数码管0-9
sbitA1=P2^0;
sbitA2=P2^1;
sbitA3=P2^2;
sbitA4=P2^3;
sbitbeep=P1^4;
unsignedcharShiwan;
unsignedcharWanwei;
unsignedcharQianwei;
unsignedcharBaiwei;
unsignedcharShiwei;//定义十位
unsignedcharGewei,Naoling1,Naoling2,Naoling3,Naoling4;//定义个位
staticunsignedcharhour=12,minute=30,second=0,count=0;
staticunsignedcharalarmhour=12,alarmminute=29,i=0,j=0,k;
/******************************************************************/
/*延时函数*/
/******************************************************************/
voiddelay(unsignedintcnt)
{
while(--cnt);
}
voidxianshi(void)
{
Gewei=tab[second%10];//个位显示处理
Shiwei=tab[second/10];//十位显示值处理
if(second%2==0)
{
Baiwei=tab[minute%10];
Qianwei=tab[minute/10];//千位
}
else
{
Baiwei=(tab[minute%10]|0x80);//百位显示处理:加点的字码
Qianwei=(tab[minute/10]|0x80);
}
if(second%2!=0)
{
Wanwei=tab[hour%10];
Shiwan=tab[hour/10];
}
else
{
Wanwei=(tab[hour%10]|0x80);
Shiwan=(tab[hour/10]|0x80);
}
Naoling1=~tab[alarmhour%10];
Naoling2=~tab[alarmhour/10];
Naoling3=~tab[alarmminute%10];
Naoling4=~tab[alarmminute/10];
}
voidtimer0()interrupt3using1
{
TH1=0x3c;//中断设置初始化
TL1=0xb0;
if(alarmhour==hour&&alarmminute==minute&&j==1)
{
beep=0;
}
}
/******************************************************************/
/*定时器中断函数*/
/******************************************************************/
voidtimer1()interrupt1using0
{
TH0=0xd8;//重新赋值
TL0=0xf0;
count++;
xianshi();
if(count==99)//100x10ms=1S,大致延时时间
{
count=0;
second++;//秒加1
if(second==60)
minute++;
{
if(second==60)
second=0;
{
if(minute==60)
hour++;
{
if(minute==60)
minute=0;
{
if(hour==24)
hour=0;
}
}
}
}
}
}
/******************************************************************/
/*主函数*/
/******************************************************************/
voidmain()
{
TMOD|=0x01;//定时器设置10msin12Mcrystal,工作在模式1,16位定时
TH0=0xd8;
TL0=0xf0;
IE=0x82;//打开中断
TR0=1;//打开定时开关
xianshi();
EA=1;ET0=1;TMOD|=0x21;TR0=1;//开中断总开关,计数器0允许中断,设置中断模式,启动计数器0
ET1=1;TR1=1;
while(1)
{
{
if(!A3)
{
delay(10000);
if(!A3)
{
i++;if(i==7)i=0;
xianshi();
}
}
}
{
if(!A4)
{
delay(10000);
if(!A4)
{
i--;if(i==255)i=6;
xianshi();
}
}
}
switch(i)
{
case0://正常显示控制
{
P1=0x1e;//片选个位
P0=~Baiwei;//显示个位
delay(300);//短暂延时
P1=0x1d;//片选十位
P0=~Qianwei;//显示十位
delay(300);//短暂延时
P1=0x1b;//片选百位
P0=~Wanwei;//显示百位
delay(300);//短暂延时
P1=0x17;//片选千位
P0=~Shiwan;//显示千位
delay(300);//短暂延时
P1=0x1f;
P0=0xff;
delay(300);
};break;
case1://调分控制
{
if(second%2!=0)
{
P1=0x1e;//片选个位
P0=~Baiwei;//显示个位
delay(300);//短暂延时
P1=0x1d;//片选十位
P0=~Qianwei;//显示十位
delay(300);//短暂延时
P1=0x1f;
P0=0xff;
delay(300);
}
else
delay(300);
delay(300);
{
if(!A1)
{
delay(10000);//消抖
if(!A1)
{
minute++;if(minute==61)minute=0;
xianshi();
}
}//按键处理
}
{
if(!A2)
{
delay(10000);//消抖
if(!A2)
{
minute--;if(minute==255)minute=59;
xianshi();
}
}
}
};break;
case2://调时控制
{
if(second%2==0)
{
P1=0x1b;//片选百位
P0=~Wanwei;//显示百位
delay(300);//短暂延时
P1=0x17;//片选千位
P0=~Shiwan;//显示千位
delay(300);//短暂延时
P1=0x1f;
P0=0xff;
delay(300);
}
else
delay(300);
delay(300);
{
if(!A1)
{
delay(10000);//消抖
if(!A1)
{
hour++;if(hour==24)hour=0;
xianshi();
}
}//按键处理
}
{
if(!A2)
{
delay(10000);//消抖
if(!A2)
{
hour--;if(hour==255)hour=23;
xianshi();
}
}
}
};break;
case3://秒显示控制
{
P1=0x1e;//片选个位
P0=~Gewei;//显示个位
delay(300);//短暂延时
P1=0x1d;//片选十位
P0=~Shiwei;//显示十位
delay(300);//短暂延时
P1=0x1f;
P0=0xff;
delay(300);
delay(300);
delay(300);
};break;
case4://闹钟控制
{
if((!A1)||(!A2))
{
delay(10000);
if((!A1)||(!A2))j++;
if(j==2)
j=0;
}
switch(j)
{
case0:{
P1=0x1e;//片选个位
P0=~0x71;//显示个位
delay(300);//短暂延时
P1=0x1d;//片选十位
P0=~0x71;//显示十位
delay(300);//短暂延时
P1=0x1b;//片选百位
P0=~0x3f;//显示百位
delay(300);//短暂延时
P1=0x17;//片选千位
P0=~0x40;//显示千位
delay(300);//短暂延时
delay(300);
};break;
case1:{
P1=0x1e;//片选个位
P0=~0x37;//显示个位
delay(300);//短暂延时
P1=0x1d;//片选十位
P0=~0x3f;//显示十位
delay(300);//短暂延时
P1=0x1b;//片选百位
P0=0xff;//显示百位
delay(300);//短暂延时
P1=0x17;//片选千位
P0=~0x40;//显示千位
delay(300);//短暂延时
delay(300);
}
}
};break;
case5://闹铃分钟调整
{
{
P1=0x1e;
P0=Naoling3;
delay(300);
P1=0x1d;
P0=Naoling4;
delay(300);
P1=0x1f;
P0=0xff;
delay(300);
delay(300);
delay(300);
}
{
if(!A1)
{
delay(10000);//消抖
if(!A1)
{
alarmminute++;if(alarmminute==61)alarmminute=0;
}
}//按键处理
}
{
if(!A2)
{
delay(10000);//消抖
if(!A2)
{
alarmminute--;if(alarmminute==255)alarmminute=59;
}
}
}
};break;
case6://闹铃小时调整
{
{
P1=0x1b;
P0=Naoling1;
delay(300);
P1=0x17;
P0=Naoling2;
delay(300);
P1=0x1f;
P0=0xff;
delay(300);
delay(300);
delay(300);
}
{
if(!A1)
{
delay(10000);//消抖
if(!A1)
{
alarmhour++;if(alarmhour==24)alarmhour=0;
}
}//按键处理
}
{
if(!A2)
{
delay(10000);//消抖
if(!A2)
{
alarmhour--;if(alarmhour==255)alarmhour=23;
}
}
};break;
default:break;
}
}
}
}
‘贰’ 单片机数字时钟设计
ORG 0X00
LJMP START
ORG 0X30
#30H ; 设置堆栈
MOV P1, #0XFE ; 设置在数码管的第0位显示
MOV A, #0X01 ; A置初值为0000 0001
LOOP: MOV P0, A ; 在数码管上显示寄存器A中的二进制数
MOV R3, #0X5C ; 延时1S
ACALL EXTDELAY ; 延时观察和记录对应的显示结果
RL A ; 将A寄存器的值循环左移一位
SJMP LOOP ; 循环显示
DELAY: MOV R1, #0XC8 ; 延时20MS
DL2: MOV R2, #0X18
DL1: NOP
NOP
DJNZ R2, DL1
DJNZ R1, DL2
RET
EXTDELAY:ACALL DELAY
DJNZ R3,EXTDELAY
RET
END
ORG 0X00
SJMP START
ORG 0X30
START: MOV SP, #30H ; 设置堆栈
MOV P1, #0XFE ; 位选信号,选中第0个数码管
MOV P0, #0X6F ; 在数码管上显示"9"
LOOP: SJMP LOOP ; 循环执行程序
END
ORG 0X00
LJMP START
ORG 0X30
START: MOV SP, #30H ; 设置堆栈
MOV P1, #0XFE ; 设置在数码管的第0位显示
MOV DPTR, #TABLE ; 送TABLE地址到DPTR指针
MOV R7, #0X00 ; 标志变量,限制指针在TABLE区
LOOP: CLR A
MOVC A, @A+DPTR ; 取TABLE区的字形码
MOV P0, A ; 在数码管上显示寄存器A中的二进制数
INC R7 ; 指针控制加一
MOV R3, #0X5C ; 延时
ACALL EXTDELAY ; 延时观察和记录对应的显示结果
CJNE R7, #0X10, NEXT ; 如果TABLE中数未取到最后一个,继续取下一个
MOV R7, #0X00 ; 如果已经取过所有数,则重新开始去第一个数
MOV DPTR, #TABLE
SJMP LOOP
NEXT: INC DPTR ; 指针寄存器加1
SJMP LOOP ; 循环显示
DELAY: MOV R1, #0XC8 ; 延时20MS
DL2: MOV R2, #0X18
DL1: NOP
NOP
DJNZ R2, DL1
DJNZ R1, DL2
RET
EXTDELAY: ACALL DELAY
DJNZ R3 ,EXTDELAY
RET
TABLE: ; 相对地址
DB 0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F ;十六进制字形数据
0 1 2 3 4 5 6 7 8 9 (十六进制数)
DB 0X77,0X7C,0X39,0X5E,0X79,0X71 ; 十六进制字形数据
A B C D E F (十六进制数)
END
ORG 0X00
LJMP START
ORG 0X30
START: MOV SP, #30H
MOV A, #0XFE ; 置A寄存器为0XFE
MOV DPTR, #TABLE
MOV R7, #0X00
LOOP: MOV P1, A ; 在数码管的第0位显示
MOV R4,A ; 保存A寄存器的制
CLR A
MOVC A, @A+DPTR
MOV P0, A
MOV A, R4 ; 还原A寄存器的值
CJNE A, #0XBF, SKIP ; 如果已在第五位显示,那么下一次
MOV A, #0XFE ; 从第0位开始显示
SJMP LOOP ; 跳回执行下一次显示
SKIP: RL A ; A左移一位,下一次在数码管的下一位显示数字
INC R7
MOV R3, #0X5C
ACALL EXTDELAY
CJNE R7, #0X10, NEXT ; 如果TABLE中数未取到最后一个,继续取下一个
MOV R7, #0X00 ; 如果已经取过所有数,则重新开始去第一个数
MOV DPTR, #TABLE
SJMP LOOP
NEXT: INC DPTR ; 指针寄存器加1
SJMP LOOP ; 循环显示
DELAY: MOV R1, #0XC8 ; 延时20MS
DL2: MOV R2, #0X18
DL1: NOP
NOP
DJNZ R2, DL1
DJNZ R1, DL2
RET
EXTDELAY: ACALL DELAY
DJNZ R3, EXTDELAY
RET
TABLE: ; 相对地址
DB 0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F ;十六进制字形数据
0 1 2 3 4 5 6 7 8 9 (十六进制数)
DB 0X77,0X7C,0X39,0X5E,0X79,0X71 ; 十六进制字形数据
A B C D E F (十六进制数)
END
‘叁’ 基于单片机的数字时钟设计方案
数字钟〔★〕这里用了两种编租肆写方法(即汇编语言与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;
}