【K230 CanMV】machine.FPIOA、Pin 与 GPIO 全解析
引言:在嵌入式开发领域,GPIO(通用输入输出)引脚的功能配置和复用能力对设备的灵活性和功能实现起到了至关重要的作用。FPIOA(Field Programmable IO Array,现场可编程 IO 数组)是现代嵌入式芯片的一项重要特性,通过它可以实现 IO 引脚功能的灵活复用和分配,从而极大提升芯片资源的利用效率。本文基于【K230 CanMV】开发平台,详细解析了 FPIOA 和 machine.Pin 的相关功能,并通过 GPIO 实例演示如何在实际项目中使用这些功能。
目录
一、FPIOA介绍
二、FPIOA 的工作原理
三、FPIOA 类相关函数介绍
1.各引脚可复用功能
2.构造函数
3.设置引脚功能
4.引脚功能读取获取
5.帮助方法
四、machine.Pin相关函数介绍
1.构造函数
2.初始化引脚
3.控制PIN
3.1.value
3.2.mode
3.3.pull
3.4.drive
3.5.on
3.6.off
3.7.high
3.8.low
五、GPIO使能综合案例
一、FPIOA介绍
FPIOA(灵活外设输入/输出阵列)是 K230 CanMV 系列微处理器提供的功能,允许用户灵活配置引脚来连接不同的外设。通过这个模块,我们可以轻松管理各种硬件接口。FPIOA 可以允许用户根据需要,将特定的引脚分配给不同的功能(比如 SPI、I2C、UART 等),每个引脚在同一时刻只能激活一种功能。使用 FPIOA,可以简化引脚管理,提升芯片的灵活性。
FPIOA 类位于
machine
模块中,可以像使用其他 Python 模块一样进行操作。如from machine import FPIOA
。
二、FPIOA 的工作原理
引脚功能映射:每个物理引脚可以映射为不同的外设功能。例如,可以将某个引脚配置为 SPI 时钟线,也可以将它配置为 I2C 的 SDA 或 SCL。
单一功能激活:每个引脚在同一时刻只能激活一种功能,但可以根据需求随时调整。通过灵活的配置,可以在不同的硬件平台上复用相同的引脚,不必担心硬件布局或接线问题。
引脚管理简化:FPIOA 极大简化了硬件设计中的引脚管理工作,尤其是在需要多种外设接口的场合。开发者不需要物理地更换硬件连接,只需通过配置寄存器即可重新分配引脚功能。
三、FPIOA 类相关函数介绍
1.各引脚可复用功能
from machine import FPIOA
# 实例化FPIOA
fpioa = FPIOA()
# 打印所有引脚配置
fpioa.help()
2.构造函数
fpioa = FPIOA()
初始化一个 FPIOA 模块的实例,以便通过该实例操作 K230 或其他支持 FPIOA 功能的芯片的引脚映射。
3.设置引脚功能
fpioa.set_function(pin, func, ie=-1, oe=-1, pu=-1, pd=-1, st=-1, sl=-1, ds=-1)
引脚编号 (
pin
)
- 范围:[0, 63]
功能代码 (
func
)
- 普通 GPIO
FPIOA.GPIO0
~FPIOA.GPIO63
:配置为普通 GPIO 功能- 串口功能
FPIOA.UART0_TXD
:配置为 UART0 的发送功能 (TX)FPIOA.UART0_RXD
:配置为 UART0 的接收功能 (RX)FPIOA.UART1_TXD
:配置为 UART1 的发送功能 (TX)FPIOA.UART1_RXD
:配置为 UART1 的接收功能 (RX)FPIOA.UART2_TXD
:配置为 UART2 的发送功能 (TX)FPIOA.UART2_RXD
:配置为 UART2 的接收功能 (RX)- I²C 功能
FPIOA.IIC0_SCL
:配置为 I²C0 的时钟线 (SCL)FPIOA.IIC0_SDA
:配置为 I²C0 的数据线 (SDA)FPIOA.IIC1_SCL
:配置为 I²C1 的时钟线 (SCL)FPIOA.IIC1_SDA
:配置为 I²C1 的数据线 (SDA)- PWM 功能
FPIOA.PWM0
:配置为 PWM 通道 0FPIOA.PWM1
:配置为 PWM 通道 1FPIOA.PWM2
:配置为 PWM 通道 2FPIOA.PWM3
:配置为 PWM 通道 3FPIOA.PWM4
:配置为 PWM 通道 4FPIOA.PWM5
:配置为 PWM 通道 5以下是针对
ie
、oe
、pu
、pd
、st
、sl
、ds
的功能和可选参数:
ie
(输入使能)
- 可选参数:
-1
:默认值,保持当前状态0
:不使能输入1
:使能输入
oe
(输出使能)
- 可选参数:
-1
:默认值,保持当前状态0
:不使能输出1
:使能输出
pu
(上拉使能)
- 可选参数:
-1
:默认值,保持当前状态0
:不使能上拉1
:使能上拉
pd
(下拉使能)
- 可选参数:
-1
:默认值,保持当前状态0
:不使能下拉1
:使能下拉
st
(施密特触发器控制使能)
- 可选参数:
-1
:默认值,保持当前状态0
:不使能施密特触发器1
:使能施密特触发器,提高抗干扰能力和信号完整性
sl
(特殊功能控制)
- 可选参数:
-1
:默认值,建议直接设置为-1
0
:不使能(已废弃)1
:使能(已废弃,建议不使用)
ds
(驱动电流能力)
- 可选参数:
-1
:默认值,保持当前状态0
~15
:设置驱动电流能力,值越大驱动能力越强,推荐最大值为15
(Boot引脚例外)
4.引脚功能读取获取
获取引脚当前的功能号。
fpioa.get_pin_func(pin)
获取指定功能当前所在的引脚。
fpioa.get_pin_num(func)
如下一个简单的案例,可以看出来具体引脚功能是什么。
5.帮助方法
fpioa.help([number, func=False])
- 所有引脚的配置信息(未设置
number
) - 指定引脚的详细配置信息(设置了
number
,未设置func
或设置为False
) - 指定功能的所有可配置引脚号(设置了
number
,并将func
设置为True
)
简单案例如下所示,
四、machine.Pin相关函数介绍
machine.Pin
是用于控制和操作微控制器引脚的核心模块,支持 GPIO 输入/输出的基本功能。
from machine import Pin # 使用前导包
1.构造函数
用于构造pin对象,可同时对引脚进行初始化。
pin = Pin(index, mode, pull=Pin.PULL_NONE, drive=7)
index
: 引脚编号,范围为 [0, 63]。mode
: 引脚模式,支持以下配置:Pin.OUT
: 输出模式。Pin.IN
: 输入模式。
pull
: 上下拉配置(可选),默认为Pin.PULL_NONE
:Pin.PULL_NONE
: 无上下拉。Pin.PULL_UP
: 上拉。Pin.PULL_DOWN
: 下拉。
drive
: 驱动能力配置(可选),默认值为 7:- 范围: 0-15,数值越大引脚的驱动能力越强。
- 说明: 除了
boot 0
和boot 1
,其他引脚可以设置最大值 15。
# 实例化Pin2为输出
pin = Pin(2, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
2.初始化引脚
用于初始化引脚的模式、上下拉配置及驱动能力。
pin.init(mode, pull=Pin.PULL_NONE, drive=7)
-
mode
: 引脚的模式(输入或输出)。Pin.OUT
: 输出模式。Pin.IN
: 输入模式。
-
pull
: 上下拉配置(可选),默认值为Pin.PULL_NONE
。Pin.PULL_NONE
: 无上下拉。Pin.PULL_UP
: 上拉。Pin.PULL_DOWN
: 下拉。
-
drive
: 驱动能力(可选),默认值为 7。- 范围: 0-15,数值越大引脚的驱动能力越强。
- 说明: 除了
boot 0
和boot 1
,其他引脚可以设置最大值 15。
# 初始化pin为输入
pin.init(Pin.IN, pull=Pin.PULL_UP, drive=7)
3.控制PIN
3.1.value
获取引脚的输入电平值或设置引脚的输出电平。
pin.value([value])
value
: 输出值(可选),如果传递该参数则设置引脚输出为指定值。如果不传参则返回引脚的当前输入电平值。- 0:输出低电平。
- 1:输出高电平。
返回值
返回空或当前引脚的输入电平值。
- 0:当前引脚输入为低电平
- 1:当前引脚输入为高电平
# 设置输出为高
pin.value(1)
# 设置输出为低
pin.value(0)
# 获取引脚输入电平
print(pin.value())
3.2.mode
主要用来获取或设置引脚的模式。
pin.mode([mode])
mode
: 引脚模式(输入或输出),如果不传参则返回当前引脚的模式。Pin.OUT
Pin.IN
返回值
返回空或当前引脚模式。
# 设置引脚为输入模式
pin.mode(Pin.IN)
# 设置引脚为输出模式
pin.mode(Pin.OUT)
3.3.pull
获取或设置引脚的上下拉配置。
pin.pull([pull])
pull
: 上下拉配置(可选),如果不传参则返回当前上下拉配置。
返回值
返回空或当前引脚的上下拉配置。
3.4.drive
获取或设置引脚的驱动能力。
pin.drive([drive])
参数
drive
: 驱动能力(可选),如果不传参则返回当前驱动能力。
返回值
返回空或当前引脚的驱动能力。
3.5.on
将引脚输出设置为高电平。
pin.on()
3.6.off
将引脚输出设置为低电平。
pin.off()
3.7.high
将引脚输出设置为高电平。
pin.high()
3.8.low
将引脚输出设置为低电平。
pin.low()
五、GPIO使能综合案例
非常非常的简单,学会MCU的看一眼就懂了,这边就不再过多赘述。
from machine import Pin
from machine import FPIOA
import time
# 创建FPIOA对象,用于初始化引脚功能配置
fpioa = FPIOA()
# 设置引脚功能,将指定的引脚配置为普通GPIO功能,
fpioa.set_function(62,FPIOA.GPIO62)
fpioa.set_function(20,FPIOA.GPIO20)
fpioa.set_function(63,FPIOA.GPIO63)
# 实例化Pin62, Pin20, Pin63为输出,分别用于控制红、绿、蓝三个LED灯
LED_R = Pin(62, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 红灯
LED_G = Pin(20, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 绿灯
LED_B = Pin(63, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 蓝灯
# 板载RGB灯是共阳结构,设置引脚为高电平时关闭灯,低电平时点亮灯
# 初始化时先关闭所有LED灯
LED_R.high() # 关闭红灯
LED_G.high() # 关闭绿灯
LED_B.high() # 关闭蓝灯
# 基础点灯试验:选择一个LED灯并让其闪烁
# 默认选择红色LED灯,后续可以通过变量改变需要控制的灯
LED = LED_R # 当前控制的LED为红色LED
while True:
LED.low() # 点亮当前选择的LED
time.sleep(0.5) # 等待0.5秒
LED.high() # 熄灭当前选择的LED
time.sleep(0.5) # 等待0.5秒from machine import Pin
7色灯,本质就是RGB三色不同的组合嘛,掌握上面了下面自然也会了。
from machine import Pin
from machine import FPIOA
import time
# 创建FPIOA对象,用于初始化引脚功能配置
fpioa = FPIOA()
# 设置引脚功能,将指定的引脚配置为普通GPIO功能,
fpioa.set_function(62,FPIOA.GPIO62)
fpioa.set_function(20,FPIOA.GPIO20)
fpioa.set_function(63,FPIOA.GPIO63)
# 实例化Pin62, Pin20, Pin63为输出,分别控制红、绿、蓝灯
LED_R = Pin(62, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
LED_G = Pin(20, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
LED_B = Pin(63, Pin.OUT, pull=Pin.PULL_NONE, drive=7)
def set_color(r, g, b):
"""设置RGB灯的颜色,使用Pin.high()和Pin.low()控制"""
if r == 0:
LED_R.low() # 红灯亮
else:
LED_R.high() # 红灯灭
if g == 0:
LED_G.low() # 绿灯亮
else:
LED_G.high() # 绿灯灭
if b == 0:
LED_B.low() # 蓝灯亮
else:
LED_B.high() # 蓝灯灭
def blink_color(r, g, b, delay):
"""设置颜色并让灯亮一段时间后熄灭"""
set_color(r, g, b) # 设置颜色
time.sleep(delay) # 保持该颜色一段时间
set_color(1, 1, 1) # 熄灭所有灯(共阳:1为熄灭)
time.sleep(delay) # 熄灭后等待一段时间
while True:
# 红色
blink_color(0, 1, 1, 0.5)
# 绿色
blink_color(1, 0, 1, 0.5)
# 蓝色
blink_color(1, 1, 0, 0.5)
# 黄色(红+绿)
blink_color(0, 0, 1, 0.5)
# 紫色(红+蓝)
blink_color(0, 1, 0, 0.5)
# 青色(绿+蓝)
blink_color(1, 0, 0, 0.5)
# 白色(红+绿+蓝)
blink_color(0, 0, 0, 0.5)
按键控灯,也是非常简单如下所示:
from machine import Pin
from machine import FPIOA
import time
# 创建FPIOA对象,用于初始化引脚功能配置
fpioa = FPIOA()
# 设置引脚功能,将指定的引脚配置为普通GPIO功能,
fpioa.set_function(62,FPIOA.GPIO62)
fpioa.set_function(20,FPIOA.GPIO20)
fpioa.set_function(63,FPIOA.GPIO63)
fpioa.set_function(53,FPIOA.GPIO53)
# 实例化Pin62, Pin20, Pin63为输出,分别用于控制红、绿、蓝三个LED灯
LED_R = Pin(62, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 红灯
LED_G = Pin(20, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 绿灯
LED_B = Pin(63, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 蓝灯
# 按键引脚为53,按下时为高电平,所以这里设置为下拉并设置为输入模式
button = Pin(53, Pin.IN, Pin.PULL_DOWN) # 使用下拉电阻
# 板载RGB灯是共阳结构,设置引脚为高电平时关闭灯,低电平时点亮灯
# 初始化时先关闭所有LED灯
LED_R.high() # 关闭红灯
LED_G.high() # 关闭绿灯
LED_B.high() # 关闭蓝灯
# 基础控制RGB灯亮灭试验:选择一个LED灯并让其闪烁
# 默认选择红色LED灯,后续可以通过变量改变需要控制的灯
LED = LED_R # 当前控制的LED为红色LED
while True:
if button.value() == 1:
LED.high()
else:
LED.low()
按键消抖,如下所示:
from machine import Pin
from machine import FPIOA
import time
# 创建FPIOA对象,用于初始化引脚功能配置
fpioa = FPIOA()
# 设置引脚功能,将指定的引脚配置为普通GPIO功能,
fpioa.set_function(62,FPIOA.GPIO62)
fpioa.set_function(20,FPIOA.GPIO20)
fpioa.set_function(63,FPIOA.GPIO63)
fpioa.set_function(53,FPIOA.GPIO53)
# 实例化Pin62, Pin20, Pin63为输出,分别控制红、绿、蓝三个LED灯
LED_R = Pin(62, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 红灯
LED_G = Pin(20, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 绿灯
LED_B = Pin(63, Pin.OUT, pull=Pin.PULL_NONE, drive=7) # 蓝灯
# 按键引脚为53,按下时高电平,设置为输入模式
button = Pin(53, Pin.IN, Pin.PULL_DOWN) # 使用下拉电阻
# 初始选择控制红灯
LED = LED_R # 默认控制红灯
# 初始化时关闭所有LED灯(共阳:高电平时为灭灯)
LED_R.high()
LED_G.high()
LED_B.high()
# 消抖时间设置为20毫秒
debounce_delay = 20 # 毫秒
last_press_time = 0 # 上次按键按下的时间,单位为毫秒
# 记录LED当前状态,True表示亮,False表示灭
led_on = False
# 记录按键状态,用于检测按下和松开的状态变化
button_last_state = 0 # 上次按键状态
# 主循环
while True:
button_state = button.value() # 获取当前按键状态
current_time = time.ticks_ms() # 获取当前时间(单位:毫秒)
# 检测按键从未按下(0)到按下(1)的变化(上升沿)
if button_state == 1 and button_last_state == 0:
# 检查按键是否在消抖时间外
if current_time - last_press_time > debounce_delay:
# 切换LED的状态
if led_on:
LED.high() # 熄灭LED
else:
LED.low() # 点亮LED
led_on = not led_on # 反转LED状态
last_press_time = current_time # 更新按键按下时间
# 更新上次按键状态
button_last_state = button_state