#include<reg51h>
#define uchar unsigned char
uchar code ledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9
unsigned char sec=0,min=0,hour=0,scanled;
unsigned char key,time;
unsigned char disdat[6];
sbit K=P1^0;
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 //秒计时
{
TR0=0;
TH0=0x3c;
TL0=0xb0;
TR0=1;
time++;
if(time==20)
{
time=0;
sec++;
if(sec>59)
{
sec=0;
min++;
if(min>59)
{
min=0;
hour++;
if(hour>23)hour=0;
}
}
}
dischg();
}
void t1isr() interrupt 3 //显示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case 0:
P2=0x01;
P0=~ledtab[disdat[5]];
break;
case 1:
P2=0x02;
P0=~ledtab[disdat[4]]&0x7f;
break;
case 2:
P2=0x04;
P0=~ledtab[disdat[3]];
break;
case 3:
P2=0x08;
P0=~ledtab[disdat[2]]&0x7f;
break;
case 4:
P2=0x10;
P0=~ledtab[disdat[1]];
break;
case 5:
P2=0x20;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
EA=1;
TR1=1;
ET0=1;
ET1=1;
sec=0;
min=0;
hour=0;
scanled=0;
time=0;
key=0;
dischg();
while(1)
{
if(K==0)
{
while(K==0);
key++;
key%=2;
}
switch(key)
{
case 0:
TR0=1;
break;
case 1:
TR0=0;
break;
}
}
}
带万年历的LCD显示多功能数字钟
程序清单:
; SMC1602接口程序(MCS51模拟口线方式)
;
;连线图: LCM---8031 LCM---8031 LCM------------8031
; DB0---P00 DB4---P04 RS-------------P20
; DB1---P01 DB5---P05 RW-------------P21
; DB2---P02 DB6---P06 E--------------P22
; DB3---P03 DB7---P07 VLCD接10K可调电阻到GND
;注:8051的晶振频率为110592MHz R0设置数据存放 S8为设置键 S7为加键 S4为确认键
;
;P0口液晶显示
; P24位选键P23加一键P22返回键及报时功能键闹钟设置P20控制显示键
;寄存器 clr rs0 setb rs1 R0 R4 R5在按键中用到 延时中用到 SETB RS0 SETB RS1的R0 R1 R2
;SETB RS0 CLR RS1显示中用到 CLR RS0 CLR RS1 在闹钟调整子程序中用到R1
;
;
;报时功能P26 和闹钟功能P25 闹钟调整时间功能已经可以设置 显示的切换方式变了 再关闭的情况下一切正常运行
;
RSPIN BIT P12
RWPIN BIT P11
EPIN BIT P10
WEIXUAN BIT P24 ;位选键设置键
JIAJIAN BIT P23 ;加一键
JIANJIAN BIT P22 ;减一键
FANHUI BIT P21 ;返回键
NZKG BIT P20 ;闹钟设置键
SECONTL EQU 30H ;秒
SECONTH EQU 31H ;秒
MAOHAOL EQU 32H ;:
MINIUTL EQU 33H ;分
MINIUTH EQU 34H ;分
MAOHAOH EQU 35H ;:
HOURL EQU 36H ;时
HOURH EQU 37H ;时
;日期部分
DAYL EQU 40H ;日个
DAYH EQU 41H ;日十
HENL EQU 42H ;-
MONTHL EQU 43H ;yue
MONTHH EQU 44H ;yue
HENH EQU 45H ;-
YEARO EQU 46H ;年
YEART EQU 47H
YEARS EQU 48H
YEARF EQU 49H
TEMP EQU 50H ;用做存储单元显示子程序(DISPLAY)里用到
BIJIAO EQU 51H ;加一子程序(JIAYI)中用到
ZDRQO EQU 55H ;中断加一程序中用到
ZDRQT EQU 56H ;中断加一程序中用到
ZDRQS EQU 57H ;中断加一程序中用到
ZDRQF EQU 58H ;中断加一程序中用到
DIZHI EQU 59H ;键盘(JIANPAN)子程序里用到
NZBZ BIT 60H ;定时标志位在(闹钟开关部分)
;38H到3FH没用到
BSCSBZ BIT 39H ;报时次数转换标志 (BSCS)里用到
BSCSCC EQU 3AH ;报时次数存储 (BSCS)里用到
ZDBSBZ BIT 3BH ;整点报时标志 (SSBS)里用到
ZMBSBZ BIT 3CH ;整秒闪烁标志 (SSBS)里用到
BSKGBZ BIT 3DH ;报时开启标志 (BSKG)里用到
XKQHBZ BIT 3EH ;显示开启关闭标志 (XIANKONG)里用到
ORG 0000H
AJMP MAIN
ORG 000BH
AJMP ZD
ORG 0030H
MAIN: MOV SP,#60H ;给堆栈指针赋初值
MOV 30H,#05H ;秒
MOV 31H,#05H ;秒
MOV 32H,#3AH ;:
MOV 33H,#09H ;分
MOV 34H,#05H ;分
MOV 35H,#3AH ;:
MOV 36H,#03H ;时
MOV 37H,#01H ;时
;日期部分
MOV 40H,#09H ;日个
MOV 41H,#02H ;日十
MOV 42H,#2DH ;-
MOV 43H,#09H ;yue
MOV 44H,#00H ;yue
MOV 45H,#2DH ;-
MOV 46H,#09H ;年
MOV 47H,#09H
MOV 48H,#09H
MOV 49H,#02H
CLR P25 ;闹钟
CLR P26 ;整点报时
MOV 03H,#00H ;闹钟分个位
MOV 04H,#00H ;闹钟分十位
MOV 06H,#04H ;闹钟时个位
MOV 07H,#01H ;闹钟时十位
;CLR P15
;CLR P14
MOV B,#20
MOV TMOD,#01H ;定时器工作方式1
MOV TH0,#4CH
MOV TL0,#08H
SETB ET0 ;允许T0中断
SETB EA ;总中断开放
LCALL LCDRESET ;初始化LCD
LCALL DISPSTART ;调用显示初始状态
SETB TR0 ;开启定时器
CLR NZBZ ;闹钟开启关闭标志
CLR BSKGBZ ;报时开启关闭标志
CLR XKQHBZ ;显示开启关闭标志
LOOP: LCALL JIANPAN ;按键子程序
LCALL DISPLAY ;显示子程序
LCALL NZBF ;NAOZHONG BUFENG
LCALL NZBJ ;NAOZHONG BIJIAO
LCALL BSKG ;BAOSHIKAIGUAN
LCALL BSCS ;BAOSHICISHU
LCALL SSBS ;闪烁报时
SJMP LOOP
;==============================中断加一程序===================================
ZD: PUSH ACC
MOV TH0,#4CH
MOV TL0,#08H
DJNZ B,ZDEND
MOV B,#20
INC SECONTL
SETB ZMBSBZ
MOV A,SECONTL
CJNE A,#0AH,ZDEND
MOV SECONTL,#00H
INC SECONTH
MOV A,SECONTH
CJNE A,#06H,ZDEND
MOV SECONTH,#00H
INC MINIUTL
MOV A,MINIUTL
CJNE A,#0AH,ZDEND
MOV MINIUTL,#00H
INC MINIUTH
MOV A,MINIUTH
CJNE A,#06H,ZDEND
MOV MINIUTH,#00H
INC HOURL
SETB BSCSBZ
SETB ZDBSBZ
MOV A,HOURL ;24小时的判断
CJNE A,#04H,ZDF
MOV A,HOURH
CJNE A,#02H,ZDEND
MOV HOURL,#00H
MOV HOURH,#00H
LCALL ZDRQ
SJMP ZDEND
ZDF: CJNE A,#0AH,ZDEND
MOV HOURL,#00H
INC HOURH
ZDEND: POP ACC
RETI
;日期部分
ZDRQ: PUSH ACC
INC DAYL
;判断天数28,30,31部分
MOV A,MONTHH ;用于判断月份时为31天30天28天
CJNE A,#01H,LL
MOV 55H,#0AH ;存放月份的十位转化为个位是0AH
MOV A,MONTHL
ADD A,55H ;月分高低相加用于查表
SJMP LL3
LL: MOV A,MONTHL
ADD A,MONTHH
LL3: MOV 56H,A ;存放相加后的月份数据
MOV DPTR,#TAB5
MOVC A,@A+DPTR ;查十位和天数的十位比较
MOV 57H,A
MOV A,56H
MOV DPTR,#TAB6 ;查个位和天数的个位比较
MOVC A,@A+DPTR
MOV 58H,A
MOV A,DAYH
CJNE A,57H,LL2
MOV A,DAYL
CJNE A,58H,LL2
MOV DAYH,#00H
MOV DAYL,#01H
SJMP LL4
LL2: MOV A,DAYL
CJNE A,#0AH,ZDRQEND
MOV DAYL,#00H
INC DAYH
MOV A,DAYH ;比较天数是否要进位
CJNE A,57H,ZDRQEND
MOV A,DAYL
CJNE A,58H,ZDRQEND
MOV DAYH,#00H
MOV DAYL,#01H
;月份和年份
LL4: INC MONTHL
MOV A,MONTHL
CJNE A,#03H,ZDRQ1 ;用于判断月份时为12月时进位
MOV A,MONTHH
CJNE A,#01H,ZDRQ1
MOV MONTHL,#01H ;天数符合要求
MOV MONTHH,#00H
SJMP ZDRQ2
ZDRQ1: CJNE A,#0AH,ZDRQEND
MOV MONTHL,#00H
INC MONTHH
SJMP ZDRQEND
ZDRQ2: INC YEARO ;年的加一
MOV A,YEARO
CJNE A,#0AH,ZDRQEND
MOV YEARO,#00H
INC YEART ;年的进位
MOV A,YEART
CJNE A,#0AH,ZDRQEND
MOV YEART,#00H
INC YEARS
MOV A,YEARS
CJNE A,#0AH,ZDRQEND
MOV YEARS,#00H
INC YEARF
MOV A,YEARF
CJNE A,#0AH,ZDRQEND
MOV YEARF,#00H
ZDRQEND:
POP ACC
RET
;液晶初始化
;========================初始化程序=======================================
LCDRESET: ;初始化程序
LCALL DELAY5MS ;延时15MS
LCALL DELAY5MS
LCALL DELAY5MS
MOV A,#38H ;显示模式设置(不检测忙信号)
LCALL LCDWCN ;共三次
LCALL DELAY5MS
MOV A,#38H
LCALL LCDWCN
LCALL DELAY5MS
MOV A,#38H
LCALL LCDWCN
MOV A,#38H ;显示模式设置(以后均检测忙信号)
LCALL LCDWC
MOV A,#08H ;显示关闭
LCALL LCDWC
MOV A,#01H ;显示清屏
LCALL LCDWC
MOV A,#06H ;显示光标移动设置
LCALL LCDWC
MOV A,#0CH ;显示开及光标设置
LCALL LCDWC
RET
;==============================写指令===================================
LCDWC: ;送控制字子程序(检测忙信号)
LCALL WAITIDLE
;写指令;送控制字子程序(不检测忙信号)
LCDWCN: CLR RSPIN ;RS=0 RW=0 E=高脉冲
CLR RWPIN
MOV P0,A
SETB EPIN ;(
NOP ;给高电平脉冲
CLR EPIN ;)
RET
;==========================写数据=======================================
LCDWD: ;写字符子程序
LCALL WAITIDLE
SETB RSPIN ;RS=1 RW=0 E=高脉冲
CLR RWPIN
MOV P0,A
SETB EPIN
NOP
CLR EPIN
RET
;===============================等待控制器空闲==================================
WAITIDLE:
PUSH ACC ;正常读写 *** 作之前必须检测LCD控制器状态
MOV P0,#0FFH
lcall DELAY5MS ;4566666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
CLR RSPIN ;RS=0 RW=1 E=高电平
SETB RWPIN
SETB EPIN
lcall DELAY5MS ;465555546465464654648791313848946113134849845461313579641613131354649498
WTD_PA: NOP ;DB7: 0 LCD控制器空闲
JB P07,WTD_PA ; 1 LCD控制器忙
CLR EPIN
POP ACC
RET
;初始状态子程序
DISPSTART: ;显示初始状态子程序
PUSH ACC
MOV A,#80H
LCALL LCDWC
MOV DPTR,#TAB ;显示字符
DISP1: CLR A
MOVC A,@A+DPTR
JZ DISP2
LCALL LCDWD
INC DPTR
SJMP DISP1
DISP2: MOV A,#0C0H
LCALL LCDWC
MOV DPTR,#TAB1
DISP3: CLR A
MOVC A,@A+DPTR
JZ DISP_END
LCALL LCDWD
INC DPTR
SJMP DISP3
DISP_END:
POP ACC
RET
;==========================显示子程序=======================================
DISPLAY:PUSH PSW
PUSH ACC
SETB RS0
CLR RS1
MOV A,#85H
LCALL LCDWC
MOV R1,#38H ;第一行显示数据存储单元的启始地址
MOV TEMP,#30H ;第一行显示数据存储单元的结束地址
MOV R6,#2
PLAY: DEC R1
CJNE R1,#32H,PLY ;判断是否为冒号位
MOV A,MAOHAOL ;是者送冒号的ACSI码
SJMP PLAY1
PLY: CJNE R1,#35H,PLY1
MOV A,MAOHAOH
SJMP PLAY1
PLY1: CJNE R1,#42H,PLY2 ;判断是否为横杠的位置
MOV A,HENL ;是者送横杠的ACSI码
SJMP PLAY1
PLY2: CJNE R1,#45H,PLY3
MOV A,HENH
SJMP PLAY1
PLY3: MOV A,@R1 ;用查表法送要显示的数据
MOV DPTR,#TAB2
MOVC A,@A+DPTR
PLAY1: LCALL LCDWD
MOV A,R1
CJNE A,TEMP,PLAY ;判断第一行是否显示好了
MOV A,#0C5H
LCALL LCDWC
MOV R1,#4AH ;第二行显示数据存储单元的启始地址
MOV TEMP,#40H ;第二行的结束地址
DJNZ R6,PLAY ;R6为0时两行显示结束
POP ACC
POP PSW
RET
;按键子程序
JIANPAN:clr rs0 ;键盘子程序
setb rs1 ;键盘子程序
JB WEIXUAN,JIAN_ZEND ;设置键的判断
LCALL DELAY5MS
JB WEIXUAN,JIAN_ZEND
PUSH ACC
JNB WEIXUAN,$
;MOV A,#0FH ;开启光标闪烁设置
;LCALL LCDWCN
fah: JNB NZBZ,JPNZSJ ;为“1”闹钟 为“0”时钟
LCALL JPXS
MOV R4,#86H ;闹钟设定时间R4存放显示位地址
MOV R5,#2 ;闹钟设定时间第一行第二行•••••位置改变次数
MOV DIZHI,#8CH ;闹钟设定时间第一行结束地址
MOV R0,#06H
SJMP GIVED
JPNZSJ: CLR TR0
MOV R4,#86H ;R4存放显示位地址
MOV R5,#2 ;第一行第二行•••••位置改变次数
MOV DIZHI,#8DH ;第一行结束地址
MOV R0,#36H
GIVED: MOV A,#0FH ;开启光标闪烁设置555555555555555555555555555555555555555555555
LCALL LCDWCN
MOV A,R4
LCALL LCDWC
UPONE: JB FANHUI,UPtwo ;返回键的判断
LCALL DELAY5MS
JB FANHUI,UPtwo
JNB FANHUI,$
SJMP GOBACK
JIAN_ZEND:SJMP JIAN_END ;中继跳转6666666666666666666666666666666666666666666666666666666666666666
UPtwo: JB JIAJIAN,IAM ;加一键的判断
LCALL DELAY5MS
JB JIAJIAN,IAM
JNB JIAJIAN,$
LCALL JIAYI ;调用按键加一子程序
;MOV A,#0FH ;开启光标闪烁设置555555555555555555555555555555555555555555555
;LCALL LCDWCN
IAM: JB JIANJIAN,IAM22 ;减一键的判断
LCALL DELAY5MS
JB JIANJIAN,IAM22
JNB JIANJIAN,$
LCALL JIANYI ;调用按键减一子程序
AJMP GIVED
IAM22: JB WEIXUAN,UPONE ;位选键的判断
LCALL DELAY5MS
JB WEIXUAN,UPONE
JNB WEIXUAN,$
DEC R0
INC R4
LCALL JIAN ;调用位选比较程序
CJNE r4,#88H,JJ11
DEC R0
INC R4
SJMP JJ22
JJ11: CJNE r4,#8BH,JJ22
DEC R0
INC R4
JJ22: MOV A,R4
CJNE A,DIZHI,GIVED
JB NZBZ,fah ;为“1”闹钟 为“0”时钟
MOV R4,#0C5H
MOV DIZHI,#0CFH
MOV R0,#49H
DJNZ R5,GIVED
LJMP fah
GOBACK: MOV A,#0CH ;关闭光标闪烁设置
LCALL LCDWCN
POP ACC
JIAN_END:
SETB TR0
RET
;1111111111111111111111111111111111111111111111111111111111111111111111111111
;11111111111111111111111111111111111111111111111111111111111111111111111111
JPXS: MOV A,#85H
LCALL LCDWC
MOV R1,#08H ;第一行显示数据存储单元的启始地址
JPXS_LL:DEC R1
CJNE R1,#05H,JPXS_LP
MOV A,#3AH
SJMP JPXS_LY
JPXS_LP:MOV A,@R1 ;用查表法送要显示的数据
MOV DPTR,#TAB2
MOVC A,@A+DPTR
JPXS_LY:LCALL LCDWD
CJNE R1,#03H,JPXS_LL
RET
;111111111111111111111111111111111111111111111111111111111111111111111
;111111111111111111111111111111111111111111111111111111111111111111111
;位选比较控制程序
; 在调整时间时这几位是符号冒号和横杠的数据
;在这几位时跳过到下一位
JIAN: CJNE R4,#87H,JIAN5
DEC R0
INC R4
SJMP JIANEND
JIAN5: CJNE R4,#8AH,JIAN1
DEC R0
INC R4
SJMP JIANEND
JIAN1: CJNE R4,#0C9H,JIAN2
DEC R0
INC R4
SJMP JIANEND
JIAN2: CJNE R4,#0CCH,JIANEND
DEC R0
INC R4
JIANEND:RET
;按键加一子程序
JIAYI: INC @R0
CJNE @R0,#0AH,JIAYI_END
MOV @R0,#0
CJNE R4,#86H,JIAYI55
SJMP JIAYI33
JIAYI55:CJNE r4,#89H,JIAYI11
SJMP JIAYI33
JIAYI11:CJNE r4,#8CH,JIAYI22
SJMP JIAYI33
JIAYI22:CJNE R0,#30H,JIAYI_END
JIAYI33:INC R0
INC @R0
CJNE @R0,#06H,JIAYI44
MOV @R0,#0
JIAYI44:DEC R0
JIAYI_END:MOV A,#0CH ;开启光标闪烁设置
LCALL LCDWCN
JNB NZBZ,JIAYI88 ;为“1”闹钟 为“0”时钟
LCALL JPXS
SJMP JIAYI99
JIAYI88:LCALL DISPLAY ;显示子程序
JIAYI99: RET
;%%%%%%%%%%%%%%%%%%减一%%%%%%%%%%%%%%%%%%%%%%%%
JIANYI: DEC @R0
CJNE @R0,#00H,JIANYI_END
MOV @R0,#9
CJNE R4,#86H,JIANYI55
SJMP JIANYI33
JIANYI55:CJNE r4,#89H,JIANYI11
SJMP JIANYI33
JIANYI11:CJNE r4,#8CH,JIANYI22
SJMP JIANYI33
JIANYI22:CJNE R0,#30H,JIANYI_END
JIANYI33:INC R0
DEC @R0
CJNE @R0,#0FFH,JIANYI44
MOV @R0,#5
JIANYI44:DEC R0
JIANYI_END:MOV A,#0CH ;开启光标闪烁设置
LCALL LCDWCN
JNB NZBZ,JIANYI88 ;为“1”闹钟 为“0”时钟
LCALL JPXS
SJMP JIANYI99
JIANYI88: LCALL DISPLAY ;显示子程序
JIANYI99: RET
;闹钟开关部分
NZBF: JB NZKG,NZBF_END
LCALL DELAY5MS
JB NZKG,NZBF_END
JNB NZKG,$
CPL NZBZ
JB NZBZ,NZBF_LL
MOV A,#01H ;显示清屏
LCALL LCDWC
CLR P25
LCALL DISPSTART ;调用显示初始状态
LCALL DISPLAY ;调用显示初始状态
JB BSKGBZ,NZBF_LP ; |
SJMP NZBF_END ; |
NZBF_LP:MOV A,#8FH ;报时标志显示位置 ; |
LCALL LCDWC ; |保护报时标志在清屏是不被误清
MOV A,#25H ;显示报时标志 ; |
LCALL LCDWD ; |
SJMP NZBF_END ; |
NZBF_LL:MOV A,#8EH ;闹钟标志显示位置
LCALL LCDWC
MOV A,#26H ;显示闹钟标志
LCALL LCDWD
NZBF_END:RET
;闹钟比较部分
NZBJ: JB NZBZ,NZBJ_LL
SJMP NZBJ_END
NZBJ_LL:MOV A,07H
CJNE A,37H,NZBJ_END
MOV A,06H
CJNE A,36H,NZBJ_END
MOV A,04H
CJNE A,34H,NZBJ_END
MOV A,03H
CJNE A,33H,NZBJ_END
SETB P25
NZBJ_END:RET
;报时开关
BSKG: JB FANHUI,BSKG_END
LCALL DELAY5MS
JB FANHUI,BSKG_END
JNB FANHUI,$
CPL BSKGBZ
JB BSKGBZ,BSKG_LL
MOV A,#01H ;显示清屏
LCALL LCDWC
CLR P26
LCALL DISPSTART ;调用显示初始状态
LCALL DISPLAY ;调用显示
JB NZBZ,BSKG_LP ; |
SJMP BSKG_END ; |
BSKG_LP:MOV A,#8EH ; |
LCALL LCDWC ; |保护闹钟标志在清屏是不被误清
MOV A,#26H ; |
LCALL LCDWD ; |
SJMP BSKG_END ; |
BSKG_LL:MOV A,#8FH ;报时标志显示位置
LCALL LCDWC
MOV A,#25H ;显示报时标志
LCALL LCDWD
BSKG_END:RET
;报时次数
BSCS: JNB BSKGBZ,BSCS_END
JNB BSCSBZ,BSCS_END
MOV A,37H
CJNE A,#01H,BSCS_LL
MOV A,#0AH
SJMP BSCS_LP
BSCS_LL:CJNE A,#02H,BSCS_LP
MOV A,#14H
BSCS_LP:ADD A,36H
RL A
MOV BSCSCC,A
CLR BSCSBZ
BSCS_END: RET
;闪烁报时
SSBS: JNB BSKGBZ,SSBS_END
JNB ZDBSBZ,SSBS_END
JNB ZMBSBZ,SSBS_END
CPL P26
CPL P27
CLR ZMBSBZ
DJNZ BSCSCC,SSBS_END
CLR ZDBSBZ
CLR P26
SSBS_END:RET
;延时子程序(5MS)
DELAY5MS:
PUSH PSW
SETB RS0
SETB RS1
MOV R1,#25 ;延时子程序(5MS)
DL5_PA: MOV R2,#100
DJNZ R2,$
DJNZ R1,DL5_PA
POP PSW
RET
TAB: DB "TIME:",00h
TAB1: DB "DATE:",00h
TAB2: DB "01234567891"
TAB3: DB 0AH,06H,00H,0AH,06H,00H,0AH,03H ;用于比较调整时间时的比较
TAB4: DB 0AH,04H,00H,0AH,02H,00H,0AH,0AH,0AH,0AH;用于调整日期时的比较
TAB5: DB 00H,03H,02H,03H,03H,03H,03H,03H,03H,03H,03H,03H,03H;用于天数十位比较
TAB6: DB 00H,02H,09H,02H,01H,02H,01H,02H,02H,01H,02H,01H,02H;用于天数个位比较
END
给个我以前写的程序,你参考参考,我这个使用1602液晶写的,显示方式需要改改
#include "1602yejingh"
sbit key1=P3^2; //选择调整位置按钮
sbit key2=P3^3; //加一按钮
sbit key3=P3^4; //减一按钮
sbit key4=P3^5; //定时按钮
char shi,fen,miao,T_shi,T_fen,T_miao;
uchar count,keynum,flag;
uchar code table1[]=" 2011-12-26 1";
uchar code table2[]=" 10:30:30";
uchar code table3[]="input the timing";
uchar code table4[]=" 00:00:00";
void write_sfm(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0xc0+add);
write_date(shi+'0');
write_date(ge+'0');
}
void init()
{
uchar num;
shi=10;
fen=30;
miao=30;
P1=0xfe;
write_com(0x38);//显示模式
write_com(0x0c);//不显示光标,光标不闪烁
write_com(0x06);//地址指针加一,光标加一
write_com(0x01);//清屏
write_com(0x80);
for(num=0;num<16;num++)
{
write_date(table1[num]);
delay(5);
}
write_com(0xc0);
for(num=0;num<12;num++)
{
write_date(table2[num]);
delay(5);
}
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void keyscan()
{
uchar i;
if(key4==0)
{
delay(5);
if(key4==0)
{
while(!key4);
flag=1;
write_com(0x80);
for(i=0;i<16;i++)
{
write_date(table3[i]);
delay(5);
}
write_com(0xc0);
for(i=0;i<12;i++)
{
write_date(table4[i]);
delay(5);
}
}
}
if(key1==0)
{
delay(5);
if(key1==0)
{
while(!key1);
keynum++;
if(keynum==1)
{
if(flag==0) TR0=0;
write_com(0xc0+11);
write_com(0x0f);
}
if(keynum==2)
{
write_com(0xc0+8);
write_com(0x0f);
}
if(keynum==3)
{
write_com(0xc0+5);
write_com(0x0f);
}
if(keynum==4)
{
write_com(0x0c);
TR0=1;
if(flag==0)
{
keynum=0;
}
if(flag==1)
{
flag=0;
write_com(0x80);
for(i=0;i<16;i++)
{
write_date(table1[i]);
delay(5);
}
write_sfm(4,shi);
write_sfm(7,fen);
write_sfm(10,miao);
}
}
}
}
if(keynum!=0)
{
if(key2==0)
{
delay(5);
if(key2==0)
{
// while(!key2);
if(keynum==1)
{
if(flag==0)
{
miao++;
if(miao==60) miao=0;
write_sfm(10,miao);
write_com(0xc0+10);
delay(300);
}
if(flag==1)
{
T_miao++;
if(T_miao==60) T_miao=0;
write_sfm(10,T_miao);
write_com(0xc0+10);
delay(300);
}
}
if(keynum==2)
{
if(flag==0)
{
fen++;
if(fen==60) fen=0;
write_sfm(7,fen);
write_com(0xc0+7);
delay(300);
}
if(flag==1)
{
T_fen++;
if(T_fen==60) T_fen=0;
write_sfm(7,T_fen);
write_com(0xc0+7);
delay(300);
}
}
if(keynum==3)
{
if(flag==0)
{
shi++;
if(shi==24) shi=0;
write_sfm(4,shi);
write_com(0xc0+4);
delay(300);
}
if(flag==1)
{
T_shi++;
if(T_shi==24) T_shi=0;
write_sfm(4,T_shi);
write_com(0xc0+4);
delay(300);
}
}
}
}
if(key3==0)
{
delay(5);
if(key3==0)
{
// while(!key3);
if(keynum==1)
{
if(flag==0)
{
miao--;
if(miao==-1) miao=59;
write_sfm(10,miao);
write_com(0xc0+10);
delay(300);
}
if(flag==1)
{
T_miao--;
if(T_miao==-1) T_miao=59;
write_sfm(10,T_miao);
write_com(0xc0+10);
delay(300);
}
}
if(keynum==2)
{
if(flag==0)
{
fen--;
if(fen==-1) fen=59;
write_sfm(7,fen);
write_com(0xc0+7);
delay(300);
}
if(flag==1)
{
T_fen--;
if(T_fen==-1) T_fen=59;
write_sfm(7,T_fen);
write_com(0xc0+7);
delay(300);
}
}
if(keynum==3)
{
if(flag==0)
{
shi--;
if(shi==-1) shi=23;
write_sfm(4,shi);
write_com(0xc0+4);
delay(300);
}
if(flag==1)
{
T_shi--;
if(T_shi==-1) T_shi=23;
write_sfm(4,T_shi);
write_com(0xc0+4);
delay(300);
}
}
}
}
}
}
void main()
{
init();
while(1)
{
keyscan();
if(miao==T_miao&&fen==T_fen&&shi==T_shi)
{
P1=0xff;
}
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==16)
{
count=0;
P1=0xfe;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
if(flag==0) write_sfm(4,shi);
}
if(flag==0) write_sfm(7,fen);
}
if(flag==0) write_sfm(10,miao);
}
}
头文件
#ifndef _1602yejing_H_
#define _1602yejing_H_
#include<reg52h>
#define uchar unsigned char
#define uint unsigned int
sbit E=P2^7;
sbit RW=P2^6;
sbit RS=P2^5;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=148;y>0;y--);
}
void write_com(uchar com)//写命令函数
{
P0=com;
RS=0;
RW=0;
E=0;
delay(5);
E=1;
delay(5);
}
void write_date(uchar date)//写数据函数
{
P0=date;
RS=1;
RW=0;
E=0;
delay(5);
E=1;
delay(5);
}
#endif
#include<reg52h>
#include<defineh>
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void didi()
{
beep=0;
delay(50);
beep=1;
delay(100);
beep=0;
delay(50);
beep=1;
}
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;
EA=1;
EX0=1;
IT0=1;
dula=0;
wela=0;
lcden=0;
// set_time();
set_alarm(14,13,10);
write_ds(0x0B,0x26);
read_ds(0x0c);
// 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);
}
}
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(flag1==1)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
flag1=0;
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
flag1=0;
}
}
}
if(s1==0)
{
delay(5);
if(s1==0)
{ s1num++;
flag=1;
flag1=0;
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);
flag=0;
write_ds(0,miao);
write_ds(2,fen);
write_ds(4,shi);
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(1);
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(1);
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 write_ds(uchar add,uchar date)
{
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsrw=0;
P0=date;
dsrw=1;
dsas=1;
dscs=1;
}
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
ds_date=P0;
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}
void set_time()
{
write_ds(4,10);
write_ds(2,32);
}
void set_alarm(uchar ashi,uchar afen,uchar amiao)
{
write_ds(1,amiao);
write_ds(3,afen);
write_ds(5,ashi);
}
void main()
{
init();
while(1)
{
keyscan();
if(flag1==1)
didi();
if(flag==0)
{
miao=read_ds(0);
fen=read_ds(2);
shi=read_ds(4);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
}
}
}
void exter() interrupt 0
{ uchar c;
flag1=1;
c=read_ds(0x0c);
}
以上就是关于求一个简单的单片机时钟程序全部的内容,包括:求一个简单的单片机时钟程序、基于单片机多功能数字钟、C语言编程,数码管显示时钟跟设置闹钟的程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)