树莓派驱动GPIO--LED+键盘
单片机最近本的功能就是通用输入输出功能(GPIO),树莓派b+板上引出了40个引脚,包括27个GPIO供使用。在烧入的镜像中已经集成python以及在python中封装的操作GPIO的类:RPi.GPIO
。有了这个包,我们就可以拿树莓派来驱动一些外设了,首先是驱动一盏LED灯。
##LED灯
原理很简单,如图所示,树莓派引脚打出高电平时LED被点亮。每个引脚最大输出电流为16毫安(mA)[1],电阻最小为3.3/0.016=206.25欧姆,我用了4.7K的,实际电路如下:
控制引脚输出高电平的代码如下:
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
led = 26
GPIO.setup(led, GPIO.OUT)
print("输出高电平")
GPIO.output(led, GPIO.HIGH)
time.sleep(5)
GPIO.output(led, GPIO.LOW)
print("输出低电平")
GPIO.cleanup()
首先调用GPIO.setmode
函数来确定引脚的模式,在RPi.GPIO包中定义GPIO针脚的两种模式:BCM模式和BOARD模式,分别对应语句GPIO.setmode(GPIO.BCM)
和GPIO.setmode(GPIO.BOARD)
。我们再看下树莓派的引脚图:
以左边一排的11号引脚为例,11号引脚的编号为11,对于GPIO17,当在BCM模式下时,11号引脚对应于实际编号为11的引脚,也就是GPIO17;当在BOARD模式下时,11号引脚对应GPIO11,也就是23号引脚。
设置完引脚模式之后,使用GPIO.setup
设置引脚输入还是输出,在设置为输入时还可以有第三个参数指定上拉还是下拉,也就是给引脚一个确定的状态(上拉时为高电平,下拉时为低电平,防止悬空电平不确定)。GPIO.input
返回指定引脚的状态,GPIO.output
设置引脚的输出状态,使用完毕之后使用GPIO.cleanup
恢复所有使用过的通道状态为输入,可以避免由于短路意外损坏树莓派。这个操作仅会清理程序使用过的引脚。
##键盘
驱动完LED之后再外接一个键盘,键盘使用的是4*4的薄膜键盘,键盘的原理很简单,4行4列总共8根线,原理和是实物如图:
键盘和树莓派的接线如图所示,所用引脚在程序中都有说明。
扫描按键的原理和单片机中使用键盘类似,首先将4根列线设为输出低电平,将4跟行线设为输入并且上拉,当有键被按下时,对应行线电平被拉低,但是此时只是确定了按下的键位于哪一行,此时再反过来,将列线设置为输入上拉,将已经确定的行线对应行输出低电平,扫描4跟列线就可以确定按键属于哪一列了。程序如下,使用
python keyboard.py
运行程序,程序会显示你按下的键:
import RPi.GPIO as GPIO
import time
class keypad():
# CONSTANTS
KEYPAD = [
[1,2,3,"A"],
[4,5,6,"B"],
[7,8,9,"C"],
["*",0,"#","D"]
]
ROW = [27,23,24,25]
COLUMN = [4,17,22,5]
def __init__(self):
GPIO.setmode(GPIO.BCM)
def getKey(self):
# Set all columns as output low
for j in range(len(self.COLUMN)):
GPIO.setup(self.COLUMN[j], GPIO.OUT)
GPIO.output(self.COLUMN[j], GPIO.LOW)
# Set all rows as input
for i in range(len(self.ROW)):
GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
# Scan rows for pushed key/button
# A valid key press should set "rowVal" between 0 and 3.
rowVal = -1
for i in range(len(self.ROW)):
tmpRead = GPIO.input(self.ROW[i])
if tmpRead == 0:
rowVal = i
# if rowVal is not 0 thru 3 then no button was pressed and we can exit
if rowVal < 0 or rowVal > 3:
self.exit()
return
# Convert columns to input
for j in range(len(self.COLUMN)):
GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
# Switch the i-th row found from scan to output
GPIO.setup(self.ROW[rowVal], GPIO.OUT)
GPIO.output(self.ROW[rowVal], GPIO.HIGH)
# Scan columns for still-pushed key/button
# A valid key press should set "colVal" between 0 and 2.
colVal = -1
for j in range(len(self.COLUMN)):
tmpRead = GPIO.input(self.COLUMN[j])
if tmpRead == 1:
colVal=j
# if colVal is not 0 thru 2 then no button was pressed and we can exit
if colVal < 0 or colVal > 3:
self.exit()
return
# Return the value of the key pressed
self.exit()
return self.KEYPAD[rowVal][colVal]
def exit(self):
# Reinitialize all rows and columns as input at exit
for i in range(len(self.ROW)):
GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
for j in range(len(self.COLUMN)):
GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_UP)
if __name__ == '__main__':
# Initialize the keypad class
kp = keypad()
# Loop while waiting for a keypress
while True:
digit = None
while digit == None:
digit = kp.getKey()
# Print the result
print digit
time.sleep(0.5)
这段代码是从一个树莓派项目中抠出来的,感兴趣可以看下。
完成了最简单的GPIO功能,如果有什么好的idea也就可以实施了,你可以使用树莓派开关灯,控制继电器等等,你要你想到,它就可以帮你完成。
参考文献
[1] http://hugozhu.myalert.info/2013/05/14/35-understanding-output.html