树莓派是大家喜闻乐见的arm嵌入式计算机,它既可以当作普通的个人计算机用也可以作为服务器,最重要的一点是它具有丰富的独特接口——除传统的USB、以太网、HDMI外的GPIO接口。可当作一套嵌入式设备的控制器,比如SPI和I2C读取传感器、GPIO控制LED和蜂鸣器、UATR与其他设备通讯,同时兼具强大的运算能力、图形显示能力和网络通讯能力,这是普通MCU不能相比的。所以,linux该咋用这玩意就咋用。
下文用我的树莓派3B+做演示。
GPIO是什么
GPIO(General Purpose I/O Ports)意思是通用输入/输出端口,说白了就是一些引脚(上图左上角的两排针),它们可以输出高低电平与电路交互,实现程序控制电路的能力
当然这些引脚也不是全都能被控制,而是有相关的定义方式
由图可看出,40个引脚中除了12个电源脚外,只有28个可用引脚,其中3、5、14、15、19、21、23、24、26、27、28脚不仅能做普通的GPIO,还有特殊的用途
定义引脚的方式有三种,BOARD编码、BCM编码、Wiring编码
也可以通过在终端输入pinout
或gpio readall
查看引脚
面向GPIO编程
本文使用python3.7+VScode SSH作为测试环境
python的树莓派GPIO库有三套,功能和实现各有不同,先用最简单的RPi.GPIO
库
RPi.GPIO
:如同Arduino一般控制方便,底层基于C实现gpiozero
:面向对象的GPIO编程pigpio
:基于TCP连接pigpio服务,可以远程控制
嵌入式的Hello World——点亮一个LED
首先用杜邦线将LED的正极连接到io引脚上(这里我用的是3脚),负极连接到GND上
python代码部分需要导入RPi.GPIO
库,可参考官方文档
from RPi import GPIO
LED = 3
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED, GPIO.OUT)
GPIO.output(LED, True)
效果是这样的,就证明程序已经调试通过
GPIO.setmode()
用来设置GPIO的编码方式,它的参数可以是GPIO.BOARD
也可以是GPIO.BCM
GPIO.setup()
用来配置GPIO的模式,比如输入或者输出,上拉或下拉GPIO.output()
直接用bool值指定了GPIO的输出状态,False低电平、True高电平
但在运行时会产生一条Warring信息,这是因为重复指定了GPIO模式导致,所以需要在GPIO.setmode()
之前加一行GPIO.setwarnings(False)
用来关闭这个警告
让它闪起来!
改变GPIO的输出状态对于程序部分就是调用一个函数这么简单,所以就能通过修改传入参数实现修改电路状态的功能
这里用了一个延时和循环,使得3端口每200ms改变一下输出状态
from RPi import GPIO
import time
LED = 3
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED, GPIO.OUT)
while True:
GPIO.output(LED, True)
time.sleep(0.2)
GPIO.output(LED, False)
time.sleep(0.2)
效果就像这样
除了闪动之外,也可以使用PWM(脉宽调制)进行无极调光
使用GPIO.PWM()
创建一个PWM控制对象,其中第一个参数是要控制的GPIO,第二个参数是PWM的频率
然后使用PWM.start()
启动PWM输出,用PWM.ChangeDutyCycle()
改变占空比,用PWM.ChangeFrequency()
改变输出频率,最后再用PWM.stop()
关闭PWM输出
下面这个程序里用了两个小循环将PWM输出的占空比从0%-100%以10ms的频率递增和递减,形成了一种呼吸灯的效果
这里要注意一点:每个PWM对象是一个独立的线程,如果整个Python脚本(进程)退出了,同时也会停止所有的线程,那么所有的PWM输出也会停止
from RPi import GPIO
import time
LED = 3
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED, GPIO.OUT)
pwm = GPIO.PWM(LED, 100)
pwm.start(0)
while True:
for rate in range(0, 100):
pwm.ChangeDutyCycle(rate)
time.sleep(0.01)
for rate in range(100, 0, -1):
pwm.ChangeDutyCycle(rate)
time.sleep(0.01)
办完事记得打扫场地
不论是写什么程序,在所需的功能执行完后,都需要去释放资源,这样才是一种好的编程习惯。比如C语言释放堆内存的free()
如果不去理睬就会占用过多的系统资源
同样,在使用完GPIO的API后,也记得要在末尾添加一行GPIO.cleanup()
,使GPIO恢复到系统默认状态,释放相应的硬件资源同时也防止损坏其他设备
下期预告:输入和事件