树莓派的gpio有什么用_怎么用

嵌入式操作系统

57人已加入

描述

  树莓派现在越来越火,网上树莓派的资料也越来越多。树莓派源自英国,国外嵌入式开源领域具有良好的分享精神,树莓派各种集成库也层出不穷,下面推荐几个。

  【python GPIO】

  【开发语言】——python

  【简单介绍】——该库更确切的名称为raspberry-gpio-python,树莓派官方资料中推荐且容易上手。python GPIO是一个小型的python库,可以帮助用户完成raspberry相关IO口操作。但是python GPIO库还没有支持SPI、I2C或者1-wire等总线接口。除了python GPIO之外,还有众多的python扩展库(例如webiopi),毫无疑问的说python非常适合树莓派,树莓派也非常适合python。

  【wiringPi】

  【开发语言】——C语言

  【简单介绍】——wiringPi适合那些具有C语言基础,在接触树莓派之前已经接触过单片机或者嵌入式开发的人群。wiringPi的API函数和arduino非常相似,这也使得它广受欢迎。作者给出了大量的说明和示例代码,这些示例代码也包括UART设备,I2C设备和SPI设备等,毫无疑问地说wiringPi功能非常强大。

  【BCM2835 C Library】

  【开发语言】——C语言

  【简单介绍】BCM2835 C Library可以理解为使用C语言实现的相关底层驱动,它给我的感觉更像STM32的库函数,BCM2835 C Library的驱动库包括GPIO、SPI和UART等,可以通过学习BCM2835 C Library熟悉BCM2835相关的寄存器操作。如果有机会开发树莓派上的linux驱动,或自主开发python或PHP扩展驱动,可以从BCM2835 C Library找到不少的“灵感”。

  GPIO基本介绍

  GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平。GPIO是个比较重要的概念,用户可以通过GPIO口和硬件进行数据交互(如UART),控制硬件工作(如LED、蜂鸣器等),读取硬件的工作状态信号(如中断信号)等。GPIO口的使用非常广泛。掌握了GPIO,差不多相当于掌握了操作硬件的能力。

  现在,我们先看看树莓派上的GPIO是怎么样的:

  右上角的详细图:

  我们重点看第二张详细图。这张图上可以看到,每一个针脚都有Pin#和NAME字段。Pin代表的是该针脚的编号,其中01和02针脚对应第一张图中GPIO最右边竖排的两个针脚。而NAME代表的是该针脚的BCM名称,当然NAME也可以直接看得出针脚的默认功能。比如 3.3v和5v代表着该针脚会输出3.3v和5v的电压,Ground代表着该针脚是接地的,GPIO0*则是一些待用户开发的针脚。每个针脚都可以使用程序进行控制操作。

  控制GPIO

  想用python来控制GPIO,最便捷的办法就是使用一些python类库,比如树莓派系统本身集成的RPi.GPIO。本文详细介绍如何使用RPi.GPIO来控制GPIO。

  导入RPi.GPIO模块

  可以用下面的代码导入RPi.GPIO模块。

  import RPi.GPIO as GPIO

  引入之后,就可以使用GPIO模块的函数了。如果你想检查模块是否引入成功,也可以这样写:

  try:

  import RPi.GPIO as GPIO

  except RuntimeError:

  print(“引入错误”)

  针脚编号

  在RPi.GPIO中,同时支持树莓派上的两种GPIO引脚编号。第一种编号是BOARD编号,这和树莓派电路板上的物理引脚编号相对应。使用这种编号的好处是,你的硬件将是一直可以使用的,不用担心树莓派的版本问题。因此,在电路板升级后,你不需要重写连接器或代码。

  第二种编号是BCM规则,是更底层的工作方式,它和Broadcom的片上系统中信道编号相对应。在使用一个引脚时,你需要查找信道号和物理引脚编号之间的对应规则。对于不同的树莓派版本,编写的脚本文件也可能是无法通用的。

  你可以使用下列代码(强制的)指定一种编号规则:

  GPIO.setmode(GPIO.BOARD)

  # or

  GPIO.setmode(GPIO.BCM)

  下面代码将返回被设置的编号规则

  mode = GPIO.getmode()

  警告

  如果RPi.GRIO检测到一个引脚已经被设置成了非默认值,那么你将看到一个警告信息。你可以通过下列代码禁用警告:

  GPIO.setwarnings(False)

  引脚设置

  在使用一个引脚前,你需要设置这些引脚作为输入还是输出。配置一个引脚的代码如下:

  # 将引脚设置为输入模式

  GPIO.setup(channel, GPIO.IN)

  # 将引脚设置为输出模式

  GPIO.setup(channel, GPIO.OUT)

  # 为输出的引脚设置默认值

  GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)

  释放

  一般来说,程序到达最后都需要释放资源,这个好习惯可以避免偶然损坏树莓派。释放脚本中的使用的引脚:

  GPIO.cleanup()

  注意,GPIO.cleanup()只会释放掉脚本中使用的GPIO引脚,并会清除设置的引脚编号规则。

  输出

  要想点亮一个LED灯,或者驱动某个设备,都需要给电流和电压他们,这个步骤也很简单,设置引脚的输出状态就可以了,代码如下:

  GPIO.output(channel, state)

  状态可以设置为0 / GPIO.LOW / False / 1 / GPIO.HIGH / True。如果编码规则为,GPIO.BOARD,那么channel就是对应引脚的数字。

  如果想一次性设置多个引脚,可使用下面的代码:

  chan_list = [11,12]

  GPIO.output(chan_list, GPIO.LOW)

  GPIO.output(chan_list, (GPIO.HIGH, GPIO.LOW))

  你还可以使用Input()函数读取一个输出引脚的状态并将其作为输出值,例如:

  GPIO.output(12, not GPIO.input(12))

  读取

  我们也常常需要读取引脚的输入状态,获取引脚输入状态如下代码:

  GPIO.input(channel)

  低电平返回0 / GPIO.LOW / False,高电平返回1 / GPIO.HIGH / True。

  如果输入引脚处于悬空状态,引脚的值将是漂动的。换句话说,读取到的值是未知的,因为它并没有被连接到任何的信号上,直到按下一个按钮或开关。由于干扰的影响,输入的值可能会反复的变化。

  使用如下代码可以解决问题:

  GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)

  # or

  GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

  需要注意的是,上面的读取代码只是获取当前一瞬间的引脚输入信号。

  如果需要实时监控引脚的状态变化,可以有两种办法。最简单原始的方式是每隔一段时间检查输入的信号值,这种方式被称为轮询。如果你的程序读取的时机错误,则很可能会丢失输入信号。轮询是在循环中执行的,这种方式比较占用处理器资源。另一种响应GPIO输入的方式是使用中断(边缘检测),这里的边缘是指信号从高到低的变换(下降沿)或从低到高的变换(上升沿)。

  轮询方式

  while GPIO.input(channel) == GPIO.LOW:

  time.sleep(0.01) # wait 10 ms to give CPU chance to do other things

  边缘检测

  边缘是指信号状态的改变,从低到高(上升沿)或从高到低(下降沿)。通常情况下,我们更关心于输入状态的该边而不是输入信号的值。这种状态的该边被称为事件。

  先介绍两个函数:

  wait_for_edge() 函数。

  wait_for_edge()被用于阻止程序的继续执行,直到检测到一个边沿。也就是说,上文中等待按钮按下的实例可以改写为:

  channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000)

  if channel is None:

  print(‘Timeout occurred’)

  else:

  print(‘Edge detected on channel’, channel)

  add_event_detect() 函数

  该函数对一个引脚进行监听,一旦引脚输入状态发生了改变,调用event_detected()函数会返回true,如下代码:

  GPIO.add_event_detect(channel, GPIO.RISING) # add rising edge detection on a channel

  do_something()

  // 下面的代码放在一个线程循环执行。

  if GPIO.event_detected(channel):

  print(‘Button pressed’)

  上面的代码需要自己新建一个线程去循环检测event_detected()的值,还算是比较麻烦的。

  不过可采用另一种办法轻松检测状态,这种方式是直接传入一个回调函数:

  def my_callback(channel):

  print(‘This is a edge event callback function!’)

  print(‘Edge detected on channel %s’%channel)

  print(‘This is run in a different thread to your main program’)

  GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback)

  如果你想设置多个回调函数,可以这样:

  def my_callback_one(channel):

  print(‘Callback one’)

  def my_callback_two(channel):

  print(‘Callback two’)

  GPIO.add_event_detect(channel, GPIO.RISING)

  GPIO.add_event_callback(channel, my_callback_one)

  GPIO.add_event_callback(channel, my_callback_two)

  注意:回调触发时,并不会同时执行回调函数,而是根据设置的顺序调用它们。

  综合例子:点亮LED灯

  好了,上面说明了一大堆函数库的用法,那么现在就应该来个简单的实验了。这个实验很简单,点亮一个LED灯。

  编写代码之前,首先你需要将led灯的针脚通过杜邦线连接到树莓派的引脚上,比如你可以连接到11号引脚。

  新建一个main.py文件,写入如下代码:

  import RPi.GPIO as GPIO //引入函数库

  import time

  RPi.GPIO.setmode(GPIO.BOARD) //设置引脚编号规则

  RPi.GPIO.setup(11, RPi.GPIO.OUT) //将11号引脚设置成输出模式

  while True

  GPIO.output(channel, 1) //将引脚的状态设置为高电平,此时LED亮了

  time.sleep(1) //程序休眠1秒钟,让LED亮1秒

  GPIO.output(channel, 0) //将引脚状态设置为低电平,此时LED灭了

  time.sleep(1) //程序休眠1秒钟,让LED灭1秒

  GPIO.cleanup() //程序的最后别忘记清除所有资源

  保存,并退出文件。执行python3 main.py,即可观看效果。Ctrl+C可以关闭程序。

  此外,不妨也试试其它的函数吧,增强印象。

  使用PWM

  这个python函数库还支持PWM模式的输出,我们可以利用PWM来制作呼吸灯效果。详情看代码:

  import time

  import RPi.GPIO as GPIO //引入库

  GPIO.setmode(GPIO.BOARD) //设置编号方式

  GPIO.setup(12, GPIO.OUT) //设置12号引脚为输出模式

  p = GPIO.PWM(12, 50) //将12号引脚初始化为PWM实例 ,频率为50Hz

  p.start(0) //开始脉宽调制,参数范围为: (0.0 《= dc 《= 100.0)

  try:

  while 1:

  for dc in range(0, 101, 5):

  p.ChangeDutyCycle(dc) //修改占空比 参数范围为: (0.0 《= dc 《= 100.0)

  time.sleep(0.1)

  for dc in range(100, -1, -5):

  p.ChangeDutyCycle(dc)

  time.sleep(0.1)

  except KeyboardInterrupt:

  pass

  p.stop() //停止输出PWM波

  GPIO.cleanup() //

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分