文章目录

  • GPIO外设的概念
  • 什么是GPIO
  • GPIO内部结构
  • 输出部分
  • 输入部分
  • 【MicroPython】machine.Pin类函数详解
  • 实操


GPIO外设的概念

树莓派gpio怎么用python编程 树莓派4 gpio定义_初始化

外设(外部设备)

在早期UART和LCD控制器与cpu不在同一芯片上,所以被称作外部设备

树莓派gpio怎么用python编程 树莓派4 gpio定义_初始化_02

随着半导体技术的发展,各种外设被集成到一片芯片上,仍称外设

  • 芯片外部的外设称为片外外设
  • 芯片内部但在内核之外的外设称为片内外设

什么是GPIO

外设GPIO

全称:通用型输入输出端口 (General-purpose inpou/output)

树莓派gpio怎么用python编程 树莓派4 gpio定义_初始化_03

简单来说,就是MCU可以直接控制的引脚
MCU经常通过GPIO引脚与外部器件连接实现控制,读取或者通讯
因此GPIO可以说是大多数MCU的最重要的功能,也是外部连接的主要途径

我们看下下面RP2040的系统概述图

树莓派gpio怎么用python编程 树莓派4 gpio定义_树莓派gpio怎么用python编程_04

可以看到内核可以通过SIO(Software control of GPIO)
直接控制GPIO

但是SPI等外设需要通过GPIO才能实现对应的功能

点灯程序就是控制通过GPIO输出的高/低电平进行点亮或者熄灭发光二极管

树莓派gpio怎么用python编程 树莓派4 gpio定义_物联网_05

GPIO内部结构

树莓派gpio怎么用python编程 树莓派4 gpio定义_单片机_06

输出部分

  • 输出速度 决定了GPIO最快的反转速度
  • 输出使能 决定了是否输出
  • 输出数据 决定了输出电平
  • 输出能力 决定GPIO的驱动能力

输入部分

  • 输入使能 决定是否能够输入
  • 输入数据 输入GPIO的电平
  • 输入迟滞 是否使用施密特触发器

注意:
现阶段的MicroPython 无法控制输出速度,输出能力,输入迟滞

由上述结构可以将GPIO分为4类

  • 开漏输入
  • 悬空输入
  • 上拉输入
  • 下拉输入

【MicroPython】machine.Pin类函数详解

  • machine.Pin(id, mode=None, pull=None, value)
  • Pin对象构造函数:根据参数初始化GPIO并返回
  • id:GPIO编号,数值为0-29,如使用GPIO13则此处填写13,。;
  • mode:模式,可选None 不初始化、Pin.IN(0) 输入模式、Pin.OUT(1) 输出模式、Pin.OPEN_DRAIN(2) 开漏模式;
  • pull:使用内部上下拉电阻,仅在输入模式下有效,可选 None 悬空、Pin.PULL_UP(1) 上拉、Pin.PULL_DOWN(2)
    下拉;
  • value:输出或开漏模式下端口值,0为低(off)、1为高(on);

第一个参数ID,代表GPIO编号,数值应在0-29,如使用GPIO13则此处填写13。

第二个参数mode代表GPIO模式 可设置为不初始化,输入模式 输出模式 和开漏模式

第三个参数pull为使用内部上下拉电阻,可设置为上拉 下拉 和悬空 注意该参数仅在输入模式下有效

第四个参数为输出数值,输出或开漏模式下端口值有效。

  • Pin.init(mode=None, pull=None)
  • 重新初始化GPIO口;
  • mode:模式,可选None、Pin.IN(0)、Pin.OUT(1)、Pin.OPEN_DRAIN(2);
  • pull:使用内部上下拉电阻,仅在输入模式下有效,可选 None、Pin.PULL_UP(1)、Pin.PULL_DOWN(2);

其作用为重新初始化GPIO,参数与PIN构造函数相同,这里就不一一赘述了.

  • Pin.value([x])
  • 不填写参数的情况下返回GPIO端口数值
  • 在填写参数的情况下将参数写入GPIO端口中,参数可为0或者1;

PIN类中value函数作用为在不填写参数的情况下返回GPIO端口数值,在填写参数的情况下将参数写入GPIO端口中,参数可为0或者1;

  • Pin.toggle()
  • 输出或开漏模式下将端口设置翻转

PIN类中toggle函数为在输出或开漏模式下端口值进行一次翻转

  • Pin.low()
  • 输出或开漏模式下将端口设置为低;
  • Pin.off()
  • 输出或开漏模式下将端口设置为低;
  • Pin.high()
  • 输出或开漏模式下将端口设置为高;
  • Pin.on()
  • 输出或开漏模式下将端口设置为高;

以上四个函数均用于输出或开漏模式下,Low OFF 设置为低(0), high和on设置为高(1)

  • Pin.irq(handler=None,trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING))
  • 外部中断函数
  • 用于设置外部中断
  • handler:中断触发回调函数;
  • trigger:中断触发条件,设置为:
  • Pin.IRQ_FALLING 下降沿中断。
  • Pin.IRQ_RISING 在上升沿中断

PIN类irq函数为外部中断函数, 第一个参数为中断触发回调函数; 第二个参数trigger为中断触发条件,设置为边缘触发或者电平触发。

实操

准备扩展工具;

  • pico 1
  • 面包板 1
  • 直插按键 1
  • 直插LED 1
  • 适当阻值的直插电阻 1
  • 杜邦线若干

树莓派gpio怎么用python编程 树莓派4 gpio定义_物联网_07

将按键连接到GPIO15上面
将外部LED连接到GPIO16上面,通过1K电阻进行限流

码代码:

导入machine库中的Pin类

import machine
from machine import Pin

前者会将整个machine库导入
后者将单独导入machine库中的Pin类
相比前者,后者占用的内存更小

from machine import Pin
import utime

# 输入模式
# 初始化GPIO15,输入模式,使用内部上拉的Pin对象并赋予给了button
button_num = 15
button = Pin(button_num, Pin.IN, Pin.PULL_UP)


# 输出模式
  # 初始化GPIO16,输出模式
external_led_num = 16;
external_led = Pin(external_led_num, Pin.OUT)

  # 初始化GPIO25,输出模式
led_num = 25
led = Pin(led_num, Pin.OUT)

print("button gpio={0}".format(button_num))
   


while True:
   #led灯关闭
   # 按键释放完后将GPIO25(led)设置为低电平
   # 然后等待按间再次按下
   lef.off()   
   # 读取按钮的值
   # 读取GPIO15的数值并判断是否为0,0表示按钮被按下
   # 等待10ms后重新判断按钮是否被按下
   # 若还是按下就开始执行下一步 
   if(button.value() == 0):
   # 进行了一个软件消抖,即检测出按键闭合后执行一个10ms的延时,要前沿抖动消失后再一次检测按键状态
   # 若仍保持闭合状态下的电平,则认为有键按下,才转入按键处理程序
        utime.sleep(0.01) 
        if(button.value() == 0):
            # 按键按下时,GPIO16反转
            external_led.toggle()
            # 打开ledGPIO25设为高电平
            led.on()
            print("button is pressed.")
            # 通过while循环等待按键释放,等待按键释放完后将会回到代码的顶端
            while(button.value() == 0):
               utime.sleep(0.01)

为什么要等待10ms后重新判断按键是否被按下?

树莓派gpio怎么用python编程 树莓派4 gpio定义_物联网_08

在实际情况中,机械触点断开或者闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会一下就稳定的连接
在一起,也不会在断开时一下就断开
因此在闭合或断开的瞬间会产生一系列的抖动

如何避免?

  • 按键消抖

硬件消抖

软件消抖

优点

较少的软件开销

硬件的成本较低

缺点

硬件成本较高

较多的软件开销

树莓派gpio怎么用python编程 树莓派4 gpio定义_物联网_09

微雪PICO教程