樹莓派的GPIO程式設計
作者:Vamei 出處:http://www.cnblogs.com/vamei 嚴禁轉載。
樹莓派除了提供常見的網口和USB介面 ,還提供了一組GPIO(General Purpose Input/Output)介面。這組GPIO介面大大拓展了樹莓派的能力。GPIO不僅能實現通訊,還能直接控制電子元器件,從而讓使用者體驗到硬體程式設計的樂趣。
GPIO簡介
在樹莓派3上,GPIO介面由40個針腳(PIN)組成。每個針腳都可以用導線和外部裝置相連。你可以通過焊接的方式來把導線固定在PIN上,也可以用母型的跳線套接在PIN上。
跳線
40個PIN中,有固定輸出的5V(2、4號PIN)、3.3V(1、17號PIN)和地線(Ground,6、9、14、20、25、30、34、39)。如果一個電路兩端接在,5V和地線之間,該電路就會獲得5V的電壓輸入。27和28號PIN標著ID_SD和ID_SC。它們是兩個特殊的PIN。它們屬於ID EEPROM (Electrically Erasable Programmable Read-Only Memory) 介面,用於和拓展樹莓派功能的附加電路板通訊。其他的PIN大多程式設計GPIOX的編號,如GPIO14。樹莓派的作業系統中,會用GPIO的編號14來指代這個PIN,而不是位置編號的8。有一些PIN除了GPIO功能外,還提供了高階埠功能。比如說,GPIO14和GPIO15就同時可以充當UART埠。此外,GPIO上還能找到I2C和SPI埠。
樹莓派3的GPIO針腳
在計算機中,通常用高、低兩個電壓來表示二進位制的1和0。樹莓派也是如此。GPIO用相同的方式來表示資料。每個GPIO的PIN都能處於輸入或輸出狀態。當處於輸出狀態時,系統可以把1或0傳給該PIN。如果是1,那麼對應的物理PIN向外輸出3.3V的高電壓,否則輸出0V的低電壓。相應的,處於輸入狀態的PIN可以探測物理PIN上的電壓。如果是高電壓,那麼該PIN將向系統返回1,否則返回0。就是利用上述簡單機制,GPIO實現了和物理電路的互動。
控制LED燈
我們先來看GPIO輸出的一個例子。我們在GPIO21和地線之間接了一個串聯電路。電路上有一個LED燈,還有一個用於防止短路的330歐電阻。當GPIO21位於高電平時,將有電流通過電路,從而點亮LED燈。
我們用bash命令來控制GPIO21。在Linux中,外部裝置經常被表示成檔案。向檔案寫入或讀取字元,就相當於向裝置輸出或者從裝置輸入字元。樹莓派上的GPIO埠也是如此,其代表檔案位於/sys/class/gpio/下。首先,啟用GPIO21:
echo 21 > /sys/class/gpio/export
這個命令的意思,是把字元"21"輸入到/sys/class/gpio/export。可以看到,命令執行後,/sys/class/gpio/下面增加了代表GPIO21的一個目錄,目錄名就是gpio21。下一步,我們把GPIO21置於輸出狀態:
echo out > /sys/class/gpio/gpio21/direction
檔案/sys/class/gpio/gpio21/direction用於控制GPIO21的方向。我們向裡面寫入了代表輸出的字元"out"。最後,向GPIO21寫入1,從而讓PIN處於高電壓:
echo 1 > /sys/class/gpio/gpio21/value
可以看到,LED燈亮了起來。如果想關掉LED燈,只需要向GPIO21寫入0:
echo 0 > /sys/class/gpio/gpio21/value
使用完畢GPIO21,可以刪除該埠:
echo 21 > /sys/class/gpio/unexport
/sys/class/gpio/gpio21隨即消失。
兩個樹莓派之間的GPIO
我們可以用GPIO的方式連線兩個樹莓派。一個樹莓派的GPIO輸出,將成為另一個樹莓派的GPIO輸入。連線方式很簡單,只需要2根導線。一個導線連線兩個樹莓派的地線,另一根導線連線樹莓派的兩個PIN:
我們用左側的樹莓派來輸出,右側樹莓派來輸入。輸出過程和上面控制LED燈的例子相似。在第一個樹莓派中的GPIO21準備輸出:
echo 21 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio21/direction
在第二個樹莓派中,準備好讀取GPIO26:
echo 26 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio26/direction
當我們往/sys/class/gpio/gpio26中寫入"in"時,就把GPIO26置於輸入狀態。
此後,在第一個樹莓派中,就可以更改輸出值為1或0:
echo 1 > /sys/class/gpio/gpio21/value
echo 0 > /sys/class/gpio/gpio21/value
在第二個樹莓派中,可以用cat命令來讀取檔案,獲得輸入值:
cat /sys/class/gpio/gpio26/value
由於cat命令讀完一次後會返回。為了持續讀取,我們可以用bash中的無限迴圈,來反覆呼叫cat:
while true; do cat /sys/class/gpio/gpio26/value; done
隨著第一個樹莓派中輸出的改變,第二個樹莓派獲得的輸入也隨之改變。我們在兩個樹莓派之間實現了簡單的通訊。
最後,在使用完GPIO後,別忘了刪除埠。
UART程式設計
計算機的資料都是許多位的0和1構成的序列。儘管GPIO可以在0和1之間切換,但並不能準確地分割出位。比如說,我們把一個二進位制序列11000111輸出到GPIO埠,那麼在輸入端看來,只是輸入了一段時間的1,然後變成0,然後又變成1。輸入端沒法準確說出,一段高電平輸入究竟包好了幾位1。
一個解決方案是用多個PIN同時通訊,每個PIN表示一位。當輸入端讀取完成後,通知輸出端,讓輸出端送來下面一批的資料。這種通訊方式被稱為並口傳輸。和並口對應的是串列埠傳輸。傳輸時依然是用一個PIN,但輸入方可以知道一位的資料持續了多長時間。GPIO上的UART、I2C、SPI都是串列埠通訊。
UART與其餘兩者的區別在於,通訊雙方通過事先約定的速率來發送或接受資料。這種通訊方式稱為非同步通訊。在I2C和SPI這樣的同步通訊方式,會用額外的連線來保證雙方速率相同。UART的連線和實現方式很簡單,成為最流行的串列埠通訊方式。但UART的缺點在於,如果傳送方和接收方的速率不同,那麼通訊就會發生錯誤。通訊速率就稱為“波特率”(baudrate),單位是每秒通訊的位數(bps)。
UART的埠至少有RX、TX和地線三個針腳。RX負責讀取,TX負責輸出。如果有兩個UART埠,它們的連線方式如下:
在樹莓派3的情況下,TX和RX就是GPIO14和GPIO15針腳。因此,我們可以把兩個樹莓派之間按照上圖的方式連線起來,然後在兩個樹莓派之間實現UART通訊。
在這裡,我們要注意樹莓派3發生的一點變化。樹莓派1和2中都使用了標準的UART,在作業系統中的對應檔案是/dev/ttyAMA0。在樹莓派3中,新增的藍芽模組佔用了標準UART埠和樹莓派溝通,外部的UART通訊採用了簡單的Mini UART,在作業系統中的對應檔案是/dev/ttyS0。由於mini UART的波特率依賴於CPU時鐘頻率,而CPU頻率可能在執行過程中浮動,因此mini UART經常會帶來意向不到的錯誤。一般有兩種解決方案有。一種是關閉藍芽模組,讓外部連線重新使用標準UART埠。另一種是固定CPU時鐘頻率,以便mini UART能以準確的波特率進行通訊。
關閉藍芽模組,需要修改/boot/config.txt,在檔案末尾增加:
dtoverlay=pi3-disable-bt
修改後重啟。此後的UART通訊,就可以通過/dev/ttyAMA0進行。
如果是採取第二種解決方案,還是要修改/boot/config.txt,上面的修改變成:
core_freq=250
dtoverlay=pi3-miniuart-bt
修改後重啟。此後的UART通訊,就可以通過/dev/ttyS0進行。
我們以第一種解決方案為例,進行UART通訊。設定波特率:
stty -F /dev/ttyAMA0 9600
輸出文字:
echo "hello" > /dev/ttyAMA0
讀取文字:
cat /dev/ttyAMA0
如果使用第二種解決方案,那麼只需要把上面的/dev/ttyAMA0改為/dev/ttyS0。
可以看到,UART可以實現更加複雜的文字通訊。
用UART連線PC
一般的PC都沒有暴露在外的UART針腳。為了通過UART來連線PC和樹莓派,我們需要一個USB和UART的轉換器。這個轉換器的一端是USB介面,另一端是UART的針腳。我們把USB一端插入到PC。另一端按照UART到UART的方式,連線到樹莓派的UART針腳。
連線好之後,就可以在PC上,利用串列埠操作軟體來和樹莓派通訊。在Linux下,USB連線表示為/dev/ttyUSB0。當然,當計算機上只有1個USB裝置時,最後的編號才會是0。而在我的Mac OSX上,該USB連線被表示成/dev/cu.SLAB_USBtoUART。此後,就可以通過操作USB檔案來進行UART通訊。在Windows下,也有現成的進行串列埠通訊的圖形化軟體。
用UART登陸樹莓派
我們還可以用UART的方式連線並登陸樹莓派。進入樹莓派設定:
sudo raspi-config
在Interfacing Options->Serial中,允許開機時通過串列埠登陸。
重啟後,樹莓派啟動時會自動把開機資訊已115200的波特率推到UART埠。在UART另一端的PC上,如果你使用Mac OSX,那麼你可以用下面命令連線:
screen /dev/cu.SLAB_USBtoUART 115200
如果PC是Linux系統,只需要把USB裝置檔案改為對應的裝置檔案即可。如果是Windows系統,還可以用圖形化軟體。這裡不再贅述。