用8051单片机编写一个闹钟程序,先设置时间,然后中断开始计数,如果时间到了,则报警,但是程序有问题

用8051单片机编写一个闹钟程序,先设置时间,然后中断开始计数,如果时间到了,则报警,但是程序有问题,第1张

通过了,自己对照看看问题出在哪里。

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语言,跪求高手等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9370106.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存