A. 急求 單片機原理與技術 周明德 課後習題答案
第1章 作 業 答 案
1.1 微處理器、微型計算機和微型計算機系統三者之間有什麼不同?
解:
把CPU(運算器和控制器)用大規模集成電路技術做在一個晶元上,即為微
處理器。微處理器加上一定數量的存儲器和外部設備(或外部設備的介面)構成了
微型計算機。微型計算機與管理、維護計算機硬體以及支持應用的軟體相結合就形
成了微型計算機系統。
1.2 CPU在內部結構上由哪幾部分組成?CPU應該具備哪些主要功能?
解:
CPU主要由起運算器作用的算術邏輯單元、起控制器作用的指令寄存器、指
令解碼器、可編程邏輯陣列和標志寄存器等一些寄存器組成。其主要功能是進行算
術和邏輯運算以及控制計算機按照程序的規定自動運行。
1.3 微型計算機採用匯流排結構有什麼優點?
解:
採用匯流排結構,擴大了數據傳送的靈活性、減少了連線。而且匯流排可以標准
化,易於兼容和工業化生產。
1.4 數據匯流排和地址匯流排在結構上有什麼不同之處?如果一個系統的數據和地址合用
一套匯流排或者合用部分匯流排,那麼要靠什麼來區分地址和數據?
解:
數據匯流排是雙向的(數據既可以讀也可以寫),而地址匯流排是單向的。
8086CPU為了減少晶元的引腳數量,採用數據與地址線復用,既作數據匯流排也作為
地址匯流排。它們主要靠信號的時序來區分。通常在讀寫數據時,總是先輸出地址
(指定要讀或寫數據的單元),過一段時間再讀或寫數據。
1.8在給定的模型中,寫出用累加器的辦法實現15×15的程序。
解:
LD A, 0
LD H, 15
LOOP:ADD A, 15
DEC H
JP NZ, LOOP
HALT
第 2 章 作 業 答 案
2.1 IA-32結構微處理器直至Pentillm4,有哪幾種?
解:
80386、30486、Pentium、Pentium Pro、Peruium II 、PentiumIII、Pentium4。
2.6 IA-32結構微處理器有哪幾種操作模式?
解:
IA一32結構支持3種操作模式:保護模式、實地址模式和系統管理模式。操
作模式確定哪些指令和結構特性是可以訪問的。
2.8 IA-32結構微處理器的地址空間如何形成?
解:
由段寄存器確定的段基地址與各種定址方式確定的有效地址相加形成了線性地址。若末啟用分頁機制,線性地址即為物理地址;若啟用分頁機制,則它把線性地址轉為物理地址。
2.15 8086微處理器的匯流排介面部件由哪幾部分組成?
解:
8086微處理器中的匯流排介面單元(BIU)負責CPU與存儲器之間的信息傳
送。具體地說,BIU既負責從內存的指定部分取出指令,送至指令隊列中排隊
(8086的指令隊列有6個位元組,而8088的指令隊列只有4個位元組);也負責傳送執
行指令時所需的操作數。執行單元(EU)負責執行指令規定的操作。
2.16 段寄存器CS=120OH,指令指針寄存器IP=FFOOH,此時,指令的物理地址為
多少?
解:
指令的物理地址=12000H+FFOOH=21FOOH
第 3 章 作 業 答 案
3.1分別指出下列指令中的源操作數和目的操作數的定址方式。
(1)MOV SI, 30O
(2)MOV CX, DATA[DI]
(3)ADD AX, [BX][SI]
(4)AND AX, CX
(5)MOV [BP], AX
(6)PUSHF
解:
(l)源操作數為立即定址,目的操作數為寄存器定址。
(2)源操作數為變址寄存器加位移量定址,目的操作數為寄存器定址。
(3)源操作數為基址加變址定址,目的操作數為寄存器定址。
(4)源操作數和目的操作數都為寄存器定址。
(5)源操作數為寄存器定址,目的操作數為寄存器間接定址。
(6)為堆棧操作。
3.2 試述指令MOV AX,2000H和MOV AX,DSz[2000H]的區別。
解:前一條指令是立即定址,即把立即數2000H傳送至寄存器AX。後一條指令
是直接定址,是把數據(DS)段中的地址為200OH單元的內容傳送至寄存器AX。
3.3 寫出以下指令中內存操作數的所在地址。
(1)MOV AL, [BX+10]
(2)MOV [BP+10], AX
(3)INC BYTE PTR[SI十5]
(4)MOV DL, ES:[BX+SI]
(5)MOV BX , [BP+DI+2]
解:
(1)數據段BX+10單元。
(2)堆棧段BP+10單元。
(3)數據段SI+5位元組單元。
(4)附加段(ES段)BX+SI單元。
(5)堆棧段BP+DI+2單元。
3.4 判斷下列指令書寫是否正確。
(1)MOV AL, BX
(2)MOV AL, CL
(3)INC [BX]
(4)MOV 5, AL
(5)MOV [BX], [SI]
(6)M0V BL, OF5H
(7)MOV DX, 2000H
(8)POP CS
(9)PUSH CS
解:
(l)不正確,AL與BX數據寬度不同。
(2)正確。
(3)不正確,因為不明確是增量位元組還是字。
(4)不正確,立即數不能作為目的操作數。
(5)不正確,因為不明確要傳送的是位元組還是字。
(6)正確。
(7)正確。
(8)不正確,CS不能作為:pop指令的操作數。
(9)不正確,CS不能作為PUSH指令的操作數。
3.5 設堆錢指針SP的初值為1000H,AX=2000H, BX=3000H,試問:
(1)執行指令PUSH AX後SP的值是多少?
(2)再執行PUSH BX及POP AX後,SP、AX和BX的值各是多少?
解:
(1) SP=OFFEH。
(2) SP=OFFEH; AX=3000H, BX=3000H。
3.6要想完成把[3000H]送[2000H]中,用指令:
MOM [200OH], [300OH]
是否正確?如果不正確,應該用什麼方法實現?
解: 不正確。
正確的方法是:
MOV AL, [300OH]
MOV [2000H], AL
3.7 假如想從200中減去AL中的內容,用SUB 200,AL是否正確?如果不正確,應該
用什麼方法?
解:不正確。
正確的方法是:
MOV BL, 200
SUB BL, AL
3.8 試用兩種方法寫出從8OH埠讀入信息的指令。再用兩種方法寫出從4OH口輸
出10OH的指令。
解:
(1)IN AL, 80H
(2)MOV DX, 8OH
IN AL, DX
(3)MOV, AL, lOOH
OUT 40H, AL
4)MOV AL, 10OH
MOV DX,4OH
OUT DX, AL
3.9假如:AL=20H,BL=1OH,當執行CMP AL,BL後,問:
(1)AL、BL中的內容是兩個無符號數,比較結果如何?影響哪兒個標志位?
(2)AL、BL中的內容是兩個有符號數,結果又如何,影響哪幾個標志位?
解:
(l)AL=2OH,BL=1OH,O=0,S=0,Z=0,A=0,P=0,C=0。
(2)因為兩個都是符號正數,其結果與(l)相同。
3.10 若要使AL×10,有哪幾種方法,試編寫出各自的程序段?
解:
(1)使用乘法指令:
MOV BL,10
MUL BI,
(2)使用移位指令:
SHL AL,1
MOV BL,AL
SHL AL, 2
ADD AL,BL
(3)使用加法指令:
ADD AL,AL
MOV BL, AL
ADD AL, AL
ADD AL, AL
ADD AL, BL
3.11 8086匯編語言指令的定址方式有哪幾類?哪種定址方式的指令執行速度最快?
解:定址方式分為:立即數定址方式、寄存器操作數定址方式和存儲器操作數尋
址方式。其中,寄存器操作數定址方式的指令執行速度最快。
3.12 在直接定址方式中,一般只指出操作數的偏移地址,那麼,段地址如何確定?如果要用某個段寄存器指出段地址,指令中應該如何表示?
解:
默認的數據訪問,操作數在DS段;堆棧操作在SS段;串操作源操作數(SI)在DS段,目的操作數(DI)在ES段;用BP作為指針在SS段。如果要顯式地指定段地址,則在操作數中規定段寄存器。例如:
MOV AX, ES:(BX+10H)
3.13 在寄存器間接定址方式中,如果指令中沒有具體指明段寄存器,那麼如何確定段地址?
解:
在寄存器間接定址方式中,如果指令中沒有具體指明段寄存器,段地址是
隱含約定的,也就是隱含地選擇段寄存器。如操作類型為指令,則指定代碼段寄
存器CS,如操作類型為堆棧操作,則指定堆找段寄存器SS,…,如表3-1中所示。
當需要超越約定時,通常用段替代前綴加冒號":"來表示段超越,它允許程序設計者偏離任何約定的段。
例如:
MOV ES:〔BX],AX
這時數據將從寄存器EAX傳送至附加段中由EBX定址的存儲單元,而不是傳送
到數據段中。
3.14 採用寄存器間接定址方式時,BX、BP、SI、DI分別針對什麼情況來使用?這4個寄存器組合間接定址時,地址是怎樣計算的?請舉例說明。
解: 在寄存器間接定址方式下,BX和BP作為間址寄存器使用,而SI、DI作為
變址寄存器使用。除BP間址默認的段為堆棧段,其他的都默認為數據段。它們
都可以單獨使用,或加上偏移量或組合使用。如:
[BX +n]
LBP +n]
[SI +n]
[DI +n]
[BX +SI +n]
[BX +DI +n]
[BP +SI +n]
[BP +DI +n]
3.15 設DS=2100H,SS=5200H,BX=1400H,BP=6200H,說明下面兩條指令所進行
的具體操作:
MOV BYTE PTR[BP],200
MOV WORD PTR[BX],2000
解:前一條指令是把立即數(應是位元組)200,傳送至堆棧段(BP的默認段〉偏移
量由BP規定的位元組單元,地址為:52000H+620OH=58200H
第二條指令是把立即數.2000,傳送至數據段(BX的默認段)偏移量由BX規定的
字單元,地址為:21000H+1400H = 22400H。
3.16 使用堆錢操作指令時要注意什麼問題?傳送指令和交換指令在涉及內存操作數時應該分別要注意什麼問題?
解:使用堆棧指令可以把內存單元作為一個操作數(從內存到內存)。但堆棧固定在堆棧段且只能由SP指向。且堆棧操作要修改堆核指針。MOV指令不能實現內存單元間的數據傳送。XCHG指令是交換,有一個操作數必須是寄存器。
3.17下面這些指令中哪些是正確的?哪些是錯誤的?若是錯誤的,請說明原因。
(1)XCHG CS, AX
(2)MOV [BX], [1000]
(3)XCHG BX, IP
(4)PUSH CS
(5)POP CS
(6)IN BX, DX
(7)MOV BYTE[BX], 100O
(8)MOV CS, [1000]
解:
(l)錯誤,CS不能交換。
(2)錯誤,MOV指令不能在內存間傳送。
(3)錯誤,IP不能交換。
(4)錯誤,CS可以作為PUSH指令的操作數。
(5)錯誤,CS可以作為POP指令的操作數。
(6)錯誤,IN指令的目的操作數是累加器。
(7)錯誤,目的操作數是位元組單元。
(8〉錯誤,CS不能作為MOV指令的目的操作數。
3.18 以下是格雷碼的編碼表,
O 0000
1 0001
2 0011
3 0010
4 0110
5 0111
6 0101
7 0100
8 1100
請用換碼指令和其他指令設計一個程序段,以實現由格雷碼向ASCII碼的轉換。
解:
MOV BX,TABLE
MOV SI,ASCII_TAB
MOV AL,0
MOV CX,10
TRAN: XLAT TABLE
MOV DL,AL
ADD DL,30H
MOV [SI],DL
INC AL
LOOP TRAN
3.19 使用乘法指令時,特別要注意先判斷是用有符號數乘法指令還是用無符號數乘法指令,這是為什麼?
解:因為有符號數和無符號數,其數的乘法是一樣的。但結果的符號取決於兩
個操作數的符號。
3.20 位元組擴展指令和字擴展指令一般用在什麼場合?舉例說明。
解:主要用於位元組相除和字相除之前,把被除數擴展為兩倍寬度的操作數。
3.21 什麼叫BCD碼?什麼叫組合的BCD碼?什麼叫非組合的BCD碼?8086匯編語言在對BCD碼進行加、減、乘、除運算時,採用什麼方法?
解:BCD碼為十進制編碼的二進制數。組合的BCD數是把兩位BCD加在一個位元組中,高位的在高4位。非組合的BCD碼是把一位BCD數放在一個位元組的低4位,高4位為0。8086在BCD加、減和乘法運算以後用BCD調整指令把結果調整為正確的BCD數。在BCD除法之前先用BCD調整指令再做除法.
3.22 用普通運算指令執行BCD碼運算時,為什麼要進行十進制調整?具體地講,在進行BCD碼的加、減、乘、除運算時,程序段的什麼位置必須加上十進制調整指令?
解:因為8086指令把操作數作為二進制數進行二進制運算,要得到正確的BCD結果,需要進行調整。在加、減、乘法指令之後加上BCD調整指令,而在除法指令之前先用BCD調整指令再用除法指令。
第4章 作業答案
4.1 在下列程序運行後,給相應的寄存器及存儲單元填入運行的結果:
MOV AL, 1OH
MOV CX, 100OH
MOV BX , 2000H
MOV [CX],AL
XCHG CX, BX
MOV DH, [BX]
MOV DL, 01H
XCHG CX, BX
MOV [BX],DL
HLT
解:寄存器及存儲單元的內容如下:
AL = 1OH
BL = OOH
BH = 2OH
CL = OOH
CH = 1OH
DH = 1OH
(10O0H) = lOH
(200OH) = 0lH
2.要求同題4.1,程序如下:
MOV AL, 50H
MOV BP, 100OH
MOV BX, 200OH
MOV [BP], AL
MOV DH, 20H
MOV [BX], DH
MOV DL, OlH
MOV DL, [BX]
MOV CX, 300OH
HLT
解:寄存器及存儲單元的內容如下:
AL = 5OH
BL = OOH
BH = 20H
CL = OOH
CH = 30H
DL = 20H
DH = 2OH
BP = 100OH
(10OOH) = 5OH
(20OOH) = 20H
4.3 自1000H單元開始有一個100個數的數據塊,若要把它傳送到自200OH開始的存
儲區中去,可以採用以下3種方法實現,試分別編製程序以實現數據塊的傳送。
(l)不用數據塊傳送指令
(2)用單個傳送的數據塊傳送指令
(3)用數據塊成組傳送指令。
解:
(1) LEA SI, 1OOOH
LEA DI, 200OH
MOV CX, 100
L1: MOV AX, [SI]
MOV [DI], AX
LOOP Ll
HLT
(2) LEA SI, 100OH
LEA DI, 2000H
MOV CX, 100
CLD
L1: MOVSB
LOOP L1
HLT
(3) LEA SI, 100OH
LEA DI, 200OH
MOV CX, 100
CLD
REP MOVSB
HLT
4.4 利用變址寄存器,編寫一個程序,把自1000H單元開始的100個數傳送到自1070H
開始的存儲區中去。
解:
LEA SI, 100OH
LEA DI, 1070H
MOV CX, 100
CLD
REP MOVSB
HLT
4.5 要求同題4.4,源地址為2050H,目的地址為2000H,數據塊長度為50.
解:
LEA SI, 205OH
LEA DI, 200OH
MOV CX, 50
CLD
REP MOVSB
HLT
4.6 編寫一個程序,把自100OH單元開始的100個數傳送'至105OH開始的存儲區中
(注意:數據區有重疊)。
解:
LEA SI, 100OH
LEA DI , 1050H
ADD SI, 63H
ADD DI, 63H
MOV CX, 100
STD
REP MOVSB
HLT
4.7 在自0500H單元開始,存有100個數。要求把它傳送到1000H開始的存儲區中,
但在傳送過程中要檢查數的值,遇到第一個零就停止傳送。
解:
LEA SI, 050OH
LEA DI, 10OOH
MOV CX, 100
N1: MOV AL, [SI]
CMP AL, 0
JZ N2
MOV [DI], AL
INC SI
INC DI
LOOP N1
N2: HLT
4.14若在0500H單元中有一個數
(1)利用加法指令把它乘2,且送回原存儲單元(假定X×2後仍為一個位元組);
(2)X×4;
(3)X×10(假定X×l0≤255).
解:
(1) LEA BX, 050OH
MOV AL, [BX]
ADD AL, AL
MOV [BX], AL
(2) LEA BX, 0500H
MOV AL, [BX]
ADD AL, AL
ADD AL, AL
MOV [BX], AL
(3) LEA BX, 050OH
MOV AL, [BX]
ADD AL, AL
MOV DL, AL
ADD AL, AL
ADD AL, AL
ADD AL, DL
MOV [BX], AL
第 5 章 作業答案
5.1 匯流排周期的含義是什麼?8086/8088CPU的基本匯流排周期由幾個時鍾組成?如果一個CPU的時鍾頻率為8MHz,那麼,它的一個時鍾周期是多少?一個基本匯流排周期是多少?如果主頻為5MHz呢?
解: CPLI訪問匯流排(從內存儲器或I/0埠讀/寫位元組或字)所需的時間稱為匯流排周期。8086/8088CPU的基本匯流排周期由4個時鍾組成。若CPU的時鍾頻率為8(5)MHz,時鍾周期為1/8MHz=125(1/5MHz=2O)ns,基本匯流排周期為4×125(200)ns=500(800)ns
5.2 在匯流排周期的TI、T2、T3、T4狀態,CPU分別執行什麼動作?什麼情況下需要插入
等待狀態Tw? Tw在哪兒插入? 怎樣插入?
解: 下面以存儲器讀為例進行說明。
在Tl周期:輸出地址信號、地址鎖存允許信號、內存或I/O埠訪問控制信號;
在T2周期:CPIJ開始執行數據傳送操作,此時,8086CPU內部的多路開關進行切換,將地址/數據線AD15~AD0上的地址撤銷,切換為數據匯流排,為讀寫數據作準備。8288匯流排控制器發出數據匯流排允許信號和數據發送/接收控制信號DT/R允許數據收發器工作,使數據匯流排與8086CPU的數據線接通,並控制數據傳送的方向。同樣,把地址/狀態線A19/S6~A16/S3切換成與匯流排周期有關的狀態信息,指示若干與周期有關的情況。
在T3周期:開始的時鍾下降沿上,8086CPU采樣READY線。如果READY信號有效(高電平),則在T3狀態結束後進人TA狀態。在T4狀態開始的時鍾下降沿,把數據匯流排上的數據讀入CPU或寫到地址選中的單元。
在T4狀態:結束匯流排周期。如果訪問的是慢速存儲器或是外設介面,則應該在Tl狀態輸出的地址,經過解碼選中某個單元或設備後,立即驅動READY信號到低電平。8086CPU在T3狀態采樣到READY信號無效,就會插入等待周期Tw,在Tw狀態CPU繼續采樣READY信號;直至其變為有效後再進人T4狀態,完成數據傳送,結束匯流排周期。在T4狀態,8086CPU完成數據傳送,狀態信號 。變為無操作的過渡狀態。在此期間,8086CPU結束匯流排周期,恢復各信號線的初態,准備執行下一個匯流排周期。
第 6 章 作 業 答 案
6.1 若有一單板機,具有用8片2114構成的4KBRAM,連線如圖創所示。
若以每1KB RAM作為一組,則此4組RAM的基本地址是什麼?地址有沒有重疊區?每一組的地址范圍為多少?
解:RAM的基本地址為:
第一組 OOOOH ~ 03FFH
第二組 4000H ~ 43FFH
第三組 8000H ~ 83FFH
第四組 COOOH ~ C3FFH
地址有重疊區。每一組的地址范圍為OOOH ~ 3FFH(1024個位元組)。
6.4 若要擴充1KB RAM(用2114片子),規定地址為8000H~83FFH,地址線應該如何
連接?
解: 擴充lKB RAM至規定地址8000H ~ 83FFH,其地址線的低10位接晶元,高6位地址(Al5 ~A10 = 100000)產生組選擇信號。
第 7 章 作 業 答 案
7.1 外部設備為什麼要通過介面電路和主機系統相連?
解: 因為外部設備種類繁多,輸入信息可能是數字量、模擬量或開關量,而且輸入速度、電平、功率與CPU差距很大。所以,通常要通過介面電路與主機系統相連。
7.4 CPU和輸入輸出設備之間傳送的信息有哪幾類?
解:CPU和輸入輸出設備之間傳送的信息主要有3類。
(l)數據
在微型計算機中,數據通常為8位、16位或32位。
(2)狀態信息
在輸入時,有輸入設備的信息是否准備好;在輸出時有輸出設備是否有空,若輸出設備正在輸出信息,則以忙指示等。
(3)控制信息
例如,控制輸入輸出設備啟動或停止等。
7.9 設一個介面的輸入埠地址為0100H,狀態埠地址為0104H,狀態埠中第5位為1表示輸入緩沖區中有一個位元組准備好,可以輸入。設計具體程序以實現查詢式
輸入。
解: 查詢輸入的程序段為:
POLl : IN AL, 0104H
AND AL, 20H
JZ POLl
IN AL, 0100H
第 8 章作 業 答 案
8.1 在中斷響應過程中,8086CPU向8259A發出的兩個RT互信號分別起什麼作用?
解: CPU發出的第一個 脈沖告訴外部電路,其提出的中斷請求已被響應,
應准備將類型號發給CPU,8259A接到了這個 脈沖時,把中斷的最高優先順序
請求置入中斷狀態寄存器(ISR)中,同時把IRR(中斷請求寄存器)中的相應位復
位。CPU發出的第二個 脈沖告訴外部電路將中斷的類型號放在數據匯流排上。
8.2 8086CPU最多可以有多少個中斷類型?按照產生中斷的方法分為哪兩大類?
解:8086CPU最多可以有256個中斷類型。按照產生中斷的方法,可以分為內
部中斷(軟體中斷)和外部(硬體中斷)中斷兩大類。
8.9 在編寫中斷處理子程序時,為什麼要在子程序中保護許多寄存器?
解: 因為在用戶程序運行時,會在寄存器中有中間結果,當在中斷服務程序中要
使用這些寄存器前要把這些寄存器的內容推至堆棧保存(稱為保護現場)。在從中斷服務程序返回至用戶程序時把這些內容從堆找恢復至寄存器中(稱為恢復現場)。
8.12 若在一個系統中有5個中斷源,其優先權排列為:1、2、3、4、5,它們的中斷服務程序的入口地址分別為:3000H、302OH、3050H、3080H、30AOH。編寫一個程序,當有中斷請求CPU響應時,能用查詢方式轉至申請中斷的優先權最高的源的中斷服
務程序。
解: 若5個中斷源的中斷請求放在一中斷狀態寄存器中,按優先權分別放在狀態的7位(優先權最高)至位3中。查詢方法的程序段為:
IN AL, STATUS
CMP AL, 80H
JNE N1
JMP 3000H
N1: IN AL, STATUS
CMP AL, 40H
JNE N2
JMP 3020H
N2: IN AL, STATUS
CMP AL, 20H
JNE N3
JMP 3050H
N3: IN AL, STATUS
CMP AL, 10H
JNE N4
JMP 3080H
N4: IN AL, STATUS
CMP AL, 08H
JNE N5
JMP 30A0H
N5: RET
第9章 作 業 答 案
9.3 在某一應用系統中,計數器/定時器8253地址為340H~343H,定時用作分頻器(N為分頻系數),定時器2用作外部事件計數器,如何編制初始化程序?
解:
定時器0用作分頻器,工作方式2,其初始化程序為:
MOV AL, 34H
OUT 343H, AL
MOV AL, N1
OUT 342H, AL
MOV AL, N2
OUT 342H, AL
定時器2用作外部事件計數器,工作在方式0,其初始程序:
MOV AL, 0B0H
OUT 343H,AL
MOV AL, N1
OUT 342H,AL
MOV AL, N2
OUT 342H,AL
9.4 若已有一頻率發生器,其頻率為1MHZ,若要示求通過計數器/定時器8253,著重產生每秒一次的信號,8253應如何連接?編寫出初始化程序。
解:
1MHZ的信號要變為每秒一次,則需經過106分頻。一個通道的計數為16 位最大為65536。故需要需兩個通道級連,則每個通道計數為1000。用通道0和通道1級連,都工作在方式2,初始化程序為:
MOV AL, 34H
OUT 343H, AL
MOV AL, 0E8H
OUT 342H, AL
MOV AL, 03
OUT 342H, AL
MOV AL, 74H
OUT 343H, AL
MOV AL, 0E8H
OUT 342H, AL
MOV AL, 03
OUT 342H, AL
9.9 編程將計數器/定時器8253計數器0設置為模式1,計數初值3000H;計數器1設置為模式2初值為2010H;計數器2設置為模式4初值為4030H;
解: 若埠地址為:0F8H~0FBH,初始化程序為:
MOV AL, 32H
OUT 0FBH, AL
MOV AL, 00H
OUT 0F8H, AL
MOV AL, 30H
OUT 0F8H, AL
MOV AL, 74H
OUT 0FBH, AL
MOV AL, 10H
OUT 0F9H, AL
MOV AL, 20H
OUT 0F9H, AL
MOV AL, 0B8H
OUT 0FBH, AL
MOV AL, 30H
OUT 0FAH, AL
MOV AL, 40H
OUT 0FAH, AL
第 10 章 作 業 答 案
10.4 可編程並行介面晶元8255A的3個埠在使用時有什麼差別?
解:通常埠A或B作為輸入輸出的數據埠(埠A還可以作為雙向數據埠),而埠C作為控制或狀態信息的埠,它在"方式"字的控制下,可以分成兩個4位的埠。每個埠包含一個4位鎖存器。它們分別與埠A和B配合使用,可用以作為控制信號輸出,或作為狀態信號輸入。
10.7 8255A有哪幾種基本工作方式?對這些工作方式有什麼規定?
解:8255A有3種基本的工作方式:
方式0-----基本輸入輸出:
方式1-----選通輸入輸出;
方式2-----雙向傳送。
10.8 設置8255A工作方式,8255A的控制口地址為OOC6H。要求埠A工作在方式1,輸
入;埠B工作在方式0,輸出;埠C的高4位配合埠A工作;低4位為輸入。
解:按要求的方式控制字為:10111001B。編程語句為:
MOV AL, 0B9H
OUT OOC6H, AL ;
10.9 設可編程並行介面晶元8255A的4個埠地址為OOCOH、00C2H、00C4H、OOC6H,要求用置0/置1方式對PC6置1,對PC4置0。
解:對埠C的PC6置1的控制字為: 00001101B,
對PC4置O的控制字為: 0000100OB。
程序段為:
MOV AL, DH
OUT OOC6H, AL
MOV AL, 08H.
OUT 00C6H, AL
B. 8051與8086、8088的區別
主要8051是8位,而8086和8088是16位,所以匯編時會在書寫方面不一樣,那就要注意演算法了,但只要掌握好8051就很快可以過度到16位機
以下是一些概括性的資料:(是復制粘貼的)
8086是intel的CPU,地球上生產CPU的不只intel還有motorola.隨著人類的進步cpu也不斷發展。8086發育得越來越豐滿了,也就是以後的/80286/80386/80486/奔騰/p2/p3/p4.
8051是單片機,是一種計算機了,實際上8051內除有CPU外,內部還包括RAM、ROM、定時器、I/O介面等,只是她比PC機小得多,用處也不一樣而已。為什麼說8051系列呢?8051是intel發明的技術,它有自己的這種技術的產品--MCS-51。MCS-51系列單既包括三個基本型80C31、8051、8751,對應的低功耗型號80C31、8051、87C51,因而MCS-51特指Intel的這幾種型號。上個世紀80年代中期以後,Intel將8051內核以專利轉讓的形式賣了出去,8051被不同的公司AMTEL、WINBOND、PHILIPS、、MOTOROLA、ANANOG DEVICES、DALLAS這些包下了,弄出了各有千秋,風姿sex appeal的C51系列。如:ZILOG的Z8系列,PHILIPS的51X系列,motorola的68HC05/08系列等
8086/8088微處理器
8086是Inter系列的16位微處理器,晶元上有2.9萬個晶體管,採用 HMOS工
藝製造,用單一的+5V電源,時鍾頻率為5MHz~10MHz。
8086有16根數據線和20根地址線,它既能處理16位數據,也能處理8位數據。可
定址的內存空間為1MB.
Inter公司在推出8086的同時,還推出了一種准16位微處理器8088,8088的內部寄存器,運算部件及內部數據匯流排都是按16位設計的,單外部數據匯流排只有8條。推出8086的主要目的是為了與當時已有的一套Inter外部設備介面晶元直接兼容使用。8086與8088在寄存器結構,編程結構,存儲器組織及I/O埠組織方面是完全一樣的或稍有差別,在本節中,對其差別之做出說明。
1.3.1 8086/8088的寄存器結構
圖1-3示出了8086/8088的寄存器結構
1. 數據寄存器
數據寄存器為圖中最上邊所示的4個寄存器AX,BX,CX,DX。這些寄存器用以暫時保存計算過程中所得到的操作數及結果。他能處理16位數,也能處理8位數,當處理8位數時,這4個16位寄存器作為8個8為寄存器AH,AL,BH,BL,CH,CL,DH,DL來使用。
這4個數據寄存器除了作為通用寄存器以外,還有各自的專門用途:
AX(accumulator)做累加器用,是算術運算的主要寄存器。AX還用在字乘和字除法中,此外,所有的I/O指令都是以AX為中心與外部設備進行信息傳送;
BX(base)在計算寄存器地址時,常用做基值寄存器;
CX(count)再串操作指令及循環中用做計數器;
DX(data)在字乘法,字除法運算中,將DX,AX組合成一個雙字長數,DX用來存放高16位數。另外,在間接的I/O指令中,DX用來指定I/O埠地址
2. 指針寄存器及變址寄存器
指針寄存器包括堆棧寄存器SP(stack pointer)和基數指針寄存器BP(base pointer),變
值寄存器包括源變址寄存器SI(source index)和目的變值寄存器DI(destination index)。這
4個寄存器都是16位寄存器,這些寄存器在運算過程中也可以用來存放操作數(只能
以字為單位),但經常的用途是在段內定址時提供偏移地址,SP,BP一般與段寄存器SS
聯用,以確定堆棧寄存器中某一單元的地址,SP用以指示棧頂的偏移地址,而BP可
作為堆棧區中的一個基地址,用以確定在堆棧中的操作數地址。SI,DI一般與段寄存器
DS聯用,以確定數據段中某一存儲單元的地址,SI,DI具有自動增量和自動減量的功能,
這一點使在串操作指令中用做變址非常方便,SI作為隱含的源變址DS聯用,DI作為
隱含的目的變址和ES連用,從而達到在數據段和附加段中定址的目的
3. 段寄存器
一共有4個段地址寄存器,他們是:
CS(code segment register)16位代碼段寄存器
DS(data segment register)16位數據段寄存器
SS(stack segment register)16位堆棧段寄存器
ES(extra segment register )16為附加段寄存器
下面將要講到,在IBM PC機中採用存儲器地址分段的辦法,使8086/8088能定址1MB的內存。而段寄存器就是用來存放段地址的,CS段寄存器用來存放當前正在運行的程序;DS段寄存器用來存放當前運行的數據,若程序中使用了段操作指令,源操作數也
存放在數據段中,SS段寄存器規定了堆棧所處的區域;ES段寄存器用來存放輔助數據
,因ES是一個附加的數據段,在執行串操作指令時,目的操作數也一般存放在ES段中。
4. 控制寄存器
IP(instruction pointer)是指令指針寄存器,是一個16位寄存器,用來存放代碼段中的偏移地址。他與CS連用才能確定下一條指令的地址,根據這一地址,控制器從指定的存儲器中,取出下一條要執行的指令,並修改IP,以便指向下一條要執行的指令。可見IP
寄存器是用來控制指令系列的執行流程的。
PSW(processor status word)是狀態標志寄存器,也是一個16位寄存器,我們將在本節後面加以介紹。
上面介紹的這些寄存器在計算機中有非常重要的作用,在運算過程中,這些寄存器起著存儲器的作用,但存取速度比存儲器快得多。
1.3.2 8086/8088的編程結構
所謂編程結構是指從使用者看到的結構,這是一種按功能劃分的結構,這種結構與CPU內部的實際物理結構當然是有區別的。
8086的編程結構見圖1-4。他分兩部分。即匯流排介面部分BIU(bus interface unit)和執行部件EU(execution unit).
匯流排介面部分負責與存儲器,外設埠傳送數據。具體講,匯流排介面部分從內存中取出指令送到指令隊列時,CPU執行指令時,所需的操作數也由匯流排介面部分從指定的內存單元或外設埠取來,傳送給執行部分去執行,反過來,執行部分的操作結果也通過
匯流排介面傳送到指定的內存單元或外設埠中去。
匯流排介面部件由下面4部分組成:4個段寄存器,指令指針寄存器IP,20位的地址加法器及6個位元組的指令隊列。
地址加法器的作用是產生20個地址。上面提到,8086/8088內部所有的寄存器都是16位的,8086/8088可用20位地址去定址1MB的內存空間,這就需要地址加法器根據16
寄存器提供的信息,計算出20位物理地址,具體演算法將在本節後面講述存儲器組織時加以介紹。
對匯流排介面部分需說明的一點是,8086的指令隊列為6個位元組,而8088的指令隊列為4個位元組。不管是8086,還是8088,都會在執行指令的同時,從內存中取出下面一條或幾條指令,取來的指令依次放在指令隊列中,按順序放,並按順序到EU中去執行。執行部分EU的功能負責指令的執行。
執行部件包括:4個數據寄存器,2個指針寄存器,2個變值寄存器,1個狀態標志寄存器和一個算術邏輯單元。
從編程結構可看出,由於匯流排介面部分和執行部分是分開的,每當EU執行一條指令時,造成指令隊列空出2個或空出一個指令位元組時 ,BIU馬上從內存中取出下面一條或幾條指令,以添滿他的指令隊列。這樣,一般情況下,CPU在執行完一條指令後,便可馬上執行下一條指令,不像以往8位CPU那樣,執行完一條指令後,需等待下一條指令
1.3.3 8086/8088的存儲器組織
1. 存儲單元的地址和內容
2. 在計算機中用以存儲信息的基本單位是一個二進制位,每8個組成一個位元組
C. msp430F149鍗曠墖鏈哄ご鏂囦歡閲屾垜鎵撲簡綰㈢偣榪欒屾湁浠涔堢敤錛燂紵錛熶笂闈㈡槸綰㈠畾涔夛紝涓嬮潰鍙堟湁涓榪欐槸鍟ユ剰鎬濓紵
灝辨槸涓轟釜鐗規畩瀵勫瓨鍣ㄥ艱祴鍊間竴涓鍦板潃錛屼篃灝辨槸璇碩AIV鐨勫湴鍧鏄0x012Eu銆傘傘傘傘
涓嶅悓鐨勫瀷鍙鳳紝鐗規畩鍔熻兘瀵勫瓨鍣ㄥ湴鍧鍙鑳戒笉鐩稿悓錛屼絾浣犲笇鏈涚敤鍚屼竴涓鍚嶅瓧錛岄偅涔堝彧瑕佸湪榪欐敼涓嬪湴鍧鍊煎氨琛屻傘傘傘
鍋囧傛湁榪欎釜瀹 TAIV=1000錛涚瓑浠蜂簬錛坲nsigned short *錛0x012eu=1000; 0x012eu鏄瀵勫瓨鍣ㄧ殑鍦板潃錛屼絾緙栫▼涓鍐欏湴鍧鎬繪槸寰堟唻灞堬紝閭d箞鏀圭敤浠栫殑瀹廡AIV,鏈夊畠鏇挎崲錛坲nsigned short *錛0x012eu涔﹀啓灝辨柟渚誇簡銆傘傘傝ョ▼搴忓氨鏄鎸囪╁畯TAIV 鐨勫肩瓑浠蜂簬錛坲short *錛0x012eu錛涘湪緙栬瘧鏃禩AIV閮戒細琚
錛坲short *錛0x012eu鏇挎崲鎺夛紝榪欐牱灝辮揪鍒版搷浣滃瘎瀛樺櫒鐨勬晥鏋溿傘傘
D. 工業順序控制——工業自動加熱反應爐的控制(單片機編程)
(一)溫度控制系統的組成 溫度是工業對象中主要的被控參數之一,象冶金、機械、食品、化工各類工業中,廣泛使用的各種加熱爐、熱處理爐、反應爐等,對工件的處理溫度要求嚴格控制,計算機溫度控制系統使溫度控制指標得到了大幅度提高。 電阻爐爐溫控制系統的控制過程是:單片機定時對爐溫進行檢測,經A/D轉換晶元得到相應的數字量,經過計算機進行數據轉換,得到應有的控制量,去控制加熱功率,從而實現對溫度的控制。 進行系統設計時應考慮如下問題: 爐溫變化規律的控制,即爐溫按預定的溫度——時間關系變化,這主要在控製程序設計中考慮。 溫度控制范圍:如400~1000℃,這就涉及到測溫元件、電爐功率的選擇等。 控制精度、超調量等指標,這涉及到A/D轉換精度、控制規律選擇等。 (二)硬體電路設計 1.溫度檢測元件及變送器、ADC的選擇 溫度檢測元件及變送器的選擇要考慮溫度控制范圍及精度要求。對於0~1000℃ 的測量范圍,採用熱電偶,如鎳鉻熱電偶,分度號為EU,其輸出信號為0~41.32mV,經毫伏變送器,輸出0~10mA,然後再經過電流——電壓變換電路轉換為0~5V電壓信號。為了提高測量精度,可將變送器進行零點遷移,例如溫度測量范圍改為400~1000℃,熱電偶給出16.4~41.32mV 時,使變送器輸出0~10mV,這樣使用8位A/D轉換器,能使量化誤差達到±2.34℃。 2.介面晶元的擴展 由於本系統既要顯示、報警、鍵盤輸入,又要進行控制,所以系統在8031系統中擴展了一片8155,它有三個8位I/O口,256位元組的RAM,可以作為外部數據存儲器供系統使用,8031的P2.1接8155的CE,P2.0接8155的IO/M,當P2.1=0,P2.0=1時,選中8155片內的三個I/O埠,其口地址如下: 0100H 〖〗命令狀態寄存器0101H〖〗A口0102H〖〗B口0103H〖〗C口或控制口寄存器0104H〖〗計數值低八位0105H〖〗計數值高八位和方式寄存器當P2.2=0時,選中ADC0809(允許啟動各通道轉換與讀取相應的轉換結果)。轉換結束信號EOC經倒相後接至單片機的外部中斷INT1 (P3.3),當P3.3=0時,說明轉換結束。我們選用0通道作為輸入,把0809視為一個地址為03F8H的外部數據存儲單元,對其寫數據時, 8031的WR信號使ALE和START有效,將74LS373鎖存的地址低三位存入0809,並啟動ADC0809,D 9EOC為低電平時,A/D轉換正在進行,當EOC為高電平時,表示轉換結束,8031可以讀如轉換好的數據。 3.溫度控制電路 溫度控制電路採用晶閘管調功方式。雙向晶閘管串在50Hz交流電源和加熱絲電路中,只要在給定周期里改變晶閘管開關的接通時間的脈沖信號即可。這可以用一條I/O線,通過程序輸出控制脈沖。 為了達到過零觸發的目的,需要交流電過零檢測電路。此電路輸出對應於50Hz交流電壓過零時刻的脈沖,作為觸發雙向晶閘管的同步脈沖,使晶閘管,在交流電壓過零時刻導通。 電壓比較器LM311 將50HZ正弦交流電壓變成方波。方波上升沿和下降沿分別作為單穩態觸發器的觸發信號,單穩觸發器輸出的窄脈沖經二極體或門混合,就得到對應於220V市電過零時刻的同步脈沖。此脈沖一路作為觸發同步脈沖加到溫控電路,一路作為計數脈沖加到單片機8031的P3.4和P3.5輸入端。 (三)控制規律的選擇和程序設計 電阻爐爐溫控制是這樣一個反饋調節過程,比較實際爐溫和需要爐溫得到偏差,通過對偏差的處理獲得控制信號,去調節電阻爐的熱功率,從而實現對爐溫的控制。 按照偏差的比例、積分和微分產生控製作用(PID控制),是過程式控制制中應用最廣泛的一種控制形式。 計算機PID是用差分方程近似實現的。 PID調節規律的微分方程(略)。 系統控製程序採用兩重中斷嵌套方式設計。首先使T0 計數器產生定時中斷,作為本系統的采樣周期。在中斷服務程序中啟動A/D,讀入采樣數據,進行數字濾波、上下限報警處理,PID計算,然後輸出控制脈沖信號。脈沖寬度由T1計數器溢出中斷決定。在等待T1中斷時,將本次采樣值轉換成對應的溫度值放入顯示緩沖區,然後調用顯示子程序。從T1中斷返回後,再從 T0中斷返回主程序並且、繼續顯示本次采樣溫度,等待下次T0中斷。
E. 求51單片機C語言編的密碼鎖程序
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define BIN(a,b,c,d,e,f,g,h) ((a<<7)+(b<<6)+(c<<5)+(d<<4)+(e<<3)+(f<<2)+(g<<1)+(h<<0))
//下面的code表示數組存放在ROM中,因為這個數組的值不需要改寫
uchar code KeyCode[16]={15,14,12,8,30,28,24,16,60,56,48,32,120,112,96,64};//值為m*(n+1)的乘積,用於Key()
uchar dis[6];
msdelay(uint x)//延時子函數
{uchar j;
while(x--)
{for(j=0;j<125;j++){;}
}
}
//鍵盤子程序一,鍵盤值與數組值對比得到
uchar Key(void)
{uchar temp,m,n,i,j,matrix,k;
P1=0xF0; /*行線電平為高,列線為低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*行仍為高,無按健,退出*/
else msdelay(10);
for(i=1;i<16;i=i*2)
{m=i;
for(j=1;j<16;j=j*2)
{n=(~j)&0x0f;
P1=(m<<4)|n; /*m為P1的行值由i循環得到,n為列值,由j循環並取反得到*/
temp=P1&0xf0;
if (!temp)
{do{temp=P1&0xf0;}while(!temp);
matrix=m*(n+1);/*為避免乘積重復,n+1*/
for(k=0;k<16;k++){if (matrix==KeyCode[k]) return(k);} //KeyCode:見前
return(16);
} //if loop
}//j loop
}//i loop
}//Key end
//用Switch...case語句得到鍵盤值*/
uchar Key1(void)
{uchar temp,m,n,i,j,matrix;
P1=0xF0; /*行線電平為高,列線為低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*行仍為高,無按健,退出*/
else msdelay(10);
for(i=1;i<16;i=i*2)
{m=i;
for(j=1;j<16;j=j*2)
{n=(~j)&0x0f;
P1=(m<<4)|n;/*m為P1的行值由i循環得到,n為列值,由j循環並取反得到*/
temp=P1&0xf0;
if (!temp)
{do{temp=P1&0xf0;}while(!temp);
matrix=m*(n+1);
switch(matrix) //此方法的基本思路:
{case 15:return(1); break; //由循環得到的m,n值賦於P1埠實現逐個鍵掃描
case 14:return(2); break; //同時由m,n+1的值相乘得到對應鍵點de的積
case 12:return(3); break; //m*(n+1)值掃描鍵點對應而得出鍵值
case 8:return(4); break; //
case 30:return(5); break; //
case 28:return(6); break; //
case 24:return(7); break; //
case 16:return(8); break;
case 60:return(9); break;
case 56:return(0); break;
case 48:return(10); break;
case 32:return(11); break;
case 120:return(12); break;
case 112:return(13); break;
case 96:return(14); break;
case 64:return(15); break;
default:return(16);
} //switch end
} //if loop
}//j loop
}//i loop
}//Key end
//依次掃描16個按鍵
uchar Key2(void)
{uchar temp;
P1=0xF0; /*使P1=1111 0000,行線電平為高,列線為低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*讀P1=1111 xxxx,表示行仍為高,無按健,退出(x表示不關心)?/
else msdelay(10);
P1=0x1e; /*P1=0001 1110,行一為高,列一為低,掃描第一個按鍵*/
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(1);}
P1=0x1d; /*P1=0001 1101,行一為高,列二為低,掃描第二個按鍵,下面掃描其餘按鍵*/
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(2);}
P1=0x1b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(3);}
P1=0x17;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(4);}
P1=0x2e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(5);}
P1=0x2d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(6);}
P1=0x2b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(7);}
P1=0x27;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(8);}
P1=0x4e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(9);}
P1=0x4d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(0);}
P1=0x4b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(10);}
P1=0x47;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(11);}
P1=0x8e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(12);}
P1=0x8d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(13);}
P1=0x8b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(14);}
P1=0x87;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(15);}
return(16); //掃描all按鍵都未按下,則輸出16
}//Key2 end.
////////時鍾中斷顯示子程序
void T0_int() interrupt 1
{static uchar i;
if (i==6){i=0;}
P0=5-i;
P0=P0|(dis[i]<<4);
i++;
TL0=0;
TH0=252;}
void distri(uint disnum)
{uint temp;
dis[0]=0;
dis[1]=disnum/10000;
temp=disnum%10000;
dis[2]=temp/1000;
temp=temp%1000;
dis[3]=temp/100;
temp=temp%100;
dis[4]=temp/10;
dis[5]=temp%10;
}
Main()
{uchar KeyVal,i=0;
TMOD=0x01;
IE=0x82;
TH0=252;
TL0=0;
TR0=1;
distri(0);
do{
KeyVal=Key();
if (KeyVal!=16) dis[1]=KeyVal; //注意:當有按鍵時才賦於顯示位dis[1],否則出錯,請分析!
}while(1);
}