通过了,自己对照看看问题出在哪里。
ORG 00H
LJMP MAIN
ORG 0003H
LJMP EINT0
ORG 0013H
LJMP EINT1
ORG 1BH
LJMP TIMER1
ORG 0100H
MAIN:SETB EA;开所有中断
SETB PX0;使int0为高级中断,start(int0高于1)
SETB PX1;使int1为高级中断,pause
SETB IT0;int0负边沿触发
SETB IT1;int1负边沿触发
MOV SP,#60H;给指针设置初始地址
MOV R0,#00H;初始化R0
MOV R1,#00H
READY:MOV A,#00000011B;开始输入数值,并使用P10和P11
MOV P1,A
MOV A,P1;读键盘状态
JB ACC0,L1;若ACC0为1,跳转至L1,否则个位键按下执行下条指令
LCALL PROM0;若个位键按下,则跳转RPOM0,并返回R0
L1:JB ACC1,L2;若ACC1为1,跳转至L2,否则个位键按下执行下条指令
LCALL PROM1;若十位键按下,则跳转RPOM1,并返回R1
L2:MOV DPTR,#DTAB;数据表格起始地址送DPTR
MOV A,R0;把R0里的数给A,用于查表偏移量
MOVC A,@A+DPTR;查表后相应数值给A
MOV P0,A;送P0口显示
MOV A,R1;把R1里的数给A,用于查表偏移量
MOVC A,@A+DPTR;查表后相应数值给A
MOV P2,A;送P2口显示
LCALL READY;跳转回READY检查是否有按键再次按下
DTAB:DB 3FH,06H,5BH,4FH,66H;共阴极数码管从0~9表
DB 6DH,7DH,07H,7FH,6FH
PROM0:LCALL DY12MS;防抖动
INC R0;若个位键按下,则使R0+1
CJNE R0,#0AH,CTN;如果R0=10,则执行下一条指令,否则跳转
MOV R0,#00H;给R0重置0
CTN:RET
PROM1:LCALL DY12MS
INC R1;若个位键按下,则使R1+1
CJNE R1,#06H,CNT;如果R1=6,则执行下一条指令,否则跳转
MOV R1,#00H;给R1重置0
CNT:RET
DY12MS:MOV R7,#18H;延时12MS子程序
DYMS1:MOV R6,#0FFH
DYMS2:DJNZ R6,DYMS2
DJNZ R7,DYMS1
RET
EINT0:PUSH ACC
PUSH PSW
CLR TR1
POP PSW
POP ACC
SETB EX0
RETI
EINT1:ANL TMOD,#0FH;计数器置为方式1,定时器模式,与INT0有关
ORL TMOD,#90H
MOV TH1,#3CH;装入时间常数,005S
MOV TL1,#0AFH
MOV B,#0AH;
MOV A,R1;
MUL AB;把十位分乘十
ADD A,R0;
MOV B,#120;005s260
MOV R3,A
MOV R4,B
SETB TR1;启T1计数
LOOP:CJNE R4,#00H,LOOP;每当过1分钟后,才进入R3
CJNE R3,#00H,L3;
SETB P30;让P30口为1,输出高电压给蜂鸣器
LCALL DY2S;让蜂鸣器鸣叫2S
RETI
L3:CLR P30;输出低电平,使蜂鸣器不工作
SJMP LOOP
TIMER1:CLR TR1;关计数控制位
DEC R4;
CJNE R4,#00H,L4;R4不为零,则R3不减
DEC R3;
L4:MOV TL1,#0AFH;装入时间常数
MOV TH1,#3CH;
SETB TR1;开计数控制位
RETI
DY2S:MOV R7,#200;延时2S子程序
DY2S1:MOV R6,#20
DY2S2:MOV R5,#124
DY2S3:DJNZ R5,DY2S3
DJNZ R6,DY2S2
DJNZ R7,DY2S1
RET
END
用KEIL C51编译通过
CODE_SEG SEGMENT CODE
DATA_SEG SEGMENT DATA
STACK_SEG SEGMENT IDATA
K1 BIT P14
K2 BIT P15
RSEG DATA_SEG
KEY_S: DS 1
KEY_V: DS 1
DIS_DIGIT: DS 1
SEC: DS 1
DIS_INDEX: DS 1
HOUR: DS 1
MIN: DS 1
SEC100: DS 1
DIS_BUF: DS 8
BUF_HOUR_H EQU DIS_BUF ; 小时十位
BUF_HOUR_L EQU DIS_BUF+1 ; 小时个位
BUF_MIN_H EQU DIS_BUF+3 ; 分十位
BUF_MIN_L EQU DIS_BUF+4 ; 分个位
BUF_SEC_H EQU DIS_BUF+6 ; 秒十位
BUF_SEC_L EQU DIS_BUF+7 ; 秒个位
RSEG STACK_SEG
STACK: DS 20
;===============================================================================
CSEG AT 0000H
JMP MAIN
CSEG AT 0000BH
LJMP TIMER0
CSEG AT 0001BH
LJMP TIMER1
;===============================================================================
RSEG CODE_SEG
MAIN:
USING 0
MOV SP, #(STACK-1) ;
MOV P0,#0FFH
MOV P2,#0FFH
MOV TMOD,#011H ; 定时器0, 1工作模式1, 16位定时方式
MOV TH0,#0FCH
MOV TL0,#017H
MOV TH1,#0DCH
CLR A
MOV TL1,A
MOV HOUR,#12 ;
CLR A ;
MOV MIN,A
MOV SEC,A
MOV SEC100,A
MOV A,HOUR
MOV B,#10
DIV AB
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_HOUR_H,A ; 时十位
MOV A,HOUR
MOV B,#10
DIV AB
MOV A,B
MOVC A,@A+DPTR
MOV BUF_HOUR_L,A ; 时个位
MOV A,MIN
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV BUF_MIN_H,A ; 分十位
MOV A,MIN
MOV B,#10
DIV AB
MOV A,B
MOVC A,@A+DPTR
MOV BUF_MIN_L,A ; 分个位
MOV A,SEC
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV BUF_SEC_H,A ; 秒十位
MOV A,SEC
MOV B,#10
DIV AB
MOV A,B
MOVC A,@A+DPTR
MOV BUF_SEC_L,A ; 秒个位
MOV BUF_HOUR_H+02H,#0BFH
MOV BUF_HOUR_H+05H,#0BFH
MOV DIS_DIGIT,#0FEH
CLR A
MOV DIS_INDEX,A
MOV IE,#08AH ; 使能timer0,1 中断
SETB TR0
SETB TR1
MOV KEY_V,#03H
MAIN_LP:
LCALL SCAN_KEY ; 键扫描
JZ MAIN_LP ; 无键返回
MOV R7,#10 ; 延时10ms
LCALL DELAYMS ; 延时去抖动
LCALL SCAN_KEY ; 再次扫描
JZ MAIN_LP ; 无键返回
MOV KEY_V,KEY_S ; 保存键值
LCALL PROC_KEY ; 键处理
SJMP MAIN_LP ; 调回主循环
;===============================================================================
SCAN_KEY:
; 扫键扫描子程序
; 保存按键状态到key_s
; 返回: A --- 按键是否按下(BOOL)
CLR A
MOV C,K1 ; 读按键K1
MOV ACC0,C
MOV C,K2 ; 读按键K2
MOV ACC1,C
MOV KEY_S,A ; 保存按键状态到key_s
XRL A,KEY_V
RET
;===============================================================================
PROC_KEY:
; 键处理子程序
; 传入参数: KEY_V --- 按键值
; 返回值: 无
CLR EA
MOV A,KEY_V
JNB ACC0,PROC_K1
JNB ACC1,PROC_K2
SJMP END_PROC_KEY
PROC_K1: ; 按键k1处理
LCALL INC_HOUR ; 小时加1
SJMP END_PROC_KEY
PROC_K2: ; 按键K2处理
INC MIN ; 分钟加1
MOV A,MIN ;
SETB C
SUBB A,#59
JC K2_UPDATE_MIN ; 如果分钟等于60,则分清0,小时加1
CLR A ;
MOV MIN,A
K2_UPDATE_MIN: ; 更新分显示缓冲区
MOV A,MIN
MOV B,#10
DIV AB ; A = MIN / 10
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_MIN_H,A ; 更新分十位
MOV A,MIN
MOV B,#10
DIV AB
MOV A,B ; A = MIN % 10
MOVC A,@A+DPTR
MOV BUF_MIN_L,A ; 更新分个位
END_PROC_KEY:
SETB EA
RET
;===============================================================================
USING 0
TIMER0:
; 定时器0中断服程序, 用于数码管的动态扫描
; DIS_INDEX --- 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量
; DIS_DIGIT --- 位选通值, 传送到P2口用于选通当前数码管的数值, 如等于0xfe时,
; 选通P20口数码管
; DIS_BUF --- 显于缓冲区基地址
PUSH ACC
PUSH PSW
PUSH AR0
MOV TH0,#0FCH
MOV TL0,#017H
MOV P2,#0FFH ; 先关闭所有数码管
MOV A,#DIS_BUF ; 获得显示缓冲区基地址
ADD A,DIS_INDEX ; 获得偏移量
MOV R0,A ; R0 = 基地址 + 偏移量
MOV A,@R0 ; 获得显示代码
MOV P0,A ; 显示代码传送到P0口
MOV P2,DIS_DIGIT
MOV A,DIS_DIGIT ; 位选通值左移, 下次中断时选通下一位数码管
RL A
MOV DIS_DIGIT,A
INC DIS_INDEX ; DIS_INDEX加1, 下次中断时显示下一位
ANL DIS_INDEX,#0x07 ; 当DIS_INDEX等于8(0000 1000)时, 清0
POP AR0
POP PSW
POP ACC
RETI
;===============================================================================
USING 0
TIMER1:
; 定时器1中断服务程序, 产生时基信号10ms
;
;
PUSH PSW
PUSH ACC
PUSH B
PUSH DPH
PUSH DPL
MOV TH1,#0DCH
INC SEC100
MOV A,SEC100
CLR C
SUBB A,#100 ; 是否中断100次(达到1s)
JC END_TIMER1 ; < 1S
MOV SEC100,#00H ; 达到1s
LCALL INC_SEC ; 秒加1
END_TIMER1:
POP DPL
POP DPH
POP B
POP ACC
POP PSW
RETI ;
;===============================================================================
INC_SEC:
INC SEC
MOV A,SEC
SETB C
SUBB A,#59 ;
JC UPDATE_SEC
CLR A
MOV SEC,A
LCALL INC_MIN
UPDATE_SEC:
MOV A,SEC
MOV B,#10
DIV AB ; A = SEC / 10
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR ;
MOV BUF_SEC_H,A ;
MOV A,SEC
MOV B,#10
DIV AB
MOV A,B ; A = SEC % 10
MOVC A,@A+DPTR
MOV BUF_SEC_L,A
RET
;===============================================================================
INC_MIN:
INC MIN ; 分钟加1
MOV A,MIN ;
SETB C
SUBB A,#59
JC UPDATE_MIN ; 如果分钟等于60,则分清0,小时加1
CLR A ;
MOV MIN,A
LCALL INC_HOUR ; 小时加1
UPDATE_MIN: ; 更新分显示缓冲区
MOV A,MIN
MOV B,#10
DIV AB ; A = MIN / 10
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_MIN_H,A ; 更新分十位
MOV A,MIN
MOV B,#10
DIV AB
MOV A,B ; A = MIN % 10
MOVC A,@A+DPTR
MOV BUF_MIN_L,A ; 更新分个位
RET
;===============================================================================
INC_HOUR:
INC HOUR ; 小时加1
MOV A,HOUR
SETB C
SUBB A,#24
JC UPDATE_HOUR ; 如果小时等于24,则小时清0
CLR A
MOV HOUR,A ; 小时清0
UPDATE_HOUR:
MOV A,HOUR
SETB C
SUBB A,#9
JC UPDATE_HOUR1 ; 如果小时小于10,则十位0不显示
MOV A,HOUR
MOV B,#10
DIV AB
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR ;
MOV BUF_HOUR_H,A
SJMP UPDATE_HOUR2
UPDATE_HOUR1:
MOV BUF_HOUR_H,#0FFH
UPDATE_HOUR2:
MOV A,HOUR
MOV B,#10
DIV AB
MOV A,B
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_HOUR_L,A
RET
;===============================================================================
DELAYMS:
; 延时子程序
; 传入参数:R7 --- 延时值(MS)
; 返回值:无
MOV A,R7
JZ END_DLYMS
DLY_LP1:
MOV R6,#185
DLY_LP2:
NOP
NOP
NOP
DJNZ R6,DLY_LP2
DJNZ R7,DLY_LP1
END_DLYMS:
RET
; END OF DELAYMS
;===============================================================================
DIS_CODE:
DB 0C0H
DB 0F9H
DB 0A4H
DB 0B0H
DB 099H
DB 092H
DB 082H
DB 0F8H
DB 080H
DB 090H
DB 0FFH
END
#include<reg52h>
#include<intrinsh>
#include<mathh>
#define uchar unsigned char
#define uint unsigned int
#define rst573 P2&=0X1F
#define y4 P2|=0X80
#define y5 P2|=0XA0
#define y6 P2|=0XC0
#define y7 P2|=0XE0
sbit s5=P3^2;
sbit s4=P3^3;
sbit s6=P3^1;
sbit s7=P3^0;
sbit scl=P1^7;
sbit IO=P2^3;
sbit rst1302=P1^3;
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code chu[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar time[8]={0xa4,0xb0,0xbf,0x90,0x90,0xbf,0xc0,0xc0};
uchar miao1,miao2,fen1,fen2,shi1,shi2,shi,fen;
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=120;j>0;j--);
}
void writebyte(uchar add,uchar date)
{
uchar i;
scl=0;
IO=0;
rst1302=1;
for(i=0;i<8;i++)
{
scl=0;
IO=add&0x01;
scl=1;
add>>=1;
}
for(i=0;i<8;i++)
{
scl=0;
IO=date&0x01;
scl=1;
date>>=1;
}
rst1302=0;
}
uchar readbyte(uchar add)
{
uchar i,temp;
scl=0;
IO=0;
rst1302=1;
for(i=0;i<8;i++)
{
scl=0;
IO=add&0x01;
scl=1;
add>>=1;
}
for(i=0;i<8;i++)
{
scl=1;
temp>>=1;
scl=0;
if(IO)
temp|=0x80;
}
return temp;
}
void set1302()
{
writebyte(0x8e,0x00);
writebyte(0x84,0x00);
writebyte(0x82,0x00);
writebyte(0x80,0x00);
writebyte(0x8e,0x80);
}
void read1302(uchar p)
{
p[0]=readbyte(0x85);
writebyte(0x84,0x00);
p[1]=readbyte(0x83);
writebyte(0x82,0x00);
p[2]=readbyte(0x81);
writebyte(0x00,0x00);
}
void zhuanghuan()
{
shi=time[0];
fen=time[1];
miao1=(time[2]/16)%10;
miao2=(time[2]%16)%10;
}
void display()
{
rst573;
P0=chu[0];
y6;
rst573;
P0=tab[shi>>4];
y7;
delay(2);
rst573;
P0=chu[1];
y6;
rst573;
P0=tab[shi&0x0f];
y7;
delay(2);
rst573;
P0=chu[3];
y6;
rst573;
P0=tab[fen>>4];
y7;
delay(2);
rst573;
rst573;
P0=chu[4];
y6;
rst573;
P0=tab[fen&0x0f];
y7;
delay(2);
rst573;
P0=chu[6];
y6;
rst573;
P0=tab[miao1];
y7;
delay(2);
rst573;
P0=chu[7];
y6;
rst573;
P0=tab[miao2];
y7;
delay(2);
rst573;
P0=chu[2];
y6;
rst573;
P0=0xbf;
y7;
delay(2);
rst573;
P0=chu[5];
y6;
rst573;
P0=0xbf;
y7;
rst573;
delay(1);
read1302(time);
zhuanghuan();
}
void jian()
{
if(s4==0)
{
delay(5);
if(s4==0)
{
while(!s4)
display();
writebyte(0x8e,0x00);
shi++;
if(shi==10) //对应BCD的0~9
shi=16;
if(shi==26) //对应BCD的10~19
shi=32;
if(shi==36) //对应BCD的19~23
shi=0;
writebyte(0x84,shi);
}
}
if(s5==0)
{
delay(5);
if(s5==0)
{
while(!s5)
display();
writebyte(0x8e,0x00);
shi--;
if(shi==-1) //对应BCD的23~20
shi=35;
if(shi==31) //对应BCD的19~10
shi=25;
if(shi==15) //对应BCD的9~0
shi=9;
writebyte(0x84,shi);
}
}
if(s6==0)
{
delay(5);
if(s6==0)
{
while(!s6)
display();
writebyte(0x8e,0x00);
fen++;
if(fen==10) //对应BCD的0~9
fen=16;
if(fen==26) //对应BCD的10~19
fen=32;
if(fen==42) //对应BCD的20~29
fen=48;
if(fen==58) //对应BCD的30~39
fen=64;
if(fen==74) //对应BCD的40~49
fen=80;
if(fen==90) //对应BCD的50~59
fen=0;
writebyte(0x82,fen);
}
}
if(s7==0)
{
delay(5);
if(s7==0)
{
while(!s7)
display();
writebyte(0x8e,0x00);
fen--;
if(fen==-1) //对应BCD的59~50
fen=89;
if(fen==79) //对应BCD的49~40
fen=73;
if(fen==63) //对应BCD的39~30
fen=57;
if(fen==47) //对应BCD的29~20
fen=41;
if(fen==31) //对应BCD的19~10
fen=25;
if(fen==15) //对应BCD的9~0
fen=9;
writebyte(0x82,fen);
}
}
}
void main()
{
set1302();
while(1)
{
jian();
display();
}
}
我来发一个C语言51单片机时钟程序,希望能帮到你 / 程序功能:带定时闹铃时钟 / /---------------------------------------------------------------/ #include /包含器件配置文件/ #define uchar unsigned char #define uint unsigned in
以上就是关于用8051单片机编写一个闹钟程序,先设置时间,然后中断开始计数,如果时间到了,则报警,但是程序有问题全部的内容,包括:用8051单片机编写一个闹钟程序,先设置时间,然后中断开始计数,如果时间到了,则报警,但是程序有问题、51单片机6位闹钟、基于51单片机电子闹钟的设计,用C语言,跪求高手等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)