单片机源程序如下:
- ;初始化
- P_Lcd equ P0 ;液晶lcd数据总线
- pq equ p3 ;按键接口
- pf bit p2.5 ;蜂鸣器接口
- led bit p2.0 ;led灯指示接口
- lcdrs bit p2.6 ;lcdrs=1选择数据寄存器,lcdrs=0选择指令寄存器
- lcdrw bit p2.5 ;lcdrw=1进行读操作,lcdrw=0进行写操作
- lcde bit p2.7 ;lcdep由1-->0 时,液晶模块执行命令
- sclk bit p3.6 ;时钟芯片时钟线引脚
- io bit p3.4 ;时钟芯片数据传输线引脚
- rst bit p3.5 ;时钟芯片复位线引脚
- IsSheZhi bit 30h ;设置状态标示位
- BJ bit 31h ;比较标示位
- QH bit 32h ;切换标示位
- bs bit 33h ;报时功能标示位
- cxbs bit 34h ;执行报时标志位
- sec equ 50h
- min equ 51h
- hour equ 52h
- day equ 53h
- week equ 54h
- month equ 55h
- year equ 56h
- KeyCode equ 57h ;按键1功能子程序序号存储地址
- jiepai equ 58h ;存放报时声音的节拍常数
- chuzhi equ 59h ;报时开始秒时间常数
- shengshu equ 5ah ;存放报时声数
- DspBuf equ 60h ;当前时间拆字后存储首地址
- dspba equ 70h ;闹钟时间首地址
- org 0h
- ljmp main
- org 00bh
- ljmp sub1
- org 01bh
- ljmp sub2
- org 30h
- ;主程序
- main:
- clr IsSheZhi
- clr QH
- setb BJ
- setb bs
- setb cxbs
- mov KeyCode,#00h
- mov sp ,#30h
- mov year,#16h ;为当前时间赋初值
- mov month,#06h
- mov week,#4h
- mov day,#30h
- mov hour,#00h
- mov min,#00h
- mov sec,#00h
- mov DspBuf-1,#0h
- mov DspBuf-2,#02h
- mov jiepai,#80h ;设置节拍常数
- mov chuzhi,#00h ;设置1秒时开始报时
- mov dspba+0,#00h ;为闹钟时间赋初值
- mov dspba+1,#09h
- mov dspba+2,#0h
- mov dspba+3,#0h
- mov TH0,#0ffh
- mov TL0,#0ffh
- mov TH1,#0ffh
- mov TL1,#0ffh
- mov IE,#8aH
- mov TMOD,#11h
- setb pf
- acall lcd_init ;调LCM的初始化程序
- lcall word ;把自创字符写入CGRAM的子程序
- lcall set1302 ;DS1302初始化
- mainloop:
- jb IsSheZhi, SheZhi ;判断是否处于设置状态,处于设置状态则跳转
- lcall get1302 ;调读时间子程序
- lcall chaizi
- lcall display ;调显示子程序,显示当前时间与温度
- SheZhi:
- jb BJ,xq ;判断闹钟功能是否开启,未开启则跳转
- lcall bijiao ;调比较子程序,比较当前时间与闹钟时间
- xq:
- lcall anjian ;按键扫描
- jb bs,bs_1
- lcall zhengshi ;判断当前时间是否是整时,即能否报时
- bs_1:
- jb cxbs,cx_1
- lcall baoshi ;执行报时功能
- cx_1:
- sjmp mainloop
- ;液晶显示初始化设定
- lcd_init:
- mov a,#01h ;清除LCD的显示内容(清屏)
- acall LcdWrCmd
- mov a,#6 ;10ms延时
- acall delay
- mov a,#38h ;显示模式设置(使用8位数据,显示两行,使用5*7的字型)
- acall LcdWrCmd
- mov a,#6
- acall delay
- mov a,#0ch ;显示开及光标设置(显示器开,光标关,字符不闪烁)
- acall LcdWrCmd
- mov a,#6
- acall delay
- mov a,#06h ;显示光标移动设置(字符不动,光标自动右移)
- acall LcdWrCmd
- mov a,#6
- acall delay
- ret
- ;LCM命令嵌入
- LcdWrCmd:
- ACALL CMBUSY
- clr LCDRW
- clr LCDRS
- mov P_Lcd, A
- mov a,#6
- acall delay
- setb LcdE
- mov a,#6
- acall delay
- clr LcdE
- ret
- ;LCM数据输入
- LcdWrDat:
- ACALL CMBUSY
- setb LCDRS
- clr LCDRW
- mov P_Lcd, A
- mov a,#6
- acall delay
- setb LcdE
- mov a,#6
- acall delay
- clr LcdE
- ret
- ;延时子程序
- delay:
- mov r7,a ;设置a为自定义变量,可省去其他延时程序的编写
- d2: mov r6,#250 ;设置1ms延时
- d1:
- nop
- nop
- djnz r6,d1
- djnz r7,d2
- ret
- CMBUSY:
- PUSH ACC
- MOV P0,#0FFH
- CLR LCDRS
- SETB LCDRW
- SETB LcdE
- LOOP1:
- NOP
- JB P0.7,LOOP1
- CLR LcdE
- POP ACC
- RET
- ;ds1302初始化程序set1302
- set1302:
- mov a,#8eh ;写ds1302控制寄存器地址
- mov b,#00h ;允许写操作,将WP位设置为低电平
- lcall clockwr
- mov a,#8ch ;写年初值
- mov b,year
- lcall clockwr
- mov a,#88h ;写月初值
- mov b,month
- lcall clockwr
- mov a,#8ah ;写星期初值
- mov b,week
- lcall clockwr
- mov a,#86h ;写日期初值
- mov b,day
- lcall clockwr
- mov a,#84h ;写时初值
- mov b,hour
- lcall clockwr
- mov a,#82h ;写分初值
- mov b,min
- lcall clockwr
- mov a,#80h ;写秒初值
- mov b,sec
- lcall clockwr
- ret
- ;读时间子程序get1302
- get1302:mov a,#81h ;读秒
- lcall clockrd
- mov sec,a
- mov a,#83h ;读分
- lcall clockrd
- mov min,a
- mov a,#85h ;读时
- lcall clockrd
- mov hour,a
- mov a,#87h ;读日
- lcall clockrd
- mov day,a
- mov a,#8bh ;读星期
- lcall clockrd
- mov week,a
- mov a,#89h ;读月
- lcall clockrd
- mov month,a
- mov a,#8dh ;读年
- lcall clockrd
- mov year,a
- ret
- ;ds1302读子程序
- clockrd:clr rst ;rst先设置低电平,再设置高电平,起到去乱码作用
- clr sclk ;sclk置为低电平
- setb rst ;rst置为高电平,选通DS1302
- mov r7,#8 ;串行移位传送次数
- rds1:
- rrc a
- mov io,c ;输出一位寄存器读地址
- setb sclk ;发串行脉冲
- nop
- nop
- clr sclk ;sclk置为低电平
- djnz r7,rds1
- nop ;延时,防后面串行读数据丢失
- nop
- setb io ;8位地址输出完毕,IO设置为输入端口
- mov r7,#8
- rds2:
- mov c,io ;读入一位数据
- rrc a
- setb sclk ;发串行脉冲
- nop
- nop
- clr sclk
- djnz r7,rds2
- clr rst
- setb sclk
- ret
- ;ds1302写数据子程序
- clockwr:
- push acc ;设置堆栈,入栈
- push b
- clr rst
- clr sclk
- setb rst ;选通DS1302
- mov r7,#8
- wrs1:
- rrc a
- mov io,c ;输出一位寄存器写地址
- clr sclk ;发串行输出脉冲
- setb sclk
- djnz r7,wrs1
- nop
- mov a,b ;将待写入数据送A
- mov r7,#8
- wrs2:
- rrc a
- mov io,c ;经IO输出一位数据
- clr sclk
- setb sclk
- djnz r7,wrs2
- pop b ;出栈
- pop acc
- ret
- ;显示设置—— 分配时间显示空间
- chaizi:
- mov a,year ;拆年
- mov r0,#60h
- acall hex2bcd
- mov a,month ;拆月
- mov r0,#62h
- acall hex2bcd
- mov a,day ;拆日期
- mov r0,#64h
- lcall hex2bcd
- mov a,week;
- mov 66h,a
- mov a,hour ;拆时
- mov r0,#67h
- lcall hex2bcd
- mov a,min
- mov r0,#69h ;拆分
- lcall hex2bcd
- mov a,sec
- mov r0,#6bh ;拆秒
- acall hex2bcd
- ret
- ;显示设置—— 采用除法指令实现的拆字子程序
- hex2bcd:
- mov b,a
- anl a,#0f0h
- swap a
- mov @r0,a
- mov a,b
- anl a,#0fh
- inc r0
- mov @r0,a
- ret
- ;显示设置——连续显示相邻的两字节
- LcdDspBuf:
- mov A, @R0
- orl a,#30h
- acall LcdWrDat
- mov a,6
- lcall delay
- inc R0
- djnz R2, LcdDspBuf
- ret
- ;显示设置——自创字符写入CGRAM的子程序
- word:
- mov a,#40h
- lcall LcdWrCmd
- mov r5,#40
- mov dptr,#tab1
- mov r4,#0
- nextt:
- mov a,r4
- movc a,@a+dptr
- lcall LcdWrDat
- inc r4
- djnz r5,nextt
- ret
- tab1:
- db 08h,0fh,12h,0fh,0ah,1fh,02h,00h;年
- db 0fh,09h,0fh,09h,0fh,09h,13h,00h;月
- db 0fh,09h,09h,0fh,09h,09h,0fh,00h;日
- db 06h,0fh,1fh,0fh,07h,1bh,19h,00h;显示闹钟功能开启标示符号
- db 15h,15h,04h,11h,1bh,1fh,0eh,00h;显示报时功能开启标示符号
- ;进入闹钟功能设置显示
- display_nz:
- mov a,#0c2h
- acall LcdWrCmd ;确定闹钟时间的首地址
- mov R0, #dspba+0
- mov R2, #2
- acall LcdDspBuf ;显示时
- mov a,#3ah ;显示分隔符号
- acall LcdWrDat
- mov R0, #dspba+2
- mov R2, #2
- acall LcdDspBuf ;显示时
- jb BJ,XT ;判断闹钟功能是否开启
- mov a,#0c0h
- acall LcdWrCmd
- mov a,#03h ;显示闹钟功能开启标示符号
- acall LcdWrDat
- XT: ret
- ;正常显示设置
- display:
- mov a,#80h
- acall LcdWrCmd ;指明显示的首地址
- mov R0, #DspBuf-2
- mov R2, #2
- acall LcdDspBuf ;显示年份前两位
- mov R0, #DspBuf+0
- mov R2, #2
- acall LcdDspBuf ;显示年后两位
- mov a,#00h ;显示汉字年
- acall LcdWrDat
- mov R0, #DspBuf+2
- mov R2, #2
- acall LcdDspBuf ;显示月份
- mov a,#01h ;显示汉月字年
- acall LcdWrDat
- mov R0, #DspBuf+4
- mov R2, #2
- acall LcdDspBuf ;显示日期
- mov a,#02h ;显示汉日字年
- acall LcdWrDat
- mov a,#8ch ;w指明星期的首地址
- acall LcdWrCmd
- mov a,#57h
- acall LcdWrDat ;显示w
- mov a,#3ah ;显示分隔符号
- acall LcdWrDat
- mov a,66h ;显示星期值
- orl a,#30h
- acall LcdWrDat
- jb bs,XtT ;判断报时功能是否开启
- mov a,#04h ;显示报时功能开启标示符号
- acall LcdWrDat
- XtT:
- mov a,#0c2h
- acall LcdWrCmd ;确定地址
- mov R0, #DspBuf+7
- mov R2, #2
- acall LcdDspBuf ;显示时
- mov a,#3ah ;显示分隔符号
- acall LcdWrDat
- mov R0, #DspBuf+9
- mov R2, #2
- acall LcdDspBuf ;显示分
- mov a,#3ah ;显示分隔符号
- acall LcdWrDat
- mov R0, #DspBuf+11
- mov R2, #2
- acall LcdDspBuf ;显示秒
- jb BJ,xyz ;判断闹钟功能是否开启
- mov a,#0c0h
- acall LcdWrCmd
- mov a,#03h ;显示闹钟功能开启标示符号
- acall LcdWrDat
- xyz: ret
- ret
- ;按键处理
- anjian:
- mov a,pq
- anl a,#0fh
- cjne a,#0fh,kp1
- ret
- kp1:
- mov a,#5 ;设置5ms延时,起到去抖扫描
- acall delay
- mov a,pq
- anl a,#0fh
- cjne a,#0fh,kp2
- ret
- kp2:
- JB pq.0,KK1
- jnb pq.0,$
- lcall anjian1
- ret
- KK1:
- JB pq.1,KK2
- jnb pq.1,$
- lcall anjian2
- ret
- KK2:
- JB pq.2,KK3
- jnb pq.2,$
- lcall anjian3
- ret
- KK3:
- JB pq.3,KK4
- jnb pq.3,$
- lcall anjian4
- KK4: ret
- ;该子程序根据的KeyCode内容转入各对应的操作程序中
- anjian1:
- mov a,KeyCode
- mov dptr,#tab5
- add a,KeyCode
- jnc nadd
- inc dph ;KeyCode乘2进位加到DPH中
- nadd:
- mov r3,a ;暂存
- movc a,@a+dptr ;取地址高八位
- xch a,r3 ;保存转移地址高8位
- inc a
- movc a,@a+dptr ;取地址低八位
- mov dpl,a ;置转移地址低8位
- mov dph,r3
- clr a
- jmp @a+dptr
- ret
- tab5: dw opr00,opr01,opr02 ,opr03 ;16位转移地址表的首地址
- ;进入时间调整设置状态
- opr00:
- setb IsSheZhi
- mov r1,#DspBuf+12 ;编辑时间从秒个位开始
- mov a,#0fh
- acall LcdWrCmd
- mov a,#0c9h
- acall LcdWrCmd
- mov KeyCode,#02h
- ret
- ;进入设置闹钟时间状态
- opr01:
- setb IsSheZhi
- mov r1,#dspba+3 ;编辑时间从分个位开始
- mov a,#0fh
- acall LcdWrCmd
- mov a,#0c6h
- acall LcdWrCmd
- mov KeyCode,#03h
- ret
- ;把所设置的时间作为当前时间
- opr02:
- mov a,DspBuf+11
- swap a
- mov b,DspBuf+12
- orl a,b
- mov sec,a ;存秒
- mov a,DspBuf+9
- swap a
- mov b,DspBuf+10
- orl a,b
- mov min,a ;存分
- mov a,DspBuf+7
- swap a
- mov b,DspBuf+8
- orl a,b
- mov hour,a ;存时
- mov a,DspBuf+4
- swap a
- mov b,DspBuf+5
- orl a,b
- mov day,a ;存日期
- mov week,DspBuf+4; ;存星期值
- mov a,DspBuf+2
- swap a
- mov b,DspBuf+3
- orl a,b
- mov month,a ;存月
- mov a,DspBuf+0
- swap a
- mov b,DspBuf+1
- orl a,b
- mov year,a ;存年
- lcall set1302 ;为当前时间
- cpl IsSheZhi ;退出设置状态
- mov a,#0ch ;开启 闪动
- acall LcdWrCmd
- mov KeyCode,#00h
- ret
- ;把所设置的时间作为闹钟时间
- opr03:
- mov a,#0c0h
- acall LcdWrCmd
- mov a,#03h ;显示闹钟功能开启标示符号
- acall LcdWrDat
- mov a,#0ch ;撤销闪动
- acall LcdWrCmd
- clr IsSheZhi ;退出设置状态
- mov KeyCode,#00h
- clr QH
- clr BJ ;开启闹钟功能
- ret
- anjian2:
- mov a, KeyCode
- clr c
- subb a,#02h
- jc ppr1 ;判断钟是否处于设置状态,不是则跳
- jb QH, opr1a
- mov a,r1
- clr c
- subb a,#5eh
- mov dptr,#taba4
- movc a,@a+dptr
- mov b,a
- inc @r1
- mov a,@r1
- cjne a, b,ppra1
- mov @r1,#0
- ppra1:
- lcall www ;扫描当前时间编辑位
- ret
- taba4: db 0ah,0ah,0ah,0ah,02h,0ah,04h,0ah,08h,03h,0ah,06h,0ah,06h,0ah;当前时间各编辑位极大值表
- opr1a:
- mov a,r1
- clr c
- subb a,#70h
- mov dptr,#taba6
- movc a,@a+dptr
- mov b,a
- inc @r1
- mov a,@r1
- cjne a,b,ppra1k
- mov @r1,#0
- ppra1k:
- lcall wwwa ;扫描闹钟时间编辑位
- ret
- taba6 : db 03h,0ah,06h,0ah ;闹钟时间各编辑位极大值表
- ppr1: cpl IsSheZhi
- cpl QH ;切换屏幕
- jnb QH,TY
- mov a,#01h ;清屏幕
- acall LcdWrCmd
- mov KeyCode,#01h ;指明按键1下次执行的功能子程序
- acall display_nz ;显示闹钟时间
- ret
- TY: mov KeyCode,#00h ;指明按键1下次执行的功能子程序
- ret
- ;按键3处理设计
- anjian3:
- mov a, KeyCode
- clr c
- subb a,#02h
- jc ajppr2 ;判断钟是否处于设置状态,不是跳
- jb QH, opr2b ;判断钟是否处于编辑闹钟时间状态
- dec r1 ;移位
- cjne r1,#DspBuf-3,ppr2a
- mov r1,#DspBuf+12
- ppr2a:
- lcall www ;扫描当前时间编辑位
- ret
- opr2b:
- dec r1 ;移位
- cjne r1,#dspba-1,ppr2ak
- mov r1,#dspba+3
- ppr2ak:
- lcall wwwa ;扫描闹钟时间编辑位
- ret
- ajppr2:
- mov a,#01h ;清除屏幕
- acall LcdWrCmd
- cpl BJ
- JB BJ,TY_1
- ret
- TY_1:
- clr tr0
- setb pf
- ret
- ;按键4处理设计
- anjian4:
- mov a, KeyCode
- clr c
- subb a,#02h
- jc anjian4_1 ;判断钟是否处于设置状态,否则跳
- clr IsSheZhi
- mov KeyCode,#00h
- mov a,#0ch ;取消闪动
- acall LcdWrCmd
- ret
- anjian4_1:
- mov a,#01h ;清除屏幕
- acall LcdWrCmd
- cpl bs ;控制报时功能
- JB bs,TY_2
- ret
- TY_2:
- clr tr1
- setb pf
- ret
- ;扫描当前时间编辑位
- www:
- mov a,r1
- clr c
- subb a,#5eh
- mov dptr,#tab4
- movc a,@a+dptr
- mov b,a ;暂存 闪动位置
- acall LcdWrCmd ;写入编辑位的位置
- mov a,#10 ;设置10ms延时
- acall delay
- mov a,@r1
- orl a,#30h
- acall LcdWrDat ;写入数据
- mov a,b ;确定闪动位置
- acall LcdWrCmd
- ret
- ;扫描闹钟时间编辑位
- wwwa:
- mov a,r1
- clr c
- subb a,#70h
- mov dptr,#tab6
- movc a,@a+dptr
- mov b,a ;暂存 闪动位置
- acall LcdWrCmd ;写入编辑位的位置
- mov a,#10 ;设置10ms延时
- acall delay
- mov a,@r1
- orl a,#30h
- acall LcdWrDat ;写入数据
- mov a,b ;确定闪动位置
- acall LcdWrCmd
- ret
- tab4:db 80h,81h,82h,83h,85h,86h,88h,89h,8eh,0c2h,0c3h,0c5h,0c6h,0c8h,0c9h
- ;当前时间各编辑位在LCD上的位置表
- tab6:db 0c2h,0c3h,0c5h,0c6h ;闹钟时间各编辑位在LCD上的位置表
- ;比较子程序
- bijiao:
- mov a, dspba+0
- cjne a,DspBuf+7,bijiao_1 ;比较当前时间与闹钟时间的时十位
- mov a, dspba+1
- cjne a,DspBuf+8,bijiao_1 ;比较当前时间与闹钟时间的时个位
- mov a, dspba+2
- cjne a,DspBuf+9,bijiao_1 ;比较当前时间与闹钟时间的分钟十位
- mov a, dspba+3
- cjne a,DspBuf+10,bijiao_1;比较当前时间与闹钟时间的分钟个位
- setb TR0
- ret
- bijiao_1:
- clr TR0
- setb pf
- clr led
- ret
- ; 整点报时子程序
- zhengshi:
- mov a,sec ;判断当前时间是否是整时,即能否报时
- jnz js ;判断是否位0秒
- mov a,min
- jnz js ;判断是否位0分
- mov a,DspBuf+7
- mov b,#10
- mul ab
- add a,DspBuf+8 ;;BCD码转化位二进制
- cjne a,#13,$+3 ;判断时是否超过12小时
- jc ss
- clr c
- subb a,#12
- ss:
- mov shengshu,a
- cpl bs ;暂时关闭判断整时
- clr cxbs ;开始报时
- js: ret
- ;执行报时baoshi
- baoshi: ;执行报时功能
- mov a,chuzhi
- cjne a,sec,ltt
- setb tr1
- mov a,chuzhi
- add a,#01h
- da a
- mov chuzhi,a
- djnz shengshu,ltt
- cpl bs
- setb cxbs
- mov chuzhi,#00h
- ltt: ret
- ;蜂鸣器响功能设置
- sub1:
- cpl pf
- reti
- sub2:
- mov th1,#0f8h ;设置报时声的音色
- cpl pf
- djnz jiepai,sub2_1
- mov jiepai,#80h ;设置节拍常数
- clr tr1
- sub2_1: reti
- end
复制代码
|