上兩(liang) 次我們(men) 做過兩(liang) 個(ge) 實驗,都是讓P1.0這個(ge) 管腳使燈亮,我們(men) 能設想:既然P1.0能讓燈亮,那麽(me) 其它的管腳可不能呢?看一下圖1,它是8031單片機管腳的說明,在P1.0旁邊有P1.1,P1.2….P1.7,它們(men) 是否都能讓燈亮呢?除了以P1開頭的外,還有以P0,P2,P3開頭的,數一下,一共是32個(ge) 管腳,前麵我們(men) 以學過7個(ge) 管腳,加上這32個(ge) 這39個(ge) 了。它們(men) 都以P字開頭,隻是後麵的數字不一樣,它們(men) 是否有什麽(me) 聯係呢?它們(men) 能不能都讓燈亮呢?在我們(men) 的實驗板上,除了P10之外,還有P11 -> P17都與(yu) LED相連,下麵讓我們(men) 來做一個(ge) 實驗,程序如下:
MAIN: MOV P1,#0FFH
LCALL DELAY
MOV P1,#00H
LCALL DELAY
LJMP MAIN
DELAY:MOV R7,#250
D1: MOV R6,#250
D2: DJNZ R6,D2
DJNZ R7,D1
RET
END
將這段程序燒寫(xie) 到單片機中,結果如何?通電以後我們(men) 能看到8隻LED全部在閃動。因此,P10->P17是全部能點亮燈的。事實上,凡以P開頭的這32個(ge) 管腳都是能點亮燈的,也就是說:這32個(ge) 管腳都能作為(wei) 輸出使用,如果不用來點亮LED,能用來控製繼電器,能用來控製其它的執行機構。
程序分析:這段程序和前麵做過的程序比較,隻有兩(liang) 處不一樣:第一句:原來是SETB P1.0,現在改為(wei) MOV P1,#0FFH,第三句:原來是CLR P1.0,現在改為(wei) MOV P1.0,#00H。從(cong) 中能看出,P1是P1.0->P1.7的全體(ti) 的代表,一個(ge) P1就表示了所有的這八個(ge) 管腳了。當然用的指令也不一樣了,是用MOV指令。為(wei) 什麽(me) 用這條指令?看圖2,我們(men) 把P1作為(wei) 一個(ge) 整體(ti) ,就把它當作是一個(ge) 存儲(chu) 器的單元,對一個(ge) 單元送進一個(ge) 數能用MOV指令。
二、第四個(ge) 實驗
除了能作為(wei) 輸出外,這32個(ge) 管腳還能做什麽(me) 呢?下麵再來做一個(ge) 單片機實驗,源程序如下:
MAIN: MOV P3,#0FFH
LOOP: MOV A,P3
MOV P1,A
LJMP LOOP
先看一下這個(ge) 實驗的結果:所有燈全部不亮,然後我按下一個(ge) 按鈕,第(1)個(ge) 燈亮了,再按下另一個(ge) 按鈕,第(2)個(ge) 燈亮了,鬆開按鈕燈就滅了。從(cong) 這個(ge) 實驗現象結合電路來分析一下程序。
從(cong) 硬件電路的連線能看出,有四個(ge) 按鈕被接入到P3口的P32,P33,P34,P35。第一條指令的用途我們(men) 能猜到:使P3口全部為(wei) 高電平。第二條指令是MOV A,P3,其中 MOV已經知道,是送數的意思,這條指令的意思就是將P3口的數送到A中去,我們(men) 能把A當成是一個(ge) 中間單元(看圖3),第三句話是將A中的數又送到P1口去,第四句話是循環,就是持續地重複這個(ge) 過程,這我們(men) 已見過。當我們(men) 按下第一個(ge) 按鈕時,第(3)隻燈亮了,所以P12口應當輸出是低電平,為(wei) 什麽(me) P12口會(hui) 輸出低電平呢?我們(men) 看一下有什麽(me) 被送到了P1口,隻有從(cong) P3口進來的數送到A,又被送到了P1口,所以,肯定是P3口進來的數使得P12位輸出電平的。P3口的P32位的按鈕被按下,使得P32位的電平為(wei) 低,通過程序,又使P12口輸出低電平,所以P3口起來了一個(ge) 輸入的作用。驗證:按第二、三、四個(ge) 按鈕,同時按下2個(ge) 、3個(ge) 、4個(ge) 按鈕都能得到同樣的結論,所以P3口確實起到了輸入作用,這樣,我們(men) 能看到,以P字開頭的管腳,不僅(jin) 能用作輸出,還能用作輸入,其它的管腳是否能呢?是的,都能。這32個(ge) 管腳就稱之為(wei) 並行口,下麵我們(men) 就對並行口的結構作一個(ge) 分析,看一下它是怎樣實現輸入和輸出的。
並行口結構分析:
1、輸出結構
<並行口結構圖>
先看P1口的一位的結構示意圖(隻畫出了輸出部份):從(cong) 圖中能看出,開關(guan) 的打開和合上代表了管腳輸出的高和低,如果開關(guan) 合上了,則管腳輸出就是低,如果開關(guan) 打開了,則輸出高電平,這個(ge) 開關(guan) 是由一根線來控製的,這根數據總線是出自於(yu) CPU,讓我們(men) 回想一下,數據總線是一根大家公用的線,很多的器件和它連在一起,在不一樣的時候,不一樣的器件當然需要不一樣的信號,如某一時刻我們(men) 讓這個(ge) 管腳輸出高電平,並要求保持若幹時間,在這段時間裏,計算機當然在忙個(ge) 不停,在與(yu) 其它器件進行聯絡,這根控製線上的電平未必能保持原來的值不變,輸出就會(hui) 發生變化了。怎麽(me) 解決(jue) 這個(ge) 問題呢?我們(men) 在存儲(chu) 器一節中學過,存儲(chu) 器中是能存放電荷的,我們(men) 不妨也加一個(ge) 小的存儲(chu) 器的單元,並在它的前麵加一個(ge) 開關(guan) ,要讓這一位輸出時,就把開關(guan) 打開,信號就進入存儲(chu) 器的單元,然後馬上關(guan) 閉開關(guan) ,這樣這一位的狀態就被保存下來,直到下一次命令讓它把開關(guan) 再打開為(wei) 止。這樣就能使這一位的狀態與(yu) 別的器件無關(guan) 了,這麽(me) 一個(ge) 小單元,我們(men) 給它一個(ge) 很形象的名字,稱之為(wei) “鎖存器”。
2、輸入結構
這是並行口的一位的輸出結構示意圖,再看,除了輸出之外,還有兩(liang) 根線,一根從(cong) 外部管腳接入,另一根從(cong) 鎖存器的輸出接出,分別標明讀管腳和讀鎖存器。這兩(liang) 根線是用於(yu) 從(cong) 外部接收信號的,為(wei) 什麽(me) 要兩(liang) 根呢?原來,在51單片機中輸入有兩(liang) 種方式,分別稱為(wei) ‘讀管腳’和‘讀鎖存器’,第一種方式是將管腳作為(wei) 輸入,那是真正地從(cong) 外部管腳讀進輸入的值,第二種方式是該管腳處於(yu) 輸出狀態時,有時需要改變這一位的狀態,則並不需要真正地讀管腳狀態,而隻是讀入鎖存器的狀態,然後作某種變換後再輸出。
請注意輸入結構圖,如果將這一根引線作為(wei) 輸入口使用,我們(men) 並不能保證在任何時刻都能得到正確的結果(為(wei) 什麽(me) ?)參考圖2輸入示意圖。接在外部的開關(guan) 如果打開,則應當是輸入1,而如果閉合開關(guan) ,則輸入0,但是,如果單片機內(nei) 部的開關(guan) 是閉合的,那麽(me) 不管外部的開關(guan) 是開還是閉,單片機接受到的數據都是0。可見,要讓這一端口作為(wei) 輸入使用,要先做一個(ge) ‘準備工作’,就是先讓內(nei) 部的開關(guan) 斷開,也就是讓端口輸出‘1’才行。正因為(wei) 要先做這麽(me) 一個(ge) 準備工作,所以我們(men) 稱之為(wei) “準雙向I/O口”。
以上是P1口的一位的結構,P1口其它各位的結構與(yu) 之相同,而其它三個(ge) 口:P0、P2、P3則除入作為(wei) 輸入輸出口之外還有其它用途,所以結構要稍複雜一些,但其用於(yu) 輸入、輸出的結構是相同的。看圖()。對我們(men) 來說,這些附加的功能不必由我們(men) 來控製,所以我們(men) 就不去關(guan) 心它了。