作者supergothere (幸福)
看板TTU-I90B
標題微算機實驗(五)
時間Sun Jun 6 22:02:10 2004
剛剛那篇不對,所以我D掉了!
換一篇正確的!
依然是田橋仔的版本………
不過這樣中間就隔了一篇~"~
算了…開始了!
其實,到學校跟我討論會比較快…因為實驗五實在是有點長~!!!
.include "8515def.inc"
rjmp reset
.def mscnt=r16
.def temp2=r17
.def temp3=r18
.def scnt=r19
.def mcnt=r20
.def hcnt=r21
.def tempb=r22
.def tempd=r23
.def scndp=r24
.def cnt =r25
;設定暫存器
.cseg
.org 0x06 ;Timer1 溢位中斷向量
intt1: rjmp chk10ms ;跳到chk10ms
.cseg
.org 0x10
;若工作頻率8 MHz時,ck=125ns,則預除器256時為32us,而tcnt1為65535-(10*125)
;作計數溢位,則溢位中斷計時為10*125*32uS=10ms,故若中斷則為10ms 計時
;但對應10ms計時中斷需4ck且執行程式需7ck才會將新值載入tc1 內共11ck
;故需再延時245ck 總共延時245+11=256ck, 作為一個tc1 輸入週期時間作精確的校正
chk10ms:
wdr
rcall dly53
ldi temp2,high(65537-10*125);TEMP2 為高8 位元(65537-250*125)放入TCNT1H
out tcnt1h,temp2;TCNT1 由(65537-250*125) 計數到65537 溢位共計時31249
ldi temp2,low(65537-10*125);TEMP5 為低8 位元(65537-250*125)放入TCNT1L
out tcnt1l,temp2;TCNT1 由(65537-125*125) 計數到65537 溢位共計時31249
rcall clock ;呼叫clock副程式計時
reti ;跳回中斷主程
clock:
inc mscnt
cpi mscnt,100
brne notad
clr mscnt
inc scnt ;1 秒計時到則令秒暫存器scnt 加1
cpi scnt,60 ;將秒scnt 與60 比較
brne notad
clr scnt
inc mcnt ;1 分計時到則令分暫存器mcnt 加1
cpi mcnt,60 ;將分mcnt 與60 比較
brne notad ;若加一後不等於60 分則正常不進位而跳回notad
clr mcnt ;60 分計時到則清除分mcnt 後令時hscnt 計時加1
inc hcnt ;1 時計時到則令分暫存器hcnt 加1
cpi hcnt,24 ;將時hcnt 與24 比較
brne notad ;若加一後不等於24 時則正常不進位而跳回notad
clr hcnt ;24 時計時到則清除時hcnt 後令日dscnt 計時加1
notad: ret ;秒計時加一完成後回主程式
;上面就是,mscnt=百分之一秒
scnt=秒
mcnt=分
hcnt=時
然後做運算,算總共多少時間!
;總共延時245 個ck 週期時間
dly53:
ldi temp2,(53-5)/4 ;1ck
dt1: wdr ;1ck
dec temp2 ;1ck
brne dt1 ;2ck
nop ;1ck
ret ;4ck
;main program
reset:
ldi temp2,low(ramend) ;RAMEND 為8515def.inc 內建定義值為025FH
out spl,temp2 ;啟始堆疊指標低位元將R16=TEMP=02H 放入SPL=3DH
ldi temp2,high(ramend) ;以TEMP=R16<5FH 為資料載入緩衝暫存器
out sph,temp2 ;堆疊指標高位元將R16=TEMP=5FH 放入SPL+1=3EH
.equ buffer=0x0100 ;把程式offset 100的地方設為buffer
ldi xh,high(buffer) ;x指向buffer起始位置
ldi xl,low(buffer)
ldi zh,high(datab*2) ;z指向資料區(datab)起始位置
ldi zl,low(datab*2)
ldi temp2,10 ;放10的原因是把資料區(datab)的0~9放到buffer
buff: lpm
st x+,r0
ld r0,z+
dec temp2
brne buff
;上面就是如何把0~9放到buffer
start:wdr ;在使用看門狗計時器前需重設看門狗計時器內含
;避免在接下來程式前就因WDT 已快計時溢位而重設
ldi temp2,(1<<WDE) ;WDTCR 定址$21 不可位元設定以TEMP 緩衝令WDE=D3=1
out wdtcr,temp2 ;將已設定WDE=1=D3 位元值之TEMP 輸出到WDTCR 內
;上面是WDR
cli ;中斷總開關global interrupt disable
;中斷總開關,cli是關,sei是開
ldi temp2,$ff ;令temp2=ff 用來設定PD,PB 為輸出態
out ddrb,temp2 ;將temp2=FF 輸出到DDRB 設定全為輸出態
out ddrd,temp2 ;將temp2=FF 輸出到DDRD 設定全為輸出態
out ddrc,temp2
ldi temp2,0b00111111 ;temp2=00111111 令PA7-PA6 輸入態PA5-PA0 輸出
out ddra,temp2
;設定portA,B,C,D是輸入或輸出
sbi porta,6 ;令PortA6=1 提升電阻輸入態
sbi porta,7 ;令PortA7=1 提升電阻輸入態
;程式是利用portA的6,7 pin來控制,所以要提升...基本上我也不知道為啥~
clr mscnt
clr scnt ;令秒暫存器SCNT=00
clr mcnt ;令秒暫存器MCNT=00
clr hcnt ;令秒暫存器HCNT=00
;清空暫存器,因為一開始是00
out portc,mscnt
ldi scndp,0b11111011 ;令6位7-segment led掃描顯示碼起始位置為0011111
;利用portd的PD2~PD7六根pin來控制六個七段LED顯示器
mov tempb,scnt ;將秒計時搬入tempb 內
ldi temp3,$00 ;00輸到temp3使led計秒的個位數位置小數點不亮起
;最後面,秒那位的小數點不要亮!
rcall btod ;呼叫16進位數轉10進位數的副程式
rcall redsp ;呼叫顯示led的副程式
;上面四行是秒的
mov tempb,mcnt ;將分計時搬入tempb 內
ldi temp3,$ff ;ff輸到temp3使led計分的個位數位置小數點亮起
rcall btod ;呼叫16進位數轉10進位數的副程式
rcall redsp ;呼叫顯示led的副程式
;分
mov tempb,hcnt ;將時計時搬入tempb 內
ldi temp3,$ff ;ff輸到temp3使led計時的個位數位置小數點亮起
rcall btod ;呼叫16進位數轉10進位數的副程式
rcall redsp ;呼叫顯示led的副程式
;時
ldi temp2,$00 ;令TEMP2 暫存器放入00
out tccr1a,temp2 ;將TEMP2=00 內含輸出到TCCR1 內禁止比較器及PWM 動作
out tccr1b,temp2 ;將TEMP2=00 內含輸出到TCCR1 內禁止比較器及PWM 動作
;一樣的,tccr1b和1a是用來控制timer1,所以要先設定
ldi temp2,high(65535-10*125) ;TEMP2為高8位元(65536-250*125)放入TCNT1H
out tcnt1h,temp2
ldi temp2,low(65536-10*125) ;TEMP2為低8位元(65536-250*125)放入TCNT1L
out tcnt1l,temp2
;中斷計時的設定
sei ;中斷總開關sreg=d7=i=1
;中斷總開關,開=sei
ldi temp3,0b10000000 ;令toie1=1 致能中斷
out timsk,temp3 ;將R16 的D1=1 令TOIE0=1 致能中斷
;timsk也是timer的控制~~p.25
reptw: ;這個副程式是用來顯示的
ldi temp3,00 ;令R16=00
sbi porta,6 ;令portA6=1 提升電阻輸入態
sbi portb,7 ;令portB7=1 提升電阻輸入態
sbis pina,6 ;檢測PA6 輸入是否為0 若pinA6=0 則跳格啟始計時
ldi temp3,03 ;令R16=04
sbis pina,7 ;檢測PA7 輸入是否為0 若pinA6=0 則跳格重新計時
rjmp start ;跳回start 重新開始
out tccr1b,temp3 ;將R16=04 設定TC1 預除256 開始計時其單位時間為32uS
;這就是設定預除器~p.33
mov temp3,mscnt
com temp3
out portc,temp3
ldi scndp,0b11111011 ;令6 位數七段LED 掃描顯示碼起始為111110(PD7~PD2)
mov tempb,scnt ;將秒計時搬入tempb 內
ldi temp3,$00 ;00輸到temp3使led計秒的個位數位置小數點不亮起
rcall btod ;呼叫16進位數轉10進位數的副程式
rcall redsp ;呼叫顯示led的副程式
mov tempb,mcnt ;將分計時搬入tempb 內
ldi temp3,$ff ;ff輸到temp3使led計分的個位數位置小數點亮起
rcall btod ;呼叫16進位數轉10進位數的副程式
rcall redsp ;呼叫顯示led的副程式
mov tempb,hcnt ;將時計時搬入tempb 內
ldi temp3,$ff ;ff輸到temp3使led計時的個位數位置小數點亮起
rcall btod ;呼叫16進位數轉10進位數的副程式
rcall redsp ;呼叫顯示led的副程式
;上面控制秒,分,時的轉換和顯示~~
wdr
rjmp reptw ;跳回REPTW 顯示日時分秒並等待中斷計時一秒計時
下面就是真正顯示的方式!我覺得還是到學校說吧…用打得太困難啦~~
不過按照指令一步一步用數字自己代代看,應該可以搞懂!
因為我就是這樣看…!!!
redsp:
wdr
ldi xh,high(buffer) ;x指向buffer起始位置
ldi xl,low(buffer)
mov cnt,tempb ;將tempb=個位數的時間值輸到cnt
inc cnt ;cnt++
ld r0,-x ;x指標向前一格
jumpb:ld r0,x+ ;x指標向後一格
dec cnt ;cnt--
breq outb ;若cnt=0,則跳到outb,此時x指到所要表示的
;時間值資料位置的前一格
rjmp jumpb ;跳到jumpb
outb: ld r0,x+ ;x指到所要表示的時間值資料位置
mov temp2,r0 ;將r0資料輸入到temp2
sbrc temp3,1 ;如果temp3=00,則不做下一行,從下兩行開始作
ori temp2,$80 ;temp2內的值 or $80使temp2=1xxxxxxx,令7-segment的
;小數點燈號亮起
out portb,temp2 ;將讀取值之TEMP2 內含輸出到PORTB 顯示
out portd,scndp ;將SCNDP 掃描碼由右邊的PTD2=0 開始移位輸出
rcall delay ;呼叫DELAY 延時副程式令顯示一段時間
sec ;令CF=1 以便作掃描碼移位
rol scndp ;將SCNDP 與CF 作左旋轉令顯示掃描碼向左移位
wdr
ldi xh,high(buffer) ;x指向buffer起始位置
ldi xl,low(buffer)
mov cnt,tempd ;將tempd=十位數的時間值輸到cnt
inc cnt ;cnt++
ld r0,-x ;x指標向前一格在load資料到r0
jumpd:ld r0,x+ ;load資料到r0,x指標再向後一格
dec cnt ;cnt--
breq outd ;若cnt=0,則跳到outd,此時x指到所要表示的時間值資料
;位置的前一格
rjmp jumpd ;跳到jumpd
outd: ld r0,x+ ;x指到所要表示的時間值資料位置
mov temp2,r0 ;將r0資料輸入到temp2
out portb,temp2 ;將讀取值之TEMP2 內含輸出到PORTB 顯示
out portd,scndp ;將SCNDP 掃描碼由右邊的PTD2=0 開始移位輸出
rcall delay ;呼叫DELAY 延時副程式令顯示一段時間
sec ;令CF=1 以便作掃描碼移位
rol scndp ;將SCNDP 與CF 作左旋轉令顯示掃描碼向左移位
ret
btod: clr tempd ;令tempd=$00
retrs:subi tempb,10 ;將16進位tempb - 10
brcs negs ;若減十不夠減則cf = 1 進位跳到negs做調整
inc tempd ;若cf = 0昨夠減將十進位置tempd加1
rjmp retrs ;跳回retrs繼續將16進位減10夠減就加1
negs: subi tempb,$f6 ;將10進位tempb減f6即加上10恢復原值
ret ;回主程式
;上面就是轉換(16進位-->10進位)的程式
;建議自己代數字試試看~~
delay:ldi temp3,$08
dt3: ldi temp2,$20
dt2: wdr
dec temp2
brne dt2
dec temp3
brne dt3
ret
datab:
.db 0x3f,0x06,0x5b,0x4f
.db 0x66,0x6d,0x7d,0x07
.db 0x7f,0x6f,0x77,0x7c
;這邊是放七段顯示器的資料,0~12,其實只有用到0~9
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 218.166.125.121
※ 編輯: supergothere 來自: 218.166.125.121 (06/06 22:35)
推 ysun:可不可以用成WORD檔呀 218.34.180.209 06/06
→ ysun:方便印出ㄇㄟ~~嘻嘻 ^.^" 218.34.180.209 06/06
噓 icemint:你很懶耶~~ 自己複製貼上咩 140.129.37.29 06/06
→ icemint:要不然就在文章前面按"F"..轉寄回自已信箱 140.129.37.29 06/06
推 supergothere:=.=我是直接在BBS上面打耶~賺摳摳.. 218.166.125.121 06/06
→ icemint:◆ 這一篇文章值 9 銀 140.129.37.29 06/07