看板 TTU-I90B 關於我們 聯絡資訊
由於我上課都沒聽,所以有些地方是我猜的! 我是覺得沒錯啦…反正po出來,給大家看看吧…因為我看好像沒人要念這科 組合語言很好玩耶=.=|| 程式碼詳解~我覺得老師的講義的註解太深奧…所以我用自己的話說^_^ 不過有些是用老師的,因為我也不是說完全懂! .nolist .include "8515def.inc" .list rjmp RESET ;程式開始的地方 .def TEMP =r16 .def TEMP1 =r17 .def TEMP2 =r18 .def MUSN =r22 .def TONL =r21 .def TONH =r20 .def PLYTON =r25 .def TONSET =r24 .def TONLNG =r23 ;上面是定義暫存器叫啥名字 .cseg .org 0x06 ;這是timer1的中斷向量 intt1: RJMP OUTPM ;簡單說..就是跳到OUTPM .org 0x010 ;發音起始位址 ;發音週期計時到重新載入新計時值並將輸出埠PORTD0 轉態 ;上面這句等一下解釋.. OUTPM: OUT TCNT1H,TONH ;重新將TONH 新計時值載入TCNT1H 內 OUT TCNT1L,TONL ;重新將TONL 新計時值載入TCNT1L 內 SBIS PORTD,00 ;先檢測PORTD0 是否為1 而跳格 RJMP SETOP1 ;若是PORTD0 為0 則跳到SETOP1 令PORTD0 轉為1 SETOP0: CBI PORTD,00 ;若PORTD0 為1 則令PORTD0 轉為0 LDI MUSN,$00 ;同時令MUSN 為00 值 RETI ;回中斷前主程式並令可再次中斷 SETOP1: SBI PORTD,00 ;若PORTD0 為0 則令PORTD0 轉為1 LDI MUSN,$01 ;同時令MUSN 為01 值 RETI ;回中斷前主程式並令可再次中斷 相信程式一開始一定很多人就看無啦~ 因為我第一次看…也是看不懂! 不過,上面這邊我是用猜的~ 這個實驗啊! 應該是利用PD0連結蜂鳴器,然後利用計時中斷的方式,對蜂鳴器產生High和Low的 訊號,然後產生音階!至於產生的方式,是我猜的! 我的想法是,利用那個音階對照表,每一個音階的數字代表的意義是音階: 我用第一個音階的數字當例子說明! 第一個數字是63627,就是說從63627開始計時到65536然後會發生中斷, 也就是說總共數了1909次,程式預除是8(後面程式會寫),也就是頻率是1MHz 所以,週期是1/1M=1us,所以1909次總共1.909ms,程式的delay為0.2s(請參考delay 副函式),所以0.2s中總共執行中斷約104次,每次都利用High和low從PD0輸入訊號給 蜂鳴器,也就是上面程式碼的SETOP0和SETOP1,導致產生這個音階。 ;主程式起始位址 RESET: ldi temp,low(RAMEND) out SPL,temp ldi temp,high(RAMEND) out SPH,temp ;上面四句就是把sp指到0025 wdr ;重設看門狗計時器 ldi temp,$0F ;WDTCR 定址$21 不可位元設定以TEMP 緩衝令WDE=D3=1 out WDTCR,temp ;並令預除為2048MS 設定WDE=1=D3 輸出到WDTCR 內 LDI MUSN,$00 ;令MUSN 為00 值 ldi temp,$00 ;令TEMP 暫存器放入00 out tccr1a,temp ;將TEMP=00 內含輸出到TCCR1a 內禁止比較器及pwm動作 out tccr1b,temp ;將TEMP=00 內含輸出到TCCR1b 內停止TC1 計時及捕抓 ;這邊不懂,可以看英文那本的,解說詳細 ;基本上,tccr1b和tccr1a就是用來控制timer1的register ;內容還是建議看一下英文那本! LDI TEMP,$02 ;將02 值預存入SRAM 的0100H 內作TC1 的 STS $0100,TEMP ;TCCR1B 控制內含令TC1 為計時預除8 ;這邊就是控制預除8,所以頻率是8MHz/8=1MHz LEDA: CLI ;中斷總開關sreg=d7=i=1,中斷總開關沒開不能使用中斷 ldi r16,0b10000000 ;令toie1=1 致能中斷 out timsk,r16 ;將R16 的D7=1 令TOIE1=1 致能中斷 ;有關中斷的也可以參考英文那本,超詳細 LDI TEMP,$FF ;令TEMP=$FF 以便令DDRB 設定為輸出態 OUT DDRB,TEMP LDI TEMP,0B11111101 ;PD1 為輸入模態其餘PD0,PD2-PD7 為輸出態 OUT DDRD,TEMP LDI TEMP,0B11111111 ;PD1 為輸入提升電阻模態 OUT PORTD,TEMP CLR TEMP2 ;將TEMP2,TEMP1,KSNI,SCNTT,TONLNG 等暫存器 CLR TEMP1 ;予以清除 CLR TONLNG ;上面這邊應該看的懂吧! STARTP: WDR ;清除看門狗計時器用以當機時可重新RESET SBIC PIND,01 ;檢測PIND1 是否被壓按而為LOW 則跳格 RJMP STARTP ;若PIND1 仍為HI 之未起動演奏則跳回STARTP ;檢查PD1有沒有被按,就是讓音樂播放的那根pin LDI ZH,HIGH(PLYTAB*2) ;若壓按PIND1 啟動演奏則令Z 定址於音樂盒 LDI ZL,LOW(PLYTAB*2) ;音樂演奏樂譜存放之PLYTAB*2 之起始位址 ;這邊就是把Z指標指到PLYTAB NEXMUT: LPM ;將Z 所指PROM 之預存樂譜依次取音階及音長置於R0 MOV PLYTON,R0 ;將取出的第一個音階搬入PLYTON 作週期控制 LD R0,Z+ ;以LD R0,Z+指令使得Z 間接指標遞加1 LPM ;將Z 所指PROM 之預存樂譜依次取音長置於R0 MOV TONLNG,R0 ;將取出的第一個音長搬入TONLNG 作音長控制 OR R0,PLYTON ;將此R0 音長與音階PLYTON 作OR 運算 LD R0,Z+ ;以LD R0,Z+指令使得Z 間接指標遞加1 ;上面就是把音階放入PLYTON,音長放入TONLNG BRNE PLAYM ;若音階及音長皆非全為00,值則跳到PLAYM 演奏 ;PLAYM副函式用來播放低~ LDI TEMP,$00 ;若音階及音長皆全為00,00 則為結束碼 out tccr1b,temp ;將TEMP=00 內含輸出到TCCR1b 內停止TC1 計時及捕抓 ;tccr1b是用來控制timer1的register CLI ;把中斷關掉 SBI PORTD,00 ;把蜂鳴器關掉 ;程式是利用PD0來控制蜂鳴器 RJMP STARTP ;跳回STARTP 重新再等待按鍵起動發音演奏 ;開始將PROM 取表所得的音階PLYTON 及音長對應予以計時發音 PLAYM: PUSH ZH ;將啟始的PROM 間接指標定址ZH,ZL 推入堆疊 PUSH ZL ;保存以便再次取出 TST PLYTON ;檢測PLYTON 是否為0 值 BREQ MUSTD ;若為0 值則為休止符故跳到MUSTD 作音長等待 ;測試是不是休止符,也就是00 LDI ZH,HIGH(MUSTAB*2) ;令Z 間接指標指著各音階控制計時器1 LDI ZL,LOW(MUSTAB*2) ;的計時控制計時值存放起始位址 ;把Z指到MUSTAB MOV TEMP,PLYTON ;將音階PLYTON 搬入TEMP 暫存器內 DEC TEMP ;第0音階空白休止音故演奏音階定址差1 而將其減1 ;把音階移到TEMP,不過音階裡面沒有休止符,所以要減一! LSL TEMP ;每個音階由2 個PROM 內2 的TCNT1H,TCNT1L 組構故乘2 ADD ZL,TEMP ;將正確的計時器1 控制音階的存表位移TEMP 加入ZL LDI TEMP,$00 ;令TEMP=00 以便讓ZH 與進位旗號CF 相加 ADC ZH,TEMP ;將ZH 與TEMP=00 以及CF 旗號相加得到真正Z 定址值 ;計算音階的真正位置。 ;一開始的位置是Z,也就是指到MUSTAB,然後由選擇的第幾個音, ;來控制要加多少,像是上面TEMP中就是設定的音階,要乘二是因為 ;要直接跟位置相加! LPM ;將Z 所指PROM 之預存音階之計時長度低位值置於R0 MOV TONL,R0 ;將音階之計時長度之低位值R0 搬入TONL 內 OUT TCNT1L,R0 ;將音階之計時長度之低位值R0 也搬入TCNT1L內 LD R0,Z+ ;以LD R0,Z+指令使得Z 間接指標遞加1 LPM ;將Z 所指PROM 之預存音階之計時長度高位值置於R0 MOV TONH,R0 ;將音階之計時長度之高位值R0 搬入TONH 內 OUT TCNT1H,R0 ;將音階之計時長度之高位值R0 也搬入TCNT1H內 ;把剛剛計算好的位置放到,TCNT1裡面,準備計時中斷用 POP ZL ;將ZL,ZH 由堆疊指標所指之SRAM 依次取回 POP ZH LDS TEMP,$0100 ;將SRAM 定址0100H 之內含載入TEMP 內 OUT TCCR1B,TEMP ;將原0100H 之SRAM 內含輸出到TCCR1B 控制TC1 這邊把上面設定8的預除,送到tccr1b SEI ;令中斷總開關=1 ;也就是開始計時 MUSTD: RCALL PLYDEL ;延時等待音階週期計時及單位音長0.2 S 副程式 ;就是上面提到的延遲0.2s,所以也就是說,單音的發音時間為0.2s DEC TONLNG ;將音長TONLNG 減1 BRNE MUSTD ;若音長TONLNG 不為0 則跳回MUSTD 再輸出音階發音 ;音長的控制 RJMP NEXMUT ;若此音階及其音長發音完畢則跳到NEXTNUT ;再次取下個音階及其對應音長發音 ;延時約為.2SEC 的單位延時 PLYDEL: LDI TEMP,185 ;185*1mS=185mS 即PLYDEL 為185mS DT3: LDI TEMP1,04 ;4*250uS=1mS 即DT3 約為1mS DT2: LDI TEMP2,250 ;250*8*125nS=250uS 即DT2 約為250US DT1: WDR ;1T NOP ;2T NOP ;3T NOP ;4T NOP ;5T DEC TEMP2 ;6T 將TEMP2 減1 BRNE DT1 ;8T 當TEMP2 不為0 值則共執行250*8*T=250US DEC TEMP1 ;將TEMP1 減1 BRNE DT2 ;當TEMP1 不為0 值則共執行250*4 US=1MS DEC TEMP ;將TEMP 減1 BRNE DT3 ;當TEMP 不為0 值則共執行185* 1 MS=185MS RET ;回主程式 ;上面就是延遲0.2s。 .EQU MUSTAB=0X0100 .EQU PLYTAB=0X0140 .cseg .org MUSTAB ;各音階對應TC1 的TCNT1 計時週期資料存放起始位址,共36 個音階。 ;1 2 3 4 5 6 7 8 9 ;1. '#1.',2 '#2.'3. '4. '#4 '5. '#5. .DW 63627,63730,63835,63927,64020,64102,64185,64259,64330 ;10 11 12 13 14 15 16 17 18 ;6. '#6.'7. '1 '#1 '2 '#2 '3 '4 .DW 64399,64463,64523,64579,64632,64683,64731,64776,64819 ;19 20 21 22 23 24 25 26 27 ;#4 '5 '#5 '6 '#6 '7 '.1 '#.1 '.2 ' .DW 64859,64897,64933,64967,64999,65029,65057,65084,65109 ; 28 29 30 31 32 33 34 35 36 ;#.2' .3 ' .4 '#.4 '.5 '#.5 '.6 '#.6 '.7 .DW 65133,65156,65177,65197,65216,65243,65251,65267,65282 .cseg .org PLYTAB ;音樂盒之樂譜資料存放起始位址 ; | 5 5, 6 5 | .DB 20,02,00,01,20,01,22,04,20,04 ; |.1 7 -- | .DB 25,04,24,04,00,04 ; | 5 5, 6 5 | .DB 20,02,00,01,20,01,22,04,20,04 ; |.2 .1 -- | .DB 27,04,25,04,00,04 ; | 5 5,.5 .3 | .DB 20,02,00,01,20,01,32,04,29,04 ; |.1 7 6 | .DB 25,04,24,04,22,04 ; |.4 .4 .3 .1 | .DB 30,02,00,01,30,01,29,04,25,04 ; |.2 .1 -- | .DB 27,04,25,04,00,04 .DB 00,00 ; 音樂END -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 218.166.125.121 ※ 編輯: supergothere 來自: 218.166.125.121 (06/06 21:42) ※ 編輯: supergothere 來自: 218.166.125.121 (06/06 21:52) ※ 編輯: supergothere 來自: 218.166.125.121 (06/06 21:55)
supergothere:我沒po換曲那個的~ 218.166.125.121 06/06
supergothere:因為我覺得學長寫的怪怪低 218.166.125.121 06/06
supergothere:我自己也有寫一個,不過是用想的.. 218.166.125.121 06/06
supergothere:沒跑過,所以不知道對不對…^^" 218.166.125.121 06/06
yannishadow:玩了一個週末的matlab,我覺得..... 140.129.39.71 06/06
yannishadow:matlab比組合語言好玩多了!....-_-" 140.129.39.71 06/06
icemint:◆ 這一篇文章值 515 銀 140.129.37.29 06/07