数字输入与输出
数字输入与输出是最常用的一种外设通信方式,虽然每一个端口只有0和1两种状态,但却可以组合出各种各样的变化。
数字输入与输出原理
数字输入与输出,也称为通用输入输出,全称是General-purpose input/output,大部分情况下,我们都会用简称GPIO
GPIO的功能,主要是指这个管脚可以作为数字信号的输入或者输出使用,到底是输入还是输出呢,这需要我们使用系统寄存器来进行配置。
当GPIO被设置为输入模式时,就可以读取这个管脚上的电平高低,从而实现读取外部信号的功能,比如外部按键的信号,就是这样读取的。
当GPIO被设置为输出模式时,我们就可以主动改变管脚的电平高低了,这样就能通过电平的变化,控制外部的设备,比如点亮或者熄灭一个LED灯。
除此之外,一些IO口还可以配置成其他功能,比如PWM输出,串口通信等等。
关于旭日X3派的管脚定义,大家可以参考这张图,他会显示每个管脚具体可以实现什么功能。
这里需要说明一点,旭日X3派的管脚序号定义有三种编码方式:
第一种就是Board编码,这种就是按照主板上管脚排针编号,分别对应1~40号排针。
第二种就是BCM编码,这种方式是参考 Broadcom SOC 的通道编号,侧重CPU寄存器,在使用BCM库或者使用python编程时,常采用的一种编码方式。
第三种就是X3编码,可以理解为是旭日X3派自己的编码方式,在使用旭日派自己的驱动库编程时,会使用到这种编码。
大家在后续编程开发中,需要结合函数接口的说明,使用对应的引脚编号,不然可能会出现意料之外的问题。
引脚复用配置工具
虽然从硬件上看,扩展出来的引脚只有40个,不过大部分引脚还可以配置成多种功能,这样延伸出来变化可就多了,那如何配置引脚的不同功能呢?
我们可以使用旭日X3派中提供的srpi-config工具进行配置。
直接在终端中输入这个指令,就可以看到这样的窗口,okay配置对应管脚为专用功能,disabled配置对应管脚为GPIO模式,按照自己的需要进行配置即可,配置完成后重启才会生效。
了解了GPIO的概念,接下来我们就要开始编程啦。
数字输入编程
首先我们来看下最基本的数字输入测试,读取一个按键的状态。
硬件接线
我们将按键的一边连接到旭日X3派的38号引脚上,这是一个GPIO的接口,另一边连接到39号引脚,也就是GND。
原理很简单,按键没按下时,导线是断开的,GPIO是默认的状态,按键按下后,导线就会导通,GPIO的状态变成了GND。
这样,我们就可以通过电平的变化,知道按键的状态啦。
运行例程
我们不妨来运行一下,看下实际效果是不是这样。
我们将一个按键开关接到对应的管脚上, 然后连接到旭日X3PI当中,运行刚才的程序。之后我们按下或是松开按键时,他都会打印出对应的电平变化。
按下显示的就是LOW,也就是低电平,松开就是HIGH,也就是高电平。
代码解析
数字输入的功能实现啦,我们来看下代码是如何实现的。
simple_input.py:
#!/usr/bin/env python3
import Hobot.GPIO as GPIO
import time
# 定义使用的GPIO通道为38
input_pin = 38 # BOARD 编码 38
def main():
prev_value = None
# 设置管脚编码模式为硬件编号 BOARD
GPIO.setmode(GPIO.BOARD)
# 设置为输入模式
GPIO.setup(input_pin, GPIO.IN)
print("Starting demo now! Press CTRL+C to exit")
try:
while True:
# 读取管脚电平
value = GPIO.input(input_pin)
if value != prev_value:
if value == GPIO.HIGH:
value_str = "HIGH"
else:
value_str = "LOW"
print("Value read from pin {} : {}".format(input_pin, value_str))
prev_value = value
time.sleep(1)
finally:
GPIO.cleanup()
if __name__=='__main__':
main()
我们在Python中需要引入X3Pi的GPIO库,从而使用对应的GPIO功能。
-
主函数里首先需要定义了一个变量来存储这个管脚的电平信号。
-
进行初始化,设置管脚的编码模式为BOARD模式,之后定义输入用的管脚,这里使用的是BOARD编码,因为他是第38个管脚,所以为38号。
-
之后的话就会进入到循环当中,这样的一个函数就可以读出当前的电平值。
-
没有按下按键的时候,38管脚和GND是断开的,他就是高电平,按下按键时,就和GND导通了,这个管脚就会编程低电平。
- 如果电平值和上一次存储的不一致,后面的判断就会判断出是升高还是降低,最后会把结果打印出来。
- 松开按键时同理。
数字输出编程
GPIO不止有输入功能,还有输出功能,大家应该经常看到电子设别上的LED灯吧,这就是典型的IO输出控制的设备,我们也来试一试。
硬件接线
我们将一个LED灯的正极连接到了2号引脚,这是5V电源,用来给LED供电的,不过LED电阻小,为了不至于烧坏,我们最好还是在电路中串联一个电阻来限制电流大小。
接下来,当LED的负极接到GND,也就是电源的0V上时,LED两边会因为有电势差而被点亮;当LED的负极也连接到高电平,也就是5V的时候,会因为两边没有电势差,也就不会被点亮。
这个负极的电平信号我们就用GPIO来输出,所以我们把LED的负极连接到任意的GPIO引脚上,比如38号,将这个引脚设置为输出模式,当输出高电平时,灯就会熄灭,输出低电平,灯就会被点亮。
把这两个动作放到一个循环中,就可以实现闪烁的功能啦。
运行示例程序
快来运行例程试一试吧,按照刚才的设置,将实物连接完成,然后连接到X3Pi,运行程序,就可以看到这个LED就会开始闪烁了。
代码解析
simple_out.py:
#!/usr/bin/env python3
import Hobot.GPIO as GPIO
import time
# 定义使用的GPIO通道为38
output_pin = 38 # BOARD 编码 38
def main():
# 设置管脚编码模式为硬件编号 BOARD
GPIO.setmode(GPIO.BOARD)
# 设置为输出模式,并且初始化为高电平
GPIO.setup(output_pin, GPIO.OUT, initial=GPIO.HIGH)
# 记录当前管脚状态
curr_value = GPIO.HIGH
print("Starting demo now! Press CTRL+C to exit")
try:
# 间隔1秒时间,循环控制LED灯亮灭
while True:
time.sleep(1)
GPIO.output(output_pin, curr_value)
curr_value ^= GPIO.HIGH
finally:
GPIO.cleanup()
if __name__=='__main__':
main()
数字输入与输出集成
学习了GPIO的输入与输出功能后,我们就可以做一些自动化的功能了。
硬件接线
比如我们同时连接一个按键和LED灯,尝试实现按键被按下,灯被点亮,松开,灯熄灭,这样的功能。
运行示例程序
我们通过这个例程来试一试效果如何?
我们来看一下具体的操作,同样的,按照刚才的设置,将实物连接完成,然后连接到X3Pi,运行刚才的程序。按下按键后,就可以看到LED被点亮了,松开之后,LED就熄灭了。
代码解析
button_led.py
#!/usr/bin/env python3
import Hobot.GPIO as GPIO
import time
# 定义使用的GPIO通道:
# 36号作为输出,可以点亮一个LED
# 38号作为输入,可以接一个按钮
led_pin = 36 # BOARD 编码 36
but_pin = 38 # BOARD 编码 38
# 禁用警告信息
GPIO.setwarnings(False)
def main():
prev_value = None
# Pin Setup:
GPIO.setmode(GPIO.BOARD) # BOARD pin-numbering scheme
GPIO.setup(led_pin, GPIO.OUT) # LED pin set as output
GPIO.setup(but_pin, GPIO.IN) # Button pin set as input
# Initial state for LEDs:
GPIO.output(led_pin, GPIO.LOW)
print("Starting demo now! Press CTRL+C to exit")
try:
while True:
curr_value = GPIO.input(but_pin)
if curr_value != prev_value:
GPIO.output(led_pin, curr_value)
prev_value = curr_value
print("Outputting {} to Pin {}".format(curr_value, led_pin))
time.sleep(1)
finally:
GPIO.cleanup() # cleanup all GPIO
if __name__ == '__main__':
main()
基本的配置还是一样的,引入基本的库,然后设置为BOARD模式,然后初始化两个管脚,一个用来读取按键的通断,一个用来控制LED的亮灭,之后只需要判断按键的状态来做出对应的控制LED的动作就可以了。