Ⅰ 51单片机做数字电子钟
这么复杂的东西给这么少分 晕死了 你也太小气了吧,分多的话还可能帮你动动脑
Ⅱ 用AT89S51(单片机)设计一个电子钟
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;20h.1半点标示位
;20H.2闹钟设置中........标示,为了显示区别用
;20H.3闹钟设置时间CHECK到,使能标志位
;20H.5开/关闹钟设置中........标示;
;20H.6闹钟1开关标志位
;20H.7闹钟2开关标志位
;psw.5用来做显示开关标志位
;21,22,23,24这里设置第一个闹钟的时间
;25,26,27,28这里设置第二个闹钟的时间
;29H
;P0口输出数码管段码,
;P2口 输出位选信号
;
;70H存放P1.0--3按钮值,
;71H--78H存放当前系统定时时间;
;78H 77H 76H 75H 74H 73H 72H 71H
; 星期* 小时 分钟 秒钟
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ts equ 24h ;这里设置`24小时周期制
trr equ #0bbh ;这个是温度,晶振等的时间补偿值,
org 0000h ;定时太慢此值调大,定时太快调小;
jmp main
;org 0bh ;定时器0中断入口矢量
;jmp bz
org 1bh ;定时器1中断入口矢量
jmp t1int
org 0100h ;主程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;主程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main:clr p3.0; ;关继电器
mov sp,#30h
mov r3,#20
mov tmod,#10h
;mov tl0,#06h ;定时器1,方式1,定时 50 MS;
;mov th0,#06h
mov tl1,#0b0h
mov th1,#3ch
mov ie,#88h ;开定时器1中断
;mov 65h,#5
; mov 66h,#100
;mov 64h,#4
;clr psw.5
clr p3.0
setb pt1 ;设置T1为高优先级中断
;setb tr1
clr tr1 ;开启T1中断
acall send ;71h--78h 清零;
acall send1 ;20h--29h 清零;
dd: acall daa ;进行十进制调整71H-79H
;acall compare ;第一闹钟
;acall compare1 ;第二闹钟 设置值
;acall sound
acall disp ;数码管显示,78H--71H分别对应着8个数码管显示
acall key_scanf ;按钮控制
acall time_adj ;时间调整
acall lasttime ;调用上一次的设置值为当前定时值
;acall alarm1_set ;设置定时开/关闹钟
ajmp dd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;调用上次值为设置时间
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lasttime:push acc
mov a,70h
jnb acc.2,return1
clr p3.0; 紧急暂停按钮,按下后暂停,并把上次设定值恢复.
clr tr1
mov 73h,21h
mov 74h,22h
wait7:acall disp
acall key_scanf
mov a,70h
jnb acc.0,wait7
mov 71h,#0
mov 72h,#0
mov 79h,#0
mov tl1,trr
mov th1,#3ch
mov r3,#20
setb tr1
setb p3.0
return1:pop acc
ret
daa: push acc ;对当前系统时间进行十进制调整
mov 71h,79h
mov r1,#71h
cjne @r1,#10,s2
mov 71h,#0h
mov 79h,#0
inc 72h
mov r1,#72h
cjne @r1,#6,s2
mov 72h,#0h
dec 73h
mov r1,#73h
cjne @r1,#255,s2
dec 74h
mov 73h,#9
s1: pop acc
ret
s2: mov r1,#73h
cjne @r1,#0,s1
mov r1,#74h
cjne @r1,#0,s1
clr p3.0
clr tr1
sjmp s1
h_half: ;半点CHECK
mov r1,#73h
mov a,74h
swap a
xchd a,@r1
cjne a,#29h,o25 ;CHECK 当前时间是否为29分钟
xchd a,@r1
mov r1,#71h
mov a,72h
swap a
xchd a,@r1
cjne a,#59h,o25 ;CHECK 当前时间为59秒?
setb tr0 ;启动T0
setb 20h.1 ;enable 半点flag bit
o25: xchd a,@r1
ret
compare: ;闹钟1设置时间与当前时间比较
push acc
jnb 20h.6,nequ ;闹钟1开/关标志位
mov a,73h
cjne a,21h,nequ ;分低位
mov a,74h
cjne a,22h,nequ ;分高位
mov a,75h
cjne a,23h,nequ ;小时低位
mov a,76h
cjne a,24h,nequ ;小时高位
setb 20h.3 ;到闹钟设置时间,使能闹钟报警标志位
nequ:pop acc
ret
compare1: ;闹钟2设置时间与当前时间比较
push acc
jnb 20h.7,nequ33 ;闹钟2开/关标志位
mov a,73h
cjne a,25h,nequ33
mov a,74h
cjne a,26h,nequ33
mov a,75h
cjne a,27h,nequ33
mov a,76h
cjne a,28h,nequ33
setb 20h.3 ;到闹钟设置时间,使能闹钟报警标志位
nequ33:
pop acc
ret
sound:
acall h_half ;check 是否半点?
jb 20h.1,s23 ;半点则返回
jb 20h.0,s23
mov r1,#73h
mov a,74h
swap a
xchd a,@r1
cjne a,#59h,s25
xchd a,@r1
mov r1,#71h
mov a,72h
swap a
xchd a,@r1
s20: cjne a,#56h,s21
ajmp s26
s21: cjne a,#58h,s22
ajmp s26
s22: cjne a,#59h,s25
setb tr0
ajmp s26
s25: xchd a,@r1
s23: ret
s26: jb 20h.0,s25
setb tr0
xchd a,@r1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T0中断服务程序,报时铃音信号输出
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bz: djnz 64h,rrr
jb 20h.3,alarmsign;闹钟到点报时有效
jb 20h.1,next ;半点报时
mov 64h,#4 ;0.5KHZ
ajmp justh
alarmsign:
mov 64h,#1; 2KHZ信号
justh:
djnz 66h,ccc
mov 66h,#100
djnz 65h,ccc ;产生1000次中断后关中断
mov 65h,#5 ;响0.5秒
setb 20h.0
clr tr0
reti
next:mov 64h,#2 ;1KHZ信号,半点报时音
ccc: jb 20h.3,cc
cpl p1.4 ;半点报时输出声音信号
rrr: reti
cc: cpl p1.4 ;闹钟报时输出声音信号
reti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T1中断服务程序,定时器主时钟;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
t1int:
clr ea
mov tl1,trr
mov th1,#3ch
djnz r3,sd ;20*50MS=1S
mov r3,#20
;cpl p1.4
inc 79h
clr 20h.0
clr 20h.1 ;半点报时标志清零
jb 20h.3,sdd ;闹钟CHECK有效与否?
clr tr0 ;关T0
sd: setb ea
reti
sdd: setb tr0 ;开T0,即开闹铃声音
setb ea
reti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;显示子函数
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dispnum1:; 显示
ajmp disp_num
disp:
push acc
;jb 20h.5,dispnum1;开/关闹钟设置中界面...........
;jb 20h.2,alarmcheck;闹钟设置时间中界面..........
jb psw.5,closedisp
mov r2,#01h;位选通信号输出到P2口
mov r5,#2; 显示的位数循环控制
mov r0,#73h;分别取出内存76H-71H
cjne r3,#10,dot1;在小时和分之间闪烁DOT point
dot1:jnc dsp1
orl 73h,#10h
;dot1:cjne r3,#11,dsp1
;anl 73h,#0efh
dsp1:mov a,r2
;cpl a
mov p2,a
mov a,@r0
dsp2:mov dptr,#bcd
movc a,@a+dptr
mov p0,a
acall delay
mov a,r2
rl a
mov r2,a
inc r0
djnz r5,dsp1
anl 73h,#0efh
pop acc
ret
closedisp:; 关显示
acall delay
mov p0,#0ffh
mov p2,#0
pop acc
ret
;;;;;;;;;;;;;;;;;闹钟的定时设置显示
alarmcheck:
mov r2,#01h
mov r5,#2 ;两位显示22-21H对应定时设置值
mov r0,#21h
dsp21:
mov a,r2
;cpl a
mov p2,a
mov a,@r0
mov dptr,#bcd
movc a,@a+dptr
mov p0,a
acall delay
mov a,r2
rl a
mov r2,a
inc r0
djnz r5,dsp21
pop acc
ret
bcd:; 共阳接法数码管段码表
db 0c0h,0f9h,0a4h,0b0h
db 99h,92h,82h,0f8h
db 80h,90h,88h,83h
db 0c6h,0a1h,86h,8eh; 不带小数点七段
db 40h,79h,24h,30h,19h
db 12h,02h,78h,00h,10h
db 0ffh,0bfh,7fh,3fh; 带小数点七段
delay:mov r6,#4h
tm: mov r4,#0h
ee: djnz r4,ee; 延时2048US=2MS
djnz r6,tm
ret
send:mov r7,#9; 初始化设置
mov r0,#71h
mov a,#0h
ss: mov @r0,a
inc r0
djnz r7,ss
mov 78h,#1h
mov 77h,#01ah
;mov 71h,#1
;mov 72h,#2
;mov 73h,#3
;mov 74h,#4
ret
send1:; 初始化
mov r7,#10
mov r0,#20h
mov a,#0
ss1: mov @r0,a
inc r0
djnz r7,ss1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;开/关闹钟界面显示
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
disp_num:
mov p2,#0f7h
mov a,29h ;当前要操作的闹钟号码
mov dptr,#bcd
movc a,@a+dptr
mov p0,a
acall delay
pop acc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
key_scanf:; 按钮处理
push acc
mov 70h,#0
orl p1,#0fh
mov a,p1
cpl a
anl a,#07h
jz nokey1
acall daa
acall disp
mov a,p1
cpl a
anl a,#07h
jz nokey1
mov 70h,a
key_wait:; 等按钮放下
acall daa
acall disp
mov a,p1
cpl a
anl a,#07h
jnz key_wait
mov a,70h
jnb acc.1,nokey1
cpl psw.5
nokey1:; 无按钮
pop acc
ret
a_on_off:
jnb 29h.0,iii
cpl 20h.6
iii: jnb 29h.1,out_2
cpl 20h.7
out_2:
ajmp alarmnum
alarmnum:
setb 20h.5
acall daa
acall disp
acall key_scanf
clr 20h.5
mov a,70h
jb acc.0,a_on_off
jb acc.1,alar_adj_1
jb acc.2,a_num_inc
acall numb
ajmp alarmnum
alarm1_set:
push acc
mov a,70h
jb acc.1,alarmnum
alarm1_out:
clr 20h.2
pop acc
ret
a_num_inc:
inc 29h
mov a,29h
anl a,#0fh
cjne a,#3,alarmnum
anl 29h,#0
ajmp alarmnum
alar_adj_1:
setb 20h.2
acall daa
orl 21h,#10h
acall disp
anl 21h,#0fh
acall key_scanf
mov a,70h
jb acc.1,hadj_1
jb acc.2,minc_1
ajmp alar_adj_1
madj_2:
acall daa
orl 25h,#10h
acall disp
anl 25h,#0fh
acall key_scanf
mov a,70h
jb acc.1,hadj_2
jb acc.2,minc_2
ajmp madj_2
hadj_1:
acall daa
orl 23h,#10h
acall disp
anl 23h,#0fh
acall key_scanf
mov a,70h
jb acc.1,madj_2
jb acc.2,hinc_1
ajmp hadj_1
hadj_2:acall daa
orl 27h,#10h
acall disp
anl 27h,#0fh
acall key_scanf
mov a,70h
jb acc.1,alarm1_out
jb acc.2,hinc_2
ajmp hadj_2
minc_1:
inc 21h
mov r1,#21h
cjne @r1,#10,alar_adj_1
mov 21h,#0
inc 22h
mov r1,#22h
cjne @r1,#6,alar_adj_1
mov 22h,#0h
ajmp alar_adj_1
minc_2:
inc 25h
mov r1,#25h
cjne @r1,#10,madj_2
mov 25h,#0
inc 26h
mov r1,#26h
cjne @r1,#6,madj_2
mov 26h,#0
ajmp madj_2
hinc_1:
inc 23h
mov r1,#23h
cjne @r1,#10,ss14
mov 23h,#0
inc 24h
ss14:
mov a,24h
swap a
xchd a,@r1
cjne a,#ts,ss15
mov 23h,#0
mov 24h,#0
ajmp hadj_1
ss15:xchd a,@r1
ajmp hadj_1
hinc_2:
inc 27h
mov r1,#27h
cjne @r1,#10,sss14
mov 27h,#0
inc 28h
sss14:
mov a,28h
swap a
xchd a, @r1
cjne a,#ts,sss15
mov 27h,#0
mov 28h,#0
ajmp hadj_2
sss15:
xchd a,@r1
ajmp hadj_2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;时间调整程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
time_adj:;
clr psw.5
push acc
mov a,70h
jb acc.0,l1;P1.0调时功能键,每按一次切换一位
ajmp nokeyout
adj_out:
mov 21h,73h
mov 22h,74h
setb p3.0 ;闭合继电器
setb tr1
nokeyout:
pop acc
ret
QQ: anl 73h,#0fh
anl 74h,#0fh
;anl 78h,#0fh
ret
l1: clr tr1;acall dab; 分钟调整
orl 73h,#10h;点亮分右下角的小数点,当前调整位置
acall disp
acall QQ
acall key_scanf
clr psw.5
mov a,70h
jb acc.0,h_adj;切换到小时调整
jb acc.1,m_inc;P1.2加1按钮
ajmp l1
h_adj:; 小时调整
;acall dab
orl 74h,#10h
acall disp
acall QQ
acall key_scanf
clr psw.5
mov a,70h
jb acc.0,out_adj;切换到星期调整
jb acc.1,h_inc;小时加1
ajmp h_adj
w_adj:
acall daa
orl 78h,#10h
acall disp
acall QQ
acall key_scanf
clr psw.5
mov a,70h
jb acc.0,out_adj
jb acc.2,w_inc
ajmp w_adj
out_adj:
ajmp adj_out
m_inc:;;;;;;;;;;;;;;; 调整分时,对定时复位,初始化
clr tr1
mov 71h,#0
mov 72h,#0
mov 79h,#0
mov tl1,trr
mov th1,#3ch
mov r3,#20
inc 73h
mov r1,#73h
cjne @r1,#10,s12
mov 73h,#0
inc 74h
mov r1,#74h
cjne @r1,#10,s12
mov 74h,#0
s12: ajmp l1
;;;;;;;;;;;;;;;;;;;;;;调整小时位
h_inc:
inc 74h
mov r1,#74h
cjne @r1,#10,s14
mov 74h,#0
;inc 76h
s14: ajmp h_adj
;mov a,76h
;swap a
;xchd a,@r1
;cjne a,#ts,s15;;;12进制,24进制设置值决定
;mov 75h,#0
;mov 76h,#0
;ajmp h_adj
;s15: ;xchd a,@r1
;ajmp h_adj
;;;;;;;;;;;;;;;;;;;;;;;调整星期位
w_inc:
inc 78h
mov r1,#78h
cjne @r1,#8,s16
mov 78h,#1h
s16: ajmp w_adj
;;;;;;;;;;;;;;;;;;;;;;;当前闹钟开/关情况报告位
numb:clr 29h.4
jnb 29h.0,iii1
jnb 20h.6,iii1
setb 29h.4
iii1:jnb 29h.1,out_21
jnb 20h.7,out_21
setb 29h.4
out_21:
jnb 20h.6,out_12
jnb 20h.7,out_13
mov 77h,#1dh
ajmp out_22
out_12:
jnb 20h.7,out_14
mov 77h,#1bh
ajmp out_22
out_13:
mov 77h,#1ch
ajmp out_22
out_14:
mov 77h,#1ah
out_22:
ret
end
Ⅲ 用51单片机定时器编写一个定时闹钟
问题不是很清晰!
首先,定时器溢出时间较短,需要在定时器中断外另设计数单元;
其次,什么叫“检验对准时间”?我的理解是:使用一段程序来检验当前时间与设定时间(闹钟的定时值)的差值,差值为零时报时。基于该理解,有两种方式(根据你自己的情况自选):
1)先设计出一个时钟,然后将时钟值与设定值比对,具体语句可以使用“异或”(两时间相同时,异或值为零),或CJNE指令;本人倾向于后者(如:万一出现干扰在两值相同时没有比较,前者就失效了,而后者还能继续比较)。
2) 预置一个变量,每个固定时间间隔(使用定时中断)减一,到零时报时;但要注意,直接在定时中断程序中减一时一定要在中断中判断到零否,否可能则会出现不报时的问题。
Ⅳ 用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--);
}
Ⅳ 基于51单片机的电子钟 求帮助
/**数字电子钟仿真实例,可以作秒表**/ 参考一下试试
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit qingling=P1^0; //清零
sbit tiaofen=P1^1; //调分
sbit tiaoshi=P1^2; //调时
sbit sounder=P1^7; //naozhong
uint a,b;
uchar hour,minu,sec, //时钟
hour0,minu0,sec0, //秒表
hour1,minu1,sec1;
h1,h2,m1,m2,s1,s2, //显示位
k,s; //状态转换标志
uchar code select[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/*****************函数声明***********************/
void keyscan();
void init();
void delay(uchar z);
void display(uchar,uchar,uchar);
void sounde();
/*****************主函数*************************/
void main()
{
init();
while(1)
{
while(TR1)
{
keyscan(); // 扫描函数
while(s==1) // s是状态标志,当s=0时,闹钟取消。s=1时,设定闹钟时间
//(也是通过调时,调分函数);
{ //s=2时,闹钟工作,时间与设定时刻一致时,闹钟响
// (一分钟后自动关闭,可手动关闭)。再次切换,s=0.
keyscan(); //s状态切换(0-》1-》2-》0)通过外部中断1实现。
display(hour1,minu1,sec1); //闹钟时刻显示
}
display(hour0,minu0,sec0);//时钟表显示
while(k) /*k是秒表状态(0-》1-》2-》0)通过外部中断0实现。
0秒表关;1秒表从零计时;2秒表停,显示计时时间*/
{
display(hour,minu,sec); //秒表显示
}
}
}
}
/*****************初始化函数***********************/
void init()
{
a=0;
b=0;
k=0;
s=0;
hour0=0;
minu0=0;
sec0=0;
hour=0;
minu=0;
sec=0;
hour1=0;
minu1=0;
sec1=0;
TMOD=0x11; //定时器0,1工作于方式1;赋初值
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
EA=1;
EX0=1; //秒表中断
EX1=1; //闹钟设定中断
ET0=1;
ET1=1;
IT0=1; //边沿触发方式
IT1=1;
PX0=1;
PX1=1;
TR0=0; //初始,秒表不工作
TR1=1; //时钟一开始工作
}
/*****************定时器0中断*************/
void timer0_int() interrupt 1 //秒表
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
a++;
if(a==2)
{
a=0;
sec++;
if(sec==100)
{
sec=0; //毫秒级
minu++;
if(minu==60)
{
minu=0; //秒
hour++;
if(hour==60) //分
{
hour=0;
}
}
}
}
}
/*************外部中断0中断函数************/
void ex0_int() interrupt 0
{
k++;
if(k==3)
k=0;
if(k==1)
{
TR0=~TR0;
if(TR0==1)
{
hour=0;
minu=0;
sec=0;
}
}
if(k==2)
{
TR0=~TR0;
}
}
/*************外部中断1中断函数************/
void ex1_int() interrupt 2
{
s++;
if(s==3)
s=0;
}
/*************定时器1中断****************/
void timer1_int() interrupt 3 //控制时钟工作
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
if(s==2)
{
if(hour1==hour0 && minu0==minu1)
sounde();
}
b++;
if(b==20)
{
b=0;
sec0++;
if(sec0==60)
{
sec0=0;
minu0++;
if(minu0==60)
{
minu0=0;
hour0++;
if(hour0==24)
hour0=0;
}
}
}
}
/*************键盘扫描****************/
void keyscan()
{
if(s==1)
{
if(qingling==0)
{
delay(10);
if(qingling==0)
{
sec1=0;
minu1=0;
hour1=0;
}
}
if(tiaofen==0)
{
delay(10);
if(tiaofen==0)
{
minu1++;
if(minu1==60)
{
minu1=0;
}
while(!tiaofen);
}
}
if(tiaoshi==0)
{
hour1++;
if(hour1==24)
{
hour1=0;
}
while(!tiaoshi);
}
}
else //调整时钟时间
{
if(qingling==0)
{
delay(10);
if(qingling==0)
{
sec0=0;
minu0=0;
hour0=0;
}
}
if(tiaofen==0)
{
delay(10);
if(tiaofen==0)
{
minu0++;
if(minu0==60)
{
minu0=0;
}
while(!tiaofen);
}
}
if(tiaoshi==0)
{
hour0++;
if(hour0==24)
{
hour0=0;
}
while(!tiaoshi);
}
}
}
/*************显示函数****************/
void display(uchar hour,uchar minu,uchar sec)
{
h1=hour/10;
h2=hour%10;
m1=minu/10;
m2=minu%10;
s1=sec/10;
s2=sec%10;
P0=0xff;
P2=table[h1];
P0=select[7];
delay(5);
P0=0xff;
P2=table[h2];
P0=select[6];
delay(5);
P0=0xff;
P2=0x40;;
P0=select[5];
delay(5);
P0=0xff;
P2=table[m1];
P0=select[4];
delay(5);
P0=0xff;
P2=table[m2];
P0=select[3];
delay(5);
P0=0xff;
P2=0x40;
P0=select[2];
delay(5);
P0=0xff;
P2=table[s1];
P0=select[1];
delay(5);
P0=0xff;
P2=table[s2];
P0=select[0];
delay(5);
}
/*************闹钟函数****************/
void sounde()
{
sounder=~sounder;
}
/*************延时函数****************/
void delay(uchar z)
{
int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
Ⅵ 51单片机 可编程作息时间控制器设计
本设计是可编程作息时间控制器设计,由单片机AT89C51芯片和LCD、LED显示器,辅以必要的电路,构成一个单片机四路可调闹钟。电子钟可采用数字电路实现,也可以采用单片机来完成。LCD显示“时”,“分”,LED亮灯来表示闹钟的到来,定时时间到能发出警报声。现在是自动化高度发达的时代,特别是电子类产品都是靠内部的控制电路来实现对产品的控制,达到自动运行的目的,这就需要我们这里要做的设计中的电器元件及电路的支持。
在这次设计中主要是用AT89S51来进行定时,也结合着其他辅助电路实施控制,在定时的时候,按一下控制小时的键对小时加一;按一下控制分钟的键对分钟加一;到达预设的时间,此电路就会发出报警声音提示已经到点。
自从人类学会计时开始,计时方式由在木棍和骨头上刻标记,随着人类智慧的发展,到后面使用计时工具不断改进,从最开始的圭表、日冕、漏壶、漏箭、机械闹钟、秒表、沙漏、怀表、自摆钟、石英钟等。现在,高精度的计时工具大多数采用石英晶体振荡器,走时精度高,稳定性好,使用方便,不需要经常调校。而后经发展,数字式电子钟采用集成电路设计时,译码代替机械式传动,LED显示器代替指针显示时间,减少计时误差。这种电子时钟具备实现时、分、秒功能,同时进行校对。外观时尚,使用方便,深受消费者青睐。
Ⅶ 51单片机时钟程序设计
朋友以下是本人历时一个月殚精竭虑自主开发的一个8位51单片机时钟程序,望吾之兄弟姐妹习之,此程序乃采用一键控制,通过感知按下键持续时间的长短来进行调整时间,闹铃,6只共阳数码管输出显示,此外还包括整点铃声功能,在看程序之前我先交代一下运行该程序的硬件要求:12M晶振,P0端口驱动显示,P2.0到P2.5控制显示扫描,P2.7输出铃声,注意:铃声功放三极管应采用pnp管。以下是该程序:
ORG 00H
SETB TR0
JMP START
ORG 000BH
LJMP T0
START: MOV IE,#82H
MOV TMOD,#01H
MOV DPTR,#TAB
MOV SP,#60H
MOV 20H,#0
MOV R0,#0
MOV R1,#0
MOV R2,#0
MOV R3,#0
MOV R4,#0
MOV R5,#0
MOV R6,#0
MOV R7,#0
MOV 50H,#0
MOV 51H,#0
MOV 52H,#0
MOV 53H,#0
MOV 54H,#0
MOV 55H,#0
MOV A,TL0
ADD A,0B5H
MOV TL0,A
MOV TH0,#3CH
LOOP: ANL 20H,#08H
UNSV: MOV R1,#0
LCALL DISPLAY
JB 03H,LOP1
LCALL SOUND
LCALL HDLY
LOP1: MOV P3,#0FEH ;按键监视
MOV A,P3
CJNE A,#0FEH,LOP2
MOV R1,#0
JMP LOOP
LOP2: MOV R1,#2 ;误按判断
LOP3: LCALL HD
DJNZ R1,LOP3
JNB 04H,LOOP
CLR 04H
LOP4: INC R1
MOV C,00H ;调秒
CPL C
MOV 00H,C
LCALL HDLY
CJNE R1,#40,LOP5
JMP LOOP
LOP5: JNB 05H,LOP4
CLR 05H
MOV R1,#0
LCALL HD
CLR 00H
JB 04H,TF
MOV R2,#0
MOV R3,#0
JMP LOP4
TF: CLR 04H
LOP6: INC R1
MOV C,01H ;调分
CPL C
MOV 01H,C
LCALL HDLY
CJNE R1,#40,LOP7
JMP LOOP
LOP7: JNB 05H,LOP6
CLR 05H
MOV R1,#0
LCALL HD
CLR 01H
JB 04H,TS
INC R4
MOV R1,#0
CJNE R4,#10,LOP6
MOV R4,#0
INC R5
CJNE R5,#6,LOP6
MOV R5,#0
JMP LOP6
TS: CLR 04H
LOP8: INC R1
MOV C,02H ;调时
CPL C
MOV 02H,C
LCALL HDLY
CJNE R1,#40,LOP9
JMP LOOP
LOP9: JNB 05H,LOP8
CLR 05H
MOV R1,#0
LCALL HD
CLR 02H
JB 04H,TN
INC R6
CJNE R7,#2,NO2
CJNE R6,#4,LOP8
MOV R7,#0
MOV R6,#0
NO2: CJNE R6,#10,LOP8
MOV R6,#0
INC R7
JMP LOP8
TN: CLR 04H ;调闹铃
SETB RS0
CLR RS1
MOV R2,#0
MOV R3,#0
MOV R4,#0
MOV R5,#0
MOV R6,#0
MOV R7,#0
NS: INC R1 ;闹铃秒调整
MOV C,00H
CPL C
MOV 00H,C
LCALL HDLY
CJNE R1,#40,NS1
JMP NH2
NS1: JNB 05H,NS
CLR 05H
MOV R1,#0
LCALL HD
CLR 00H
JB 04H,NF
INC R2
CJNE R2,#10,NS
MOV R2,#0
INC R3
CJNE R3,#6,NS
MOV R3,#0
JMP NS
NF: CLR 04H ;闹铃分
NF1: INC R1
MOV C,01H
CPL C
MOV 01H,C
LCALL HDLY
CJNE R1,#40,NF2
LJMP NH2
NF2: JNB 05H,NF1
CLR 05H
MOV R1,#0
LCALL HD
CLR 01H
JB 04H,NH
INC R4
CJNE R4,#10,NF1
MOV R4,#0
INC R5
CJNE R5,#6,NF1
MOV R5,#0
JMP NF1
NH: CLR 04H ;闹铃时调整
NH1: INC R1
MOV C,02H
CPL C
MOV 02H,C
LCALL HDLY
CJNE R1,#40,NH3
NH2: MOV 50H,R2
MOV 51H,R3
MOV 52H,R4
MOV 53H,R5
MOV 54H,R6
MOV 55H,R7
CLR RS0
CLR RS1
LJMP LOOP
NH3: JNB 05H,NH1
CLR 05H
MOV R1,#0
LCALL HD
CLR 02H
JB 04H,NH2
INC R6
CJNE R7,#2,NOT2
CJNE R6,#4,NH1
MOV R6,#0
MOV R7,#0
JMP NH1
NOT2: CJNE R6,#10,NH1
MOV R6,#0
INC R7
JMP NH1
;子程序区
TIMES: CJNE R0,#20,LOOP16
MOV R0,#0
INC R2
CJNE R2,#10,LOOP16
MOV R2,#0
INC R3
CJNE R3,#6,LOOP16
MOV R3,#0
ADMINI: INC R4
CJNE R4,#10,LOOP16
MOV R4,#0
INC R5
CJNE R5,#6,LOOP16
MOV R5,#0
HOUR: INC R6
LCALL SOUND ;整点铃声
CJNE R7,#2,LOOP14
CJNE R6,#4,LOOP16
MOV R6,#0
MOV R7,#0
JMP LOOP16
LOOP14: CJNE R6,#10,LOOP16
MOV R6,#0
INC R7
LOOP16: RET
DISPLAY:MOV P2,#0FFH
MOV A,R2
MOVC A,@A+DPTR
MOV P0,A
MOV C,00H
MOV P2.0,C
MOV P2,#0FFH
MOV A,R3
MOVC A,@A+DPTR
MOV P0,A
MOV P2.1,C
MOV P2,#0FFH
MOV A,R4
MOVC A,@A+DPTR
MOV P0,A
MOV C,01H
MOV P2.2,C
MOV P2,#0FFH
MOV A,R5
MOVC A,@A+DPTR
MOV P0,A
MOV P2.3,C
MOV P2,#0FFH
MOV A,R6
MOVC A,@A+DPTR
MOV P0,A
MOV C,02H
MOV P2.4,C
MOV P2,#0FFH
MOV A,R7
MOVC A,@A+DPTR
MOV P0,A
MOV P2.5,C
MOV P2,#0FFH
RET
HDLY: MOV 40H,#2
HDL1: MOV 41H,#25
HDL2: MOV 42H,#100
HDL3: DJNZ 42H,HDL4
DJNZ 41H,HDL2
DJNZ 40H,HDL1
JMP HDOT
SOUT: SETB 05H
HDOT: RET
HDL4: MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,SOUT
CLR 05H
LCALL DISPLAY
JMP HDL3
HD: MOV 30H,#5
HD1: MOV 31H,#50
HD2: MOV 32H,#100
HD3: LCALL DISPLAY
DJNZ 32H,HD4
DJNZ 31H,HD2
DJNZ 30H,HD1
SETB 04H ;计满标志位
JMP HDOUT
HD4: MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,HD3
MOV 33H,#50
HD5: MOV 34H,#100
DJNZ 34H,$
DJNZ 33H,HD5
MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,HD3
CLR 04H
HDOUT: RET
SOUND: MOV 30H,#10
SO1: MOV 31H,#100
SO2: MOV 32H,#3
MOV C,P2.7
CPL C
MOV P2.7,C
SO3: MOV 33H,#25
DJNZ 33H,$
DJNZ 32H,SO3
DJNZ 31H,SO2
DJNZ 30H,SO1
RET
T0: PUSH PSW
PUSH ACC
CLR RS1
CLR RS0
MOV A,TL0
ADD A,#0B5H
MOV TL0,A
MOV TH0,#3CH
INC R0
LCALL TIMES
MOV A,R2
CJNE A,50H,TO
SETB 03H
MOV A,R3
CJNE A,51H,TO
MOV A,R7
CJNE A,55H,TO
MOV A,R6
CJNE A,54H,TO
MOV A,R5
CJNE A,53H,TO
MOV A,R4
CJNE A,52H,TO
MOV A,R2
ADD A,R3
ADD A,R4
ADD A,R5
ADD A,R6
ADD A,R7
JZ TO
CLR 03H
TO: POP ACC
POP PSW
RETI
TAB: DB 0C0H 0F9H 0A4H 0B0H 099H
DB 092H 082H 0F8H 080H 090H
END
Ⅷ 用C语言写51单片机闹钟程序
//*********************************************************
//实现功能:本程序实现在P1口模拟一个流水灯程序
//*********************************************************
#include <reg51.h>
#define p_out P1 //宏定义输出的i/o口为P1
//******************时间延迟函数**********************
//描 述:用指令实现延时一段时间
//入口参数:int i,为时间延迟参数
//****************************************************
void delay_time(int i)
{
while(i)
i--;
}
//******************主函数***************************
//描 述:实现在P1口模拟一个流水灯程序
//****************************************************
void main(void)
{unsigned char i=0; //初始化一个局部变量为0
p_out=0xff; //初始化将要输出的i/o口,输出高电平,熄灭所有灯
while(1)
{
for(i=0;i<8;i++)
{
p_out=~(1<<i);//点亮一个灯,
delay_time(50000); //延迟一段时间
p_out=0xff;//熄灭所有灯
}
}
}
//**************************************
//****************************************************
//实现功能:把键盘输入的键盘码,用led显示出来
//****************************************************
#include <reg51.h>
#define p_key P1
#define led_date P0
#define choose_p P2
unsigned char change(unsigned char i);
unsigned int display_num=0;
//******************时间延迟函数**********************
//描 述:用指令实现延时一段时间
//入口参数:int i,为时间延迟参数
//****************************************************
void delay_time(int i)
{
while(i)
i--;
}
//******************按键扫描函数**********************
//描 述:对4*4键盘进行扫描,程序只适合4*4键盘使用,
// 键盘占用一组完整的i/o口,在使用这个程序前
// 要宏定义p_key为用户实际连接键盘的i/o口
// #define p_key Pn;//(n=0、1、2、3)
//返回参数:若有检测到按键就返回按键的编号,否则返回0xff
//****************************************************
unsigned char read_key(void)
{
unsigned char j,key,key_buf=0;
p_key=0xff;
//检测是否有建按下//
p_key=0xf0;
key=p_key;
if(key==0xf0)
{
return(0xff);//没按键按下,返回0xff
}
//有按下,延时去抖//
delay_time(5000);
//确认是否有建按下//
p_key=0xf0;
key=p_key;
if(key==0xf0)
{
return(0xff);//没按键按下,返回0xff
}
//真的有按键按下,扫描是哪一行有按键按下//
for(j=0;j<4;j++)
{key=p_key&(0x10<<j);
if (key)
{
key=p_key;
}
else
{
key_buf=j*4;
p_key=~(0x10<<j);//第j行的按键按下了,第j行输出0,其他的i/o口输出1
//扫描是第j行的哪个按键按下//
for(j=0;j<4;j++)
{
key=p_key&(1<<j);
if (key)
{
key=p_key;
}
else
{
key_buf+=j;
return(key_buf);//扫描到按键的确定位置,返回按键的编号
}
}
}
}
//没扫描到按键,//
return(0xff);
}
//***************七段数码管显示函数*******************
//描 述:对四位的扫描型七段数码管进行扫描显示,在使用
// 前要定义一个全局变量display_num
// unsigned int display_num;
//入口参数:unsigned int num,要显示的数字(0-9999)
//****************************************************
void display(unsigned int num)
{
if(num<10000)
{
display_num=num;
}
choose_p|=3;//先关显示
led_date=change(display_num/1000);//得到千位的数字,并转换成七段码型
choose_p&=0xfe;//选通千位
delay_time(50);//延时一段时间
choose_p|=1;//关显示
display_num=display_num%1000;
led_date=change(display_num/100);//得到百位的数字,并转换成七段码型
choose_p&=0xfd;//选通百位
delay_time(50);//延时一段时间
choose_p|=2;//关显示
display_num=display_num%100;
led_date=change(display_num/10);//得到十位的数字,并转换成七段码型
choose_p&=0xfb;//选通十位
delay_time(50);//延时一段时间
choose_p|=4;//关显示
led_date=change(display_num%10);//得到个位的数字,并转换成七段码型
choose_p&=0xf7;//选通十位
delay_time(50);//延时一段时间
choose_p|=8;//关显示
}
//****************数字-码型转换函数*******************
//描 述:把数字转换成七段码型,此程序仅配合共阳的七
// 段数码管使用
//入口参数:unsigned char i,要转换的数字(0-9),
//返回参数:转换后的七段码型,0xff表示转换失败
//****************************************************
unsigned char change(unsigned char i)
{
switch(i)
{
case 0:
return(0xc0);//0的七段码型
case 1:
return(0xf9);//1的七段码型
case 2:
return(0xa4);//2的七段码型
case 3:
return(0xb0);//3的七段码型
case 4:
return(0x99);//4的七段码型
case 5:
return(0x92);//5的七段码型
case 6:
return(0x82);//6的七段码型
case 7:
return(0xf8);//7的七段码型
case 8:
return(0x80);//8的七段码型
case 9:
return(0x90);//9的七段码型
default:
return(0xff);//转换失败
}
}
//*********************主函数*************************
//描 述:把键盘输入的键盘码,用led显示出来
//****************************************************
int main(void)
{unsigned char i;
while(1)
{
i=read_key();//扫描键盘
if(i<16)
display((unsigned int)i);//有效的键盘值
else
display(0xffff);//数据无效
}
}
//两个程序加起来就可以完成你要求的功能,有说明,你认真看一下吧。