IMG20230626120355.jpg (3.02 MB, 下載次數: 18)
下載附件
2023-6-26 12:06 上傳
單片機源程序如下:
- ;初始化
- 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
復制代碼
|