汇编:输入输出
預(yù)備知識(shí)
樂(lè)曲簡(jiǎn)譜中的每個(gè)音符及其節(jié)拍,在微機(jī)中對(duì)應(yīng)了揚(yáng)聲器的發(fā)聲頻率和持續(xù)時(shí)間。其中簡(jiǎn)譜音符與揚(yáng)聲器的發(fā)聲頻率的對(duì)應(yīng)關(guān)系見下表:
如何使 PC 機(jī)的揚(yáng)聲器發(fā)出指定頻率和指定時(shí)間長(zhǎng)度的聲音?下面簡(jiǎn)單介紹一下 PC 機(jī)的發(fā)聲原理:
IBM-PC 系列機(jī)的主機(jī)箱裝有一個(gè)小揚(yáng)聲器,系統(tǒng)板上的定時(shí)器 8253(或 8254)利用工作方式3 產(chǎn)生一定頻率信號(hào),通過(guò)可編程的并行外圍接口芯片 8255(或 8255A)控制其發(fā)音。揚(yáng)聲器的控制驅(qū)動(dòng)電路如下圖所示。
- 可編程的并行接口芯片 8255 有三個(gè) 8 位的并行端口:A 口、B 口和 C 口。在 IBM 系列微機(jī)中,BIOS 在開機(jī)自檢后已將 8255 初始化為 A 口和 C 口用于輸入,B 口用于輸出。B 口的 I/O 端口地址
為 61H。 - 由圖可見, 8255 的 B 口的低兩位用來(lái)控制揚(yáng)聲器驅(qū)動(dòng),當(dāng) 61H 端口的 D0 位為“1”時(shí),控制 8254定時(shí)器產(chǎn)生驅(qū)動(dòng)揚(yáng)聲器發(fā)聲的音頻信號(hào),該位為“0”則不發(fā)信號(hào)。8254 有三個(gè)定時(shí)器,分為 0 號(hào)、1號(hào)和 2 號(hào)定時(shí)器,驅(qū)動(dòng)揚(yáng)聲器的是 2 號(hào)定時(shí)器,該定時(shí)器工作在方式 3,是一個(gè)頻率發(fā)生器,它負(fù)責(zé)向揚(yáng)聲器發(fā)送指定頻率的脈沖信號(hào)。
- 輸出端口 61H 的 D1 位為“1”或?yàn)椤?”時(shí),將使控制驅(qū)動(dòng)器的與門電路接通或關(guān)閉,使 8254 所發(fā)出的音頻信號(hào)能到達(dá)驅(qū)動(dòng)器或被阻斷。這樣通過(guò)控制 D1 位的變化,可使揚(yáng)聲器接通和斷開,控制揚(yáng)聲器是否能發(fā)出聲音。此外,通過(guò)控制 D1 位的通斷時(shí)間,就能發(fā)出不同的音長(zhǎng)。
- 故當(dāng) 8255 輸出端口 61H 的 D1 位為“1”時(shí),在 61H 的 D0 位為“1”,8254 發(fā)出指定頻率的聲音信號(hào)的前提下,聲音信號(hào)通過(guò)與門到達(dá)驅(qū)動(dòng)器驅(qū)動(dòng)揚(yáng)聲器發(fā)聲。即是,如要 8255 控制 8254 的 2 號(hào)定時(shí)器驅(qū)動(dòng)揚(yáng)聲器發(fā)聲,則需要的匯編命令如下:
- 同時(shí),定時(shí)器 8254 的 2 號(hào)定時(shí)器使用 1.19MHz 的基準(zhǔn)頻率,故若要 8254 驅(qū)動(dòng)揚(yáng)聲器發(fā)出指定頻率的聲音,則需要向 2 號(hào)定時(shí)器的計(jì)數(shù)常數(shù)寄存器(即 I/O 端口 42H)存放基準(zhǔn)頻率除以指定頻率的商(即 122870H/指定頻率),該商需分兩次送往 I/O 端口 42H,先送商的低字節(jié),再送商的高字節(jié)。同時(shí),在使用定時(shí)器 8254 的 2 號(hào)定時(shí)器之前,需要初始化,即往 8254 的 2 號(hào)定時(shí)器的控制寄存器(即 I/O 端口 43H)寫控制字 0B6H:
以上是控制揚(yáng)聲器發(fā)出一定頻率的聲音,若要讓聲音按指定時(shí)間持續(xù),可使用 BIOS 提供的時(shí)間中斷 INT 1AH 的 00H 號(hào)功能作延時(shí),該功能提供了時(shí)間計(jì)數(shù)器的當(dāng)前值。時(shí)間計(jì)數(shù)器計(jì)數(shù)一次的時(shí)間約為 55.072ms。
3. 實(shí)驗(yàn)箱電路及具體接線
(1)在實(shí)驗(yàn)箱中,原 8255 的 61H 端口使用發(fā)生了變化:
需要把實(shí)驗(yàn)箱 8255 的控制口(28bh)進(jìn)行初始化,然后再對(duì) 288H 端口進(jìn)行寫操作。因?yàn)橐陨隙丝谔?hào)超過(guò)了 255,故寫端口時(shí),需要用 DX 寄存器暫存端口號(hào),如下:
(2)8254 的 2 號(hào)定時(shí)器初始化的端口從 43H 變成了 283H,且需要寫控制字 00110110B,如下:
mov dx, 283H mov al, 00110110B out dx, al且原 2 號(hào)定時(shí)器的計(jì)數(shù)常數(shù)寄存器端口(42H 端口)改為了 280H。
8255/CS接I/O 地址譯碼/Y1(288H——28FH)
8255/PA0接與門/A
8254/CLK0接時(shí)鐘/1MHz
8254/CS接I/O 譯碼/Y0(280H——287H)
8254/OUT0接 與門/B
8254/GATE0接與門/Y
8255/PA1接 喇叭
要求
試設(shè)計(jì)一個(gè)程序,能夠使用鍵盤中字母鍵模擬鋼琴按鍵發(fā)音。其中,按照字母在鍵盤中的排列方式,字母鍵 z/x/c/v/b/n/m 分別發(fā)出低 1—低 7 共 7 個(gè)低音音符,字母鍵 a/s/d/f/g/h/j 分別發(fā)出中 1—中 7 共 7 個(gè)中音音符,字母鍵 q/w/e/r/t/y/u 分別發(fā)出高 1—高 7 共 7 個(gè)高音音符。按 ESC 鍵退出程序。
源代碼
assume ds:data, ss:stack, cs:code data segmentdw 'z', 'x', 'c', 'v', 'b', 'n', 'm'dw 'a', 's', 'd', 'f', 'g', 'h', 'j'dw 'q', 'w', 'e', 'r', 't', 'y', 'u'dw 131, 147, 165, 175, 196, 220, 247dw 262, 294, 330, 349, 392, 440, 494dw 524, 587, 659, 698, 784, 880, 988data endsstack segmentdw 128 dup(0) stack endscode segment start: ; set segment registers:mov ax, datamov ds, ax mov ax, stackmov ss, ax mov sp, 256 ;調(diào)用子程序call piano ; exit to operating system.mov ax, 4c00h int 21h piano proc ;初始化2號(hào)定時(shí)器mov dx, 283h mov al, 00110110bout dx, al lop: ;char 輸入至 al.存入bl mov ah, 1int 21hmov bl, al ;判斷esccmp bl, 27 je stop ;循環(huán)比較key----------------------mov cx, 21mov si, 0 ;記錄key位置 compare: cmp bl, ds:[si];不同則跳過(guò)jne continue ;相同則發(fā)聲并退出comparemov bx, ds:[si][42]; 存頻率;求商 -> 2號(hào)定時(shí)器的計(jì)數(shù)常數(shù)寄存器mov dx, 12hmov ax, 2870hdiv bxmov dx, 280hout dx, almov al, ahout dx, al;控制2號(hào)定時(shí)器驅(qū)動(dòng)揚(yáng)聲器發(fā)聲 mov dx, 28bh ;初始化控制口mov al, 10000000b out dx, almov dx, 288h ;寫端口mov al, 03hout dx, al ;持續(xù)一會(huì)就結(jié)束 call delay mov dx, 288h ;寫端口mov al, 0hout dx, al jmp break continue: add si, 2loop compare ;循環(huán)比較key---------------------break: jmp lop stop:ret ;返回主程序 piano endp delay proc push cxpush ax push bx push dxmov ah, 0 ;獲取時(shí)鐘int 1ah mov bx, dx;存鬧鐘add bx, 50 ;延時(shí)0.2s dlop: mov ah, 0 ;獲取時(shí)鐘 int 1ah cmp dx, bx jb dloppop dxpop bx pop axpop cxret delay endp code endsend start ; set entry point and stop the assembler.總結(jié)
- 上一篇: 防丢器技术支持。
- 下一篇: 定义struct结构体数组