設計壹個音樂程序
1352282
壹. 設計任務及要求
1. 以8255接八個開關K1~K8,做電子琴按鍵輸入。
2. 以8253控制揚聲器,撥動不同的開關,發出相應的音階。
要求: K1—靜音
K2—發si的音493Hz
K3—發la的音440Hz
K4—發sol的音392Hz
K5—發fa的音349Hz
K6—發mi的音329Hz
K7—發re的音293Hz
K8—發do的音261Hz
二. 方案比較和認證
通過8255和8253來實現電子琴模擬,主要可以分成兩部分,分別為輸入部分和發音部分。輸入部分主要是由8255和8個常開型開關來完成。常開型開關如右圖。8個常開型開關K1~K8與8255的A口PA0~PA7相接,不觸動開關時,為高電平輸入,當按下開關時,就接地,為低電平輸入。例如當K1鍵按下時,從8255中A口輸入的數為11111110B,十六進制為0FEH。每壹個開關按下時,都對應壹個ASCII碼,如下表所示:
開 關 K1 K2 K3 K4 K5 K6 K7 K8
對應數據 0FEH 0FDH 0FBH 0F7H 0EFH 0DFH 0BFH 7FH
對應頻率 靜音 493 Hz 440 Hz 392 Hz 349 Hz 329 Hz 293 Hz 261 Hz
輸入部分的硬件實現比較簡單,所以說主要還是在發音部分。在設計中驅動揚聲器地聲的主要有兩種方式,分別是以位觸發和定時器控制。下面就這兩種不同的方式確定兩個不同的設計方案。
方案1:
發聲采用位觸發方式。電路原理圖如下所示。程序直接控制PPI(8255可編程序外圍接口芯片)的輸出控制寄存器(I/O端口為61H)的第壹位,使該位按所需的頻率進行1和0的交替變化,從而產生壹串脈沖控制波形,這些脈沖經過放大後驅動揚聲器發出聲音。
可以利用軟件延時來控制所產生的脈沖波形的長度和脈寬,就可以實現產生不同頻率和不同音長的聲音。軟件實現的程序如下:
IN AL,61H
MOV AH,AL
AND AL,0FCH ;關斷定時器通道2的門控
SOUND:XOR AL,2 ;觸發61H端口第1位
OUT 61H,AL
MOV CX,DX ;(DX)=控制脈沖的計數值
WAIT: LOOP WAIT ;延時循環
DEC BX ;(BX)=脈沖持續的時間
JNZ SOUND
MOV AL,AH
OUT 61H,AL ;恢復61H端口
在本方案中,通過程序的方法來控制PB1,使其在1和0之間按壹定的頻率變,從而產生壹串脈沖。控制脈沖寬度的計數值的算法如下:
計數值=2801*100/音頻
如果音頻為f,則脈沖周期1/f壹個半波的時間為1/2f秒,而1/2f秒的延時可簡單地通過LOOP指令的循環來取得,由於2801次LOOP指令循環執行所需時間是10MS,所以壹秒鐘時間約執行2801*100次LOOP指令。控制脈沖寬度的計數值的實現程序如下:
MOV AX,2801
MOV BX,50 ;頻率不同該值就不同
MUL BX
DIV DI ;(DI)= f
MOV DX,AX ;(DX)=1/2f
算出了脈沖寬度,再通過高低電平的不斷變換,就可實現不同頻率的脈沖方波。把此方波經濾波放大即可驅動揚聲器發聲了。
方案2:
利用定時器發聲。這裏是通過硬件即8253定時器產生聲音。
CUP通過對定時器的通道2進行編程,使其I/O寄存器接收壹個控制聲音頻率的16位計數值,端口61H的最低位控制通道2門控的開斷,以產生特殊的音響。當定時器接收的計數值為533H時,能產生896Hz的聲音,因此產生其他頻率的計數值就可由下式計算:
計數值=533H×896÷ f=1234DCH÷ f
在送出頻率計數值之前,還要給方式寄存器送壹個方式值,該數決定對哪壹個通道編程,采用什麽模式,送入通道的計數值是壹字節還是兩字節,是二進制碼還是BCD碼。其位組合的格式如下:
當通道2用於發聲時,采用的是模式3,在模式3下,輸出線為“1”和為“0”的時間各占計數時間的壹半,因而產生壹系列間隔均勻的脈沖。
產生指定頻率聲音的程序段如下:
MOV AL,0B6H
OUT 43H,AL ;43H為8253的控制字端口
MOV DX,12H
MOV AX,34DCH
DIV DI ;(DI)=頻率
OUT 42H,AL ;42H為8253的通道2端口
MOV AL,AH
MOV 42H,AL
從定時器輸出的方波信號,經功率放大和濾波後驅動揚聲器。送到揚聲器的信號還受到了從並行接口芯片8255(端口地址為61H)來的雙重控制,端口61H的最低位控制通道2的門控開斷,以產生特殊的音頻信號,端口61H的PB1位和定時器的輸出信號同時作為與門的輸入,PB0和PB1位可由程序決定為0還是為1。顯然只有PB0和PB1都是1時,才能使揚聲器發出聲音。控制音長的時間可以簡單地通過反復執行指令來得到。我們知道執行2801次LOOP指令約需要10MS的時間。因此用10MS的倍數值來控制揚聲器開關的時間間隔,就可控制發聲的音長了。實現程序如下:
IN AL,61H
MOV AH,AL
OR AL,3
OUT 61H,AL ;開揚聲器
L: MOV CX,2801
DY:LOOP DY
DEC BX
JNZ L
MOV AL,AH
OUT 61H,AL ;關揚聲器
下圖是利用定時器發音的電路圖。
方案比較:
在上述兩個方案中,輸入部分都是壹樣的。區別在於以不同的方式來驅動揚聲器發聲。經對比可知,兩種方案都各有優缺點。在方案1中,其優點是電路簡單,所用的器件芯片少,主要芯片只有需壹片8255,產生方波是通過軟件來實現的,易於修改和維護。然而它也存在壹定的缺點,就是系統不斷地通過軟件來產生方波,系統資源被占用,無法再做其它事。與方案1相比,方案2增加了壹個8253芯片和壹個與門,雖然電路比方案1復雜,但通過定時器產生方波,實現起來比較簡單,而且也不會出現系統資源被全部占用的情況。
經分析,選擇方案2進行設計。
三. 硬件原理,器件功能
在方案2的設計中用到了兩個主要的芯片,壹個是並行接口8255,另壹個是計數器8253。下面就先介紹壹下這兩個器件的主要功能以及在這個系統中所應用的功能。
1.8255並行接口。
8255是壹個40引腳的雙列直插式集成電路芯片。按功能可把8255分為三個邏輯電路部分,即:口電路、總線接口電路和控制邏輯電路。8255***有三個8位口,其中A口和B口是單純的數據口,供數據I/O使用。而C口則既可以作數據口,又可以作控制口使用,用於實現A口和B口的控制功能。總線接口電路用於實現8255和單片微機的信號連接。其中包括:數據總線緩沖器,讀/寫控制邏輯,控制邏輯電路。內部的結構如下圖所示。
8255的引腳信號中,除了電源和地以外,其他信號可以分為兩組:
1.和外設壹邊相連的:
PA7-PA0:A組數據信號
PB7-PB0:B組數據信號
PC7-PC0:C組數據信號
2.和CPU壹邊相連的:
RESET:復位信號,低電平有效。當RESET信號來到時,所有內部寄存器就被清除,同時,3個數據端口被自動設為輸入端口。
D7-D0:它們是8255的數據線,和系統數據總線相連。
:芯片選擇信號,低電平有效。在壹個系統中,壹般根據全部接口芯片來分配若幹較低位地址(比如A5、A4、A3)來組成各種芯片選擇碼,當這幾位地址組成某壹個代碼時,譯碼器便往8255的端 輸出壹個低電平,於是8255被選中。只有當 有效時,讀信號 和寫信號 才對8255有效。
:芯片讀出信號低電平有效。
:芯片寫入信號低電平有效。
8255***有四個可尋址的端口(即A口、B口、C口和控制寄存器),用二位地址編碼即可實現選擇。參見下表。
8255***有三種工作方式,即方式0、方式1、方式2。
1.方式0為基本輸入/輸出方式,方式0下,可供使用的是兩個8位口(A口和B口)及兩個4位口(C口高4位部分和低4位部分)。四個口可以是輸入和輸出的任何組合。方式0適用於無條件數據傳送,也可以把C口的某壹位作為狀態位,實現查詢方式的數據傳送。
2.方式1為選通輸入/輸出方式,A口和B口分別用於數據的輸入/輸出。而C口則作為數據傳送的聯絡信號。A口和B口的聯絡信號都是三個,如果A或B只有壹個口按方式1使用,則剩下的另外13位口線仍然可按方式0使用。如果兩個口都按方式1使用,則還剩下2位口線,這兩位口線仍然可以進行位狀態的輸入輸出。方式1適用於查詢或中斷方式的數據輸入/輸出。
8255作為輸入時如下圖。輸入過程如下:當輸入設備準備好數據,將數據送至PA7~PA0或PB7~PB0,同時發 ,在 下降沿控制下,8255將PA7~PA0或PB7~PB0上的數據鎖存到A口或B口數據輸入寄存器中,同時8255向輸入設備發IBF有效,告知輸入設備暫緩送數。8255A可以兩種方式通知CPU取走數據: 第壹種方式是用中斷方式,在INTE=1∩IBF=1時, 的上升沿使INTR=1,8255向CPU提出中斷申請,CPU以中斷方式取走數據,在CPU響應中斷後,執行IN指令,將8255 A口或B口數據輸入寄存器中的數據取走,同時, 信號的下降沿清除INTR信號, 信號的上升沿復位IBF。輸入設備僅當檢測到IBF為低電平後,才開始傳送下壹個數據,如此循環;第二種方式是用軟件查詢,CPU僅當查詢到IBF=1時,才從8255A 口或B口數據輸入寄存器中取走數據。
8255作為輸出時如下圖所示。輸出過程如下:首先CPU執行OUT指令,在 信號的下降沿CPU輸出的數據送入8255數據輸出緩沖器,並使INTR復位。 信號上升沿將 置為有效,通知輸出設備,CPU已把數據輸出到8255的指定端口中,輸出設備接到 信號有效後,發 有效, 下降沿將 置為1, 上升沿表示輸出設備已從8255A指定端口取走數據,此時若 INTE=1,則INTR被置為高電平,向CPU申請中斷,CPU可采用中斷方式輸出下壹個數據。CPU也可通過查詢 信號,若 =1,CPU輸出下壹個數據給8255A,即查詢方式傳送數據。
3.方式2雙向數據傳送方式。只允許A口工作在方式2,當A口工作在方式2時,B口可工作在方式0或方式1。 所謂雙向,即A口可分時進行I/O操作。 A口工作在方式2,信號聯絡線如下:
(PC6), (PC7), (PC4),IBFA(PC5);
INTE1(PC6)與輸出中斷有關,可由用戶給8255A控制字寄存器送PC6的置位/復位字來實現允許/禁止A口輸出中斷。
INTE2(PC4):與輸入中斷有關,可由用戶給8255A控制字寄存器送PC4的置位/復位字來實現允許/禁止A口輸入中斷。
INTRA(PC3):I/O中斷申請,高電平有效,產生中斷請求信號的條件為: INTRA=IBFA·INTE2· · (輸入中斷);
INTRA= ·INTE1· · (輸出中斷)。
在本設計系統中運用的是工作方式0,這種方式比較簡單。在這裏,主要是A口用於輸入,與8個常開型開關連接,用於采集輸入。B口中的PB1和PB0用於控制發聲。
2.計數器/定時器8253。 8253是8254的改進型,右圖是它的芯片實物圖。8253包括3個獨立的16位計數器通道,而每個計數器都有6種工作方式,可以按二進制或十進制(BCD碼)進行計數。如下圖為8253的內部結構圖。在圖中可以清楚地看到,8253主要是由數據總線緩沖存儲器,讀寫控制電路,控制字寄存器和3個通道4部分所組成。
1. 數據總線緩沖器是8253與CPU DB連接的8位雙向三態緩沖器,CPU通過它向8253寫方式控制字到控制字寄存器中,寫計數初值到計數通道,讀取計數通道的當前計數值。
2. 讀/寫控制邏輯控制8253內部操作。當 無效,8253的DB處於高阻狀態,當 有效, 和A1、A0、 、 組合,對3個計數通道、控制字寄存器進行讀/寫操作。
3. 控制字寄存器 8253初始化編程時,CPU寫控制字到控制字寄存器,以選擇計數通道及相應的工作方式。
4. 數通道0~2。8253內部包括3個功能完全相同和操作完全獨立的計數通道,每個計數通道由16位減法計數器、16位計數初值寄存器和16位計數值鎖存器組成。初始化時,向計數通道裝入的計數初值,先送到計數初值寄存器中保存,然後送到減法計數器。計數器啟動後,減法計數器對CLK的下降沿進行減1計數,在未鎖定時把結果送入16位計數值鎖存器中。當計數值減到0時,輸出OUT信號,壹次計數結束。計數初值寄存器的內容,在計數過程中保持不變。計數初值寄存器和計數值鎖存器占用壹個端口地址(即該計數通道口地址),CPU讀取計數通道的當前計數值來自計數值鎖存器。
各通道可工作在計數器方式,此時被計數的事件以脈沖方式從CLK輸入;
各通道可工作在定時器方式,此時確定頻率的時鐘脈沖從CLK輸入。
計數初值=定時時間÷CLK周期
各通道的啟動、禁止、允許計數與門控信號GATE有關,GATE的作用OUT的輸出波形隨各通道工作方式不同而不同。
8253即可以作為計數器又可以作為定時器使用。在本系統中主要是運用了其計數功能。在8253的3個計數器中,都有6種不同的工作方式,其中工作方式3可稱為方波發生器,其產生的方波正是在發聲系統中所需要的。所以在這裏就應用了8253作計數器並工作在方式3下。
下圖為8253工作方式3的定時波形圖。
任壹通道工作在方式3,只在計數值n為偶數,則可輸出重復周期為n,占空比為1:1的方波。如圖所示,進入工作方式3,OUT輸出低電平,裝入計數值n後,OUT立即跳變為高電平。如果當前GATE為高電平,則立即開始減1計數,OUT保持為高電平。當計數值減到n/2時,OUT跳變為低電平,壹直保持到計數值為0,系統就會自動重新置入計數值n,實現循環計數。這時OUT端輸出的周期為n×CLK周期,占空比為1:1的方波序列。
如果在操作過程中,GATE變為無效,則暫停減1計數過程,直到GATE再次有效,重新從初值n開始減計數。這壹點對本系統來說非常重要。這使得在控制發聲時可以方便隨時停止。
下面的是8253的6種工作方式下的輸出波形圖。在這裏就不再壹壹闡述了。
四. 系統原理
經過分析對比上述的兩種方案可知,選取方案2是比較合理的。下面就方案2來分析壹下整個系統的工作原理。前面已經提到,整個電路分成輸入和發音兩大部分。主要的器件有壹個並行接口8255,和壹個8253定時器。輸入部分的硬件原理圖比較簡單,如右圖所示的為輸入電路,其主要是由8個常開型開關和壹個並行接口8255組成。由圖中可看到,8個開關壹端接地,另壹端接到8255的A口輸入,並且通過壹個電阻接到+5V。因此,在開關不按下時,從8255A口輸入的是高電平,當開關按下時,輸入的則是低電平,這樣通過低電平觸發,既方便也對芯片起保護作用。如下表,當不同的開關按下時,從A口輸入就對應壹個8位的數據。
開 關 K1 K2 K3 K4 K5 K6 K7 K8
輸入數據 0FEH 0FDH 0FBH 0F7H 0EFH 0DFH 0BFH 7FH
通過軟件檢測輸入的數據,然後給8253送相應頻率的計數值。檢測的程序如下:
IN AL,60H ;從8255A口輸入壹個數據
CMP AL,0FEH
JZ K1 ;K1—K8分別為不同程序斷的標號
CMP AL,0FDH
JZ K2
CMP AL,0FBH
JZ K3
CMP AL,0F7H
JZ K4
CMP AL,0EFH
JZ K5
CMP AL,0DFH
JZ K6
CMP AL,0BFH
JZ K7
CMP AL,7FH
JZ K8
對於發音部分。PC機上的大多數輸入/輸出(I/O)都是由主板上的8255(或8255A)可編程序外圍接口芯片(PPI)管理的。PPI包括3個8位寄存器,兩個用於輸入功能,壹個用於輸出功能。輸入寄存器分配的I/O端口號為60H和62H,輸出寄存器分配的I/O端口號為61H。由PPI輸出寄存器中的0、1兩位來選擇揚聲器的驅動方式。如下圖。
連接到揚聲器上的是定時器2,從上圖可以看到,GATE2與端口61H的PB0相連,當PB0=1時,GATE2獲得高電平,使定時器2可以在模式3(方波)下工作。定時器2的OUT2與端口61H的PB1通過壹個與門與揚聲器的驅動電路相連。當PB1=1時,允許OUT2的輸出信號到達揚聲器電路。因此,只有PB0和PB1同時為“1”時,才能驅動揚聲器地聲。通過以下指令實現:
IN AL,61H
OR AL,3
OUT 61H,AL
上面的指令用以打開揚聲器,如要關閉揚聲器時則為:
AND AL,0FCH
OUT 61H,AL
當從8255中采集到輸入的數據時,需要確定相應的頻率,所以在軟件編程時要建立壹個數據表:
TABLE DW 493,440,392,349,329,293,261
把相應的頻率送到壹個寄存器上,通過公式:
計數值=533H×896÷ f=1234DCH÷ f
算出計數值,再把算得的計數值送給8253,就可產生所要頻率的方波。在把計數值送8253前,必須先把8253進行初始化:
MOV AL,0B6H
OUT 43H,AL
使其選用通道2,工作在方式3下。
就整個電路而言,接好電路後,通過軟件編程不斷地采集從8255口中輸入的信號,而8個開關都接在8255的A口上,只要有開關按下,就會采集到壹個數據,根據這個數據與事先編好的表對應,得到壹個計數值,把這個計數值送給8253的通道2,8253的通道2工作的方式3下,這樣就可以產生滿足頻率要求的發聲方波。這個方波經驅動放大就可以使揚聲器發出相應的聲音。
所以8255在這裏完成兩個任務,它不僅從A口中采集到數據,而且B口的PB1和PB0兩個位要控制發聲。8253的主要任務就是產生所要求發聲的不同頻率的方波。
五. 電路圖
下圖即為本設計中所采用的方案2的硬件連線圖。
在設計過程中,獨立編址時,用地址線的高位部分和控制信號(如RD、WR、M/IO)進行組合產生 I/O接口電路的片選信號(CS),用地址線的低位部分直接連到 I/O接口芯片實現端口的選擇。在此采用的是譯碼器譯碼,電路圖如下所示,經過74LS138譯碼後, 輸出作為8253的片選信號(CS),即其端口地址為40H~43H。 輸出作為8255的片選信號(CS),即其端口地址為60H~63H。
六. 軟件思想,流程圖,源程序
軟件部分對整個系統來說起著重要的作用,在本電子琴系統中,軟件可以分為三部分,主程序部分,發音子程序部分和延時子程序部分。
主程序的流程圖如下:
發聲程序包括3個步驟:
(1)在8253中的42端口送壹個控制字0B6H(10110110B),該控制字對定時器2進行初始化,使定時器2準備接收計數初值。
(2)在8253中的42H端口(Timer2)裝入壹個16位的計數值(533H×895/頻率),以建立將要產生的聲音頻率。
(3)把輸出端口61H的PB0、PB1兩位置1,發出聲音。
以下是發聲子程序的流程圖:
我們知道LOOP指令執行2801次的時間為10ms,所以延時子程序則很簡單,只需要反復執行LOOP指令就可實現,並且所得到的延時時間為10ms的倍數。
下面即為整個程序代碼: