跳转至

Pin

概要

熟练的掌握和使用芯片的IO资源是玩转硬件的前提。前面我们曾多次提到了如何使用MicroPython来点亮一个LED灯,本节教程我们就以该例子,进行详细的剖析,为大家讲解machine 模块中的Pin类以及数字信号的相关概念。

开始之前

信号是运载消息的工具,是消息的载体。从广义上讲,它包含光信号、声信号和电信号等,我们今天主角是电信号。电信号是指随着时间而变化的电压或电流,因此在数学描述上可将它表示为时间的函数,并可画出其波形。由于非电的物理量可以通过各种传感器较容易地转换成电信号,而电信号又容易传送和控制,所以使其成为应用最广的信号。

如果你刚开始接触嵌入式或者硬件控制,我想可能你需要先明确电信号的基本概念。

在电子线路中,我们将电信号进行如下的划分:

  • 模拟信号

  • 数字信号

analog_vs_digitial

模拟信号

简而言之,模拟信号是指信息参数在给定范围内表现为连续的信号。

还记得发电机的工作原理吗?发电机的转子转动一圈产生的感应电压正好是一个周期的三角函数波,就像上图中左边的那个波形一样。广播的声音信号,或图像信号等生活中许多常见的信号,都是模拟信号。

数字信号

数字信号是指幅度的取值是离散的,幅值表示被限制在有限个数值之内。二进制码就是一种数字信号。在这种二进制体系中,我们用 0 表示 低电平, 1表示 高电平。很可能你会问,高低电平指什么?

高低电平

你可以简单的理解为较高的电压为高电平,较低的电压自然就是低电平。当然,肯定有一套判定高低电平的准则:

一般规定低电平为0~ 0.25V,高电平为3.5~5V。

当然对于有些不同的芯片或者电路模组,对高电平或低电平的定义可能会有所差异。

上升沿 下降沿

当低电平突然跃升为高电平时,电信号的变化时间极快,几乎呈直角,从低电平直线攀升至高电平,这个电平跳变的过程我们称之为上升沿

当高电平突然下降为低电平时,电信号的变化时间极快,几乎呈直角,从高电平直线跌入低电平,这个电平跳变的过程我们称之为下降沿

同时从上面这张图你也可以看出,在数字信号中,我们的电压变化理论上只有 低电平0 或 高电平1,因此我们的数字信号能够更好的被计算机所理解,并进行快速的运算。

数模转换

我们上文说,数字信号更好被计算机理解,计算,但是现实世界中大部分信号,图像,声音等等都是连续信号,所以如果需要计算机来处理这些信号,就需要将这些模拟信号转换为数字信号。所以人们发明了各种各样的传感器来采集各种模拟量的数据,转化为我们需要的数字信号。

那么,计算机计算好了的信号,比如处理之后的声音信号,如何变为连续的信号输出,被扬声器播放呢?这就需要我们借助将模拟信号转换为数字信号的模块将数字信号转化为模拟信号输出了。

回顾

先回顾以下我们之前所教大家的点亮LED灯的代码。

>>> from machine import Pin
>>> led = Pin(2, Pin.OUT) #NodeMCU-32S默认的2号GPIO与板载的LED相连
>>> led.value(1) 

在第一行代码中,我们从machine模块中导入了Pin这个类。

你一定很好奇,Pin这个类里到底有什么,第二三行代码有什么含义。还记得TAB这个技能吗?

我们使用TAB 按键来查看Pin中所包含的内容:

>>> Pin.
__class__       __name__        IN              IRQ_FALLING
IRQ_RISING      OPEN_DRAIN      OUT             PULL_DOWN
PULL_UP         WAKE_HIGH       WAKE_LOW        init
irq             value

为了满足你的好奇心,接下来我们在API文档中分别介绍以上的内容。如果以下的内容刚开始对你来说很难以理解,没有关系,你只需建立起初步的概念,结合我们上文开始之前讲述的基本概念,通过以下的API文档理解点亮LED的代码即可,之后的内容会频繁的使用到Pin模块,到时再回过头来仔细翻看API吧。

API详解

宏定义

下面的宏定义用于配置pin,也就是将对应编号的真实的管脚配置成输入或者输出或者其他模式。

宏定义 含义
Pin.IN 信号输入
Pin.OUT 信号输出
Pin.PULL_DOWN 是否接入下拉电阻
Pin.PULL_UP 是否接入上拉电阻
Pin.IRQ_RISING 信号上升沿触发中断
Pin.IRQ_FALLING 信号下降沿触发中断
Pin.WAKE_HIGH 从高电平唤醒
Pin.WAKE_LOW 从低电平唤醒
Pin.OPEN_DRAIN 开漏

注意:不是每个端口都有下面的全部属性。例如某些引脚只能输入不能输出

我们注意到其中的Pin.OUT为信号输出,而Pin(2, Pin.OUT),就是将GPIO2 设置为输出模式,

通过改变该GPIO的value为逻辑1,于是便在该引脚上输出了高电平(3v以上的电压),该led灯便被点亮。

对于上表中的数字信号,可能很多没有学过数字电路和模拟电路的同学,需要进行以下的科普。

class machine.Pin(id[, mode[, pull[, value]]])

id:任意引脚号
mode:引脚模式

  • Pin.IN — 输入

  • Pin.OUT — 输出

  • Pin.OPEN_DRAIN — 开漏

pull:是否接入拉电阻

  • None — 无上拉、下拉电阻

  • Pin.PULL_UP — 上拉

  • Pin.PULL_DOWN — 下拉

value:引脚电平状态

  • 0 —低电平

  • 1 —高电平

定义Pin

示例:

>>> from machine import Pin
>>> 
>>> led = Pin(2, mode=Pin.OUT, pull=None, value=0)  #可以简单使用Pin(2, Pin.OUT)
>>> print(led)
Pin(2)

函数

Pin.init([mode[, pull]])

函数说明:初始化引脚。

mode

  • Pin.IN — 输入

  • Pin.OUT — 输出

  • Pin.OPEN_DRAIN — 开漏

pull

  • None — 无上拉、下拉电阻

  • Pin.PULL_UP — 上拉

  • Pin.PULL_DOWN — 下拉

示例:

>>> from machine import Pin
>>> pin = Pin(2)
>>> pin.init(mode=Pin.OUT)  #也可以写作pin.init(Pin.OUT)

Pin.value([value])

函数说明:获取或设置引脚电平状态,根据引脚的逻辑电平返回0或1。
注意:不带参数时是读取输入电平,带参数时是设置输出电平。

value:可以是True/False,也可以是1/0

示例:

>>> pin = Pin(2,Pin.OUT)
>>> pin.value()
0
>>> pin.Value(True)
>>> pin.value()
1
>>> pin.Value(0)
>>> pin.value()
0

Pin.irq(trigger, handler)

函数说明:配置一个引脚的中断处理程序,在引脚的电平满足条件时调用。

trigger

  • Pin.IRQ_FALLING — 下降沿触发

  • Pin.IRQ_RISING — 上升沿触发

handler:中断被触发之后的回调函数

示例:

>>> touch = Pin(32, Pin.IN)
>>> touch.irq(trigger=Pin.IRQ_FALLING, handler=lambda t:print("IRQ triggered by your finger"))

触摸传感器

ESP32上的部分引脚自带触摸式的传感器,我们可以直接通过触摸来改变这些引脚的电平输入,在之前的引脚的讲解中,之后我们会详细为大家介绍

然后你便可以在REPL中看到: