|
;******************************************************** ;AVR 匯編程序?qū)嵗?BR>;簡易帶1/100 秒的24 小時制時鐘 ;Mega16 4MHz ;******************************************************** .include "m16def.inc" ;引用器件I/O 配置文件 ;定義程序中使用的變量名(在寄存器空間) .def count = r18 ;循環(huán)計數(shù)單元 .def position = r19 ;LED 顯示位指針,取值為0-7 .def p_temp = r20 ;LED 顯示位選,其值取反由PC 口輸出 .def count_10ms = r21 ;10ms 計數(shù)單元 .def flag_2ms = r22 ;2ms 到標(biāo)志 .def temp = r23 ;臨時變量 .def temp1 = r24 ;臨時變量 .def temp_int = r25 ;臨時變量(在中斷中使用) ;中斷向量區(qū)定義,flash 程序空間$000-$029 .org $000 rjmp reset ;復(fù)位處理 nop reti ;IRQ0 Handler nop reti ;IRQ1 Handler nop reti ;Timer2 Compare Handler nop reti ;Timer2 Overflow Handler nop reti ;Timer1 Capture Handler nop reti ;Timer1 Compare-A Handler nop reti ;Timer1 Compare-B Handler nop rjmp time1_ovf ;Timer1 Overflow Handler nop reti ;Timer0 Overflow Handler nop reti ;SPI Transfer Complete Handler nop reti ;USART RX Complete Handler nop reti ;USART UDR Empty Handler nop reti ;USART TX Complete Handler nop reti ;ADC Conversion Complete Handler nop reti ;E2PROM Ready Handler nop reti ;Analog Comparator Handler nop reti ;Two-wire Serial Interface Handler nop reti ;IRQ2 Handler nop reti ;Timer0 Compare Handler nop reti ;SPM Ready Handler nop ;程序開始 .org $02A reset: ldi r16,high(RAMEND) ;設(shè)置堆棧指針高位 out sph,r16 ldi r16,low(RAMEND) ;設(shè)置堆棧指針低位 out spl,r16 ser temp out ddra,temp ;設(shè)置PORTA 為輸出,段碼輸出 out ddrc,temp ;設(shè)置PORTC 為輸出,位碼控制 out portc,temp ;PORTC 輸出$FF, 無顯示 ldi position,0x00 ;段位初始化為1/100 秒低位 ldi p_temp,0x01 ;LED 第1 位亮 ;初始化時鐘時間為11:59:55:00 ldi xl,low(time_buff) ; ldi xh,high(time_buff) ;X 寄存器取得時鐘單元首指針 ldi temp,0x00 st x+,temp ;1/100 秒 = 00 ldi temp,0x55 st x+,temp ;秒 = 55 ldi temp,0x59 st x+,temp ;分 = 59 ldi temp,0x11 st x,temp ;時 = 11 ldi temp,0xff ;T1 初始化,每隔2ms 中斷一次 out tcnt1h,temp ldi temp,0x83 out tcnt1l,temp clr temp out tccr1a,temp ldi temp,0x03 ;4M,64 分頻 2ms out tccr1b,temp ldi temp,0x04 out timsk,temp ;允許T1 溢出中斷 sei ;全局中斷允許 ;主程序 main: cpi flag_2ms,0x01 ;判2ms 到否 brne main ;No,轉(zhuǎn)main 循環(huán) clr flag_2ms ;到,請2ms 標(biāo)志 rcall display ;調(diào)用LED 顯示時間(動態(tài)掃描顯示一位) d_10ms_ok: cpi count_10ms,0x05 ;判10ms 到否 brne main ;No,轉(zhuǎn)main 循環(huán) clr count_10ms ;10ms 到,清零10ms 計數(shù)器 rcall time_add ;調(diào)用時間加10ms 調(diào)整 rcall put_t2d ;將新時間值放入顯示緩沖單元 rjmp main ;轉(zhuǎn)main 循環(huán) ;LED 動態(tài)掃描顯示子程序,2ms 執(zhí)行一次,一次點亮一位,8 位循環(huán) display: clr r0 ser temp ;temp = 0x11111111 out portc,temp ;關(guān)顯示,去消影和拖尾作用 ldi yl,low(display_buff) ldi yh,high(display_buff) ;Y 寄存器取得顯示緩沖單元首指針 add yl,position ;加上要顯示的位值 adc yh,r0 ;加上低位進(jìn)位 ld temp,y ;temp 中為要顯示的數(shù)字 clr r0 ldi zl,low(led_7 * 2) ldi zh,high(led_7 * 2) ;Z 寄存器取得7 段碼組的首指針 add zl,temp ;加上要顯示的數(shù)字 adc zh,r0 ;加上低位進(jìn)位 lpm ;讀對應(yīng)七段碼到R0 中 out porta,r0 ;LED 段碼輸出 MOV r0,p_temp com r0 out portc,r0 ;輸出位控制字,完成LED 一位的顯示 inc position ;調(diào)整到下一次顯示位 lsl p_temp cpi position,0x08 brne display_ret ldi position,0x00 ldi p_temp,0x01 display_ret: ret ;時鐘時間調(diào)整,加0.01 秒 time_add: ldi xl,low(time_buff) ; ldi xh,high(time_buff) ;X 寄存器為時鐘單元首指針 rcall dhm3 ;ms 單元加1 調(diào)整 cpi temp,0x99 ; brne time_add_ret ;未到99ms 返回 rcall dhm ;秒單元加1 調(diào)整 cpi temp,0x60 brne time_add_ret ;未到60 秒返回 rcall dhm ;分單元加1 調(diào)整 cpi temp,0x60 brne time_add_ret ;未到60 分返回 rcall dhm ;時單元加1 調(diào)整 cpi temp,0x24 brne time_add_ret ;未到24 時返回 clr temp st x,temp ;到24 時,時單元清另 time_add_ret: ret ;低段時間清零,高段時間加1,BCD 調(diào)整 dhm: clr temp ;當(dāng)前時段清零 dhm1: st x+,temp ;當(dāng)前時段清零,X 寄存器指針加一 dhm3: ld temp,x ;取出新時段數(shù)據(jù) inc temp ;加一 cpi temp,0x0A ;若個位數(shù)碼未到$0A(10) brhs dhm2 ;例如$58+1=$59,不須調(diào)整; subi temp,0xFA ;否則做減$FA 調(diào)整:例如$49+1-$FA=$50 dhm2: st x,temp ;并將調(diào)整結(jié)果送回 ret ;將時鐘單元數(shù)據(jù)送LED 顯示緩沖單元中 put_t2d: ldi xl,low(time_buff) ; ldi xh,high(time_buff) ;X 寄存器時鐘單元首指針 ldi yl,low(display_buff) ldi yh,high(display_buff) ;Y 寄存器顯示緩沖單元首指針 ldi count,4 ;循環(huán)次數(shù) = 4 loop: ld temp,x+ ;讀一個時間單元 MOV temp1,temp swap temp1 andi temp1,0x0f ;高位BCD 碼 andi temp,0x0f ;低位BCD 碼 st y+,temp ;寫入2 個顯示單元 st y+,temp1 ;低位BCD 碼在前,高位在后 dec count brne loop ;4 個時間單元->8 個顯示單元 ret ;T1 時鐘溢出中斷服務(wù) time1_ovf: in temp_int,sreg push temp_int ;保護(hù)狀態(tài)寄存器 ldi temp_int,0xff ;T1 初始值設(shè)定,2ms 中斷一次 out tcnt1h,temp_int ldi temp_int,0x83 out tcnt1l,temp_int inc count_10ms ;10ms 計數(shù)器加一 ldi flag_2ms,0x01 ;置2ms 標(biāo)志到 pop temp_int out sreg,temp_int ;恢復(fù)狀態(tài)寄存器 reti ;中斷返回 .CSEG ;LED 七段碼表,定義在Flash 程序空間 led_7: ;7 段碼表 .db 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07 .db 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71 ;字 PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 共陰極 共陽極 ; h g f E d c b a ;0 0 0 1 1 1 1 1 1 3FH C0H ;1 0 0 0 0 0 1 1 0 06H F9H ;2 0 1 0 1 1 0 1 1 5BH A4H ;3 0 1 0 0 1 1 1 1 4FH B0H ;4 0 1 1 0 0 1 1 0 66H 99H ;5 0 1 1 0 1 1 0 1 6DH 92H ;6 0 1 1 1 1 1 0 1 7DH 82H ;7 0 0 0 0 0 1 1 1 07H F8H ;8 0 1 1 1 1 1 1 1 7FH 80H ;9 0 1 1 0 1 1 1 1 6FH 90H ;A 0 1 1 1 0 1 1 1 77H 88H ;b 0 1 1 1 1 1 0 0 7CH 83H ;C 0 0 1 1 1 0 0 1 39H C6H ;d 0 1 0 1 1 1 1 0 5EH A1H ;E 0 1 1 1 1 0 0 1 79H 86H ;F 0 1 1 1 0 0 0 1 71H 8EH .DSEG ;定義程序中使用的變量位置(在RAM 空間) .ORG $0060 display_buff: ;LED 顯示緩沖區(qū),8 個字節(jié) .BYTE 0x00 ;LED 1 位顯示內(nèi)容 .BYTE 0x00 ;LED 2 位顯示內(nèi)容 .BYTE 0x00 ;LED 3 位顯示內(nèi)容 .BYTE 0x00 ;LED 4 位顯示內(nèi)容 .BYTE 0x00 ;LED 5 位顯示內(nèi)容 .BYTE 0x00 ;LED 6 位顯示內(nèi)容 .BYTE 0x00 ;LED 7 位顯示內(nèi)容 .BYTE 0x00 ;LED 8 位顯示內(nèi)容 .org $0068 time_buff: ;時鐘數(shù)據(jù)緩沖區(qū),4 個字節(jié) .BYTE 0x00 ;1/100s 單元 .BYTE 0x00 ;秒單元 .BYTE 0x00 ;分單元 .BYTE 0x00 ;時單元 |