请稍侯

树莓派驱动GPIO--LED+键盘

05 November 2014

  单片机最近本的功能就是通用输入输出功能(GPIO),树莓派b+板上引出了40个引脚,包括27个GPIO供使用。在烧入的镜像中已经集成python以及在python中封装的操作GPIO的类:RPi.GPIO。有了这个包,我们就可以拿树莓派来驱动一些外设了,首先是驱动一盏LED灯。

LED灯

LED原理图   原理很简单,如图所示,树莓派引脚打出高电平时LED被点亮。每个引脚最大输出电流为16毫安(mA)[1],电阻最小为3.3/0.016=206.25欧姆,我用了4.7K的,实际电路如下:
LED电路   控制引脚输出高电平的代码如下:

# -*- 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