使用RPi的GPIO,通常狀況P1就夠了,經常使用的SPI、I2C、UART都在這。使用時參考下面兩個圖(都是從elinux.org搬運過來的,詳細的描述能夠在這裏找到)。
RPi的GPIO只支持3.3V電壓,若是接5V的IO,要注意電平轉換。python
P1在板子上的位置:
linux
P1每一個Pin的功能:
git
經過UART登陸RPi。github
首先參考上面的兩個圖鏈接PC和RPi,無非是TxD接RxD,RxD接TxD,注意共地。
我用的是一個TTL-USB的轉換模塊,因此鏈接後,PC系統中會多一個tty設備/dev/ttyUSB0
。根據和PC的不一樣鏈接方式,設備節點可能會是不一樣的名字。
segmentfault
而後打開minicom鏈接RPi。建議將串口配置命名保存起來,便於下次直接使用,若是有多個串口配置,也能快速切換。數組
如下是操做過程:
佈局
若是不知道默認用戶名、密碼,能夠根據使用的系統類型,在官方下載頁面查找:
ui
點燈。spa
用P1-11,P1-12,P1-13分別控制三個LED。電路很簡單,一目瞭然。BTW,原理圖,我是用Circuit Lab在線畫的,小巧方便。code
而後是代碼,借鑑了elinux.org的示例。
#!/usr/bin/env python import time import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) GPIO.setup(11, GPIO.OUT) GPIO.setup(12, GPIO.OUT) GPIO.setup(13, GPIO.OUT) GPIO.output(11, GPIO.HIGH) GPIO.output(12, GPIO.HIGH) GPIO.output(13, GPIO.HIGH) pin = 0; while True: GPIO.output(11 + pin, GPIO.LOW) time.sleep(1) GPIO.output(11 + pin, GPIO.HIGH) pin = (pin + 1) % 3
/* blink.c * 2014/6/6 */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #define BCM2708_PERI_BASE 0x20000000 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) volatile unsigned *gpio; // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) #define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) #define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0 void map_registers() { void *gpio_map; int mem_fd; if((mem_fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0){ printf("can't open /dev/mem\n"); exit(-1); } gpio_map = mmap( NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, GPIO_BASE ); close(mem_fd); if(gpio_map == MAP_FAILED){ printf("mmap error %d\n", (int)gpio_map); exit(-1); } gpio = (volatile unsigned *)gpio_map; } int main(int argc, const char *argv[]) { int cnt = 0; int pin_map[3] = {17, 18 , 27}; map_registers(); INP_GPIO(pin_map[0]); OUT_GPIO(pin_map[0]); INP_GPIO(pin_map[1]); OUT_GPIO(pin_map[1]); INP_GPIO(pin_map[2]); OUT_GPIO(pin_map[2]); GPIO_SET = (1 << pin_map[0]) | (1 << pin_map[1]) | (1 << pin_map[2]); while(1) { GPIO_CLR = 1 << pin_map[cnt]; sleep(1); GPIO_SET = 1 << pin_map[cnt]; cnt = (cnt + 1) % 3; } return 0; }
Python版代碼簡潔不少,由於用了RPi.GPIO這個包,而C版沒有依賴任何庫。
Python版代碼,直接scp過去就可執行。C代碼須要編譯。下載編譯器,而後arm-linux-gnueabihf-gcc blink.c -o blink
。一樣scp到RPi執行。
兩個版本執行都須要root權限。
這裏有一個小小的坑。
GPIO的pin有兩種命名方式,以SoC爲中心,和以RPi爲中心。
Python版代碼中GPIO.setmode(GPIO.BOARD)
就是設置使用RPi爲中心的命名方式,這樣接下來GPIO.output(11, GPIO.HIGH)
中的pin編號,與本文最開始的圖示是一一對應的。這種方式比較直觀。
固然也可使用另外一種,GPIO.setmode(GPIO.BCM)
便可。這樣的話,pin編號與它們在RPi上的佈局有一個映射關係。詳細的能夠參考這個表格。
C版代碼中用的是SoC的命名,爲了方便操做,纔有了這個數組int pin_map[3] = {17, 18 , 27};
。可見GPIO17等同於P1-11,GPIO18等同於P1-12,GPIO27等同於P1-13。
另外C版代碼中直接操做了GPIO的寄存器。寄存器映射參考Data Sheet。