前言

本笔记围绕 K210 芯片通用输入输出(GPIO)及高速通用输入输出(GPIOHS)功能展开,结合 RGB LED(共阳极)与 KEY 按键(共阴极)的硬件连接场景,系统梳理 IO 口输出、输入及外部中断的实现逻辑与代码实操,旨在清晰、规范地呈现 K210 芯片外设控制的核心原理与实操方法,适用于嵌入式开发入门学习与正式场景参考。

一、硬件基础与核心概念

一、核心单元:Core System(主控芯片)

Core System 是电路的核心控制单元,其引脚(如框选的 IO_12~IO_14)作为信号交互接口,承担 “指令输出” 与 “信号输入” 的功能,是连接外设的硬件基础。

二、接口层:Core System 的 IO 引脚(框选区域)

框选的 IO_12、IO_13、IO_14、IO_16 为 Core System 的通用输入输出引脚(GPIO),是主控芯片与外部设备的物理连接通道

  • 可向外部设备输出控制信号;

  • 可接收外部设备的输入信号。

三、外设模块与主控的连接关系

  • RGB LED 模块RGB LED 是输出类外设,其控制引脚(对应图中 LED_G、LED_R、LED_B)直接连接至 Core System 的 IO_12~IO_14引脚,由 Core System 通过 IO 引脚输出的电平信号控制其发光状态(颜色、亮灭)

对应芯片内部 IO 编号 连接的LED颜色
IO_12 绿色LED_G
IO_13 红色LED_R
IO_14

蓝色LED_B

  • 根据电路图我们知道RGB LED 模块是共阳极,KEY模块是共阴极
对比项 共阳极 共阴极 
公共引脚接哪里 接电源正极(高电平) 接电源负极 / 接地(低电平)
怎么点亮某颜色 对应控制引脚接低电平(比如接主控 IO 输出 0) 对应控制引脚接高电平(比如接主控 IO 输出 1)
举个例子(RGB 灯) 公共脚接 + 3.3V,IO_0 输出 0 → 红灯亮 公共脚接地,IO_0 输出 1 → 红灯亮
主控 IO 逻辑 想亮就 “拉低” 引脚电平 想亮就 “拉高” 引脚电平

  • KEY 按键模块KEY 是输入类外设,其信号引脚(对应图中 boot)连接至 Core System 的 IO_16 引脚,按键动作会通过该 IO 引脚向 Core System 传输电平变化信号,实现 “操作指令输入”。

四、K210 GPIO 与 GPIOHS 对比表

项目 通用 GPIO 高速 GPIO (GPIOHS)
简称 GPIO GPIOHS
数量 8 个 32 个
中断源 8 个 IO 共用 1 个中断源 每个 IO 有独立的中断源
中断触发方式 支持 边沿触发电平触发,触发整个 GPIO 总中断 支持 边沿触发电平触发,每个 IO 独立触发
信号方向 可配置为输入或输出 可配置为输入或输出
上下拉/高阻 可配置(资料未特别说明,一般支持) 可配置 上拉下拉 或 高阻
FPIOA 映射 可分配到 FPIOA 上 48 个管脚之一 可分配到 FPIOA 上 48 个管脚之一
主要特点 数量少,共享中断,适合低速、简单 IO 场景 数量多,独立中断,速度快,适合高频/实时响应场景
默认占用情况 无特别说明被系统占用 部分默认已被使用(见下表👇)
适用场景 普通按键、继电器、低速传感器等 高速脉冲计数、精密时序控制、摄像头/屏幕数据线等

⚠️ GPIOHS 默认占用表(尽量不要冲突使用)

GPIOHS 编号 默认功能 说明
GPIOHS31 LCD_DC LCD 数据/指令选择
GPIOHS30 LCD_RST LCD 复位
GPIOHS29 SD_CS SD 卡片选
GPIOHS28 MIC_LED_CLK 麦克风 LED 时钟
GPIOHS27 MIC_LED_DATA 麦克风 LED 数据

一、IO 口输出:点亮一颗 LED 灯

功能说明

通过 K210 芯片 IO 口输出电平信号,控制红、绿、蓝三色 LED 轮流点亮,实现流水灯效果。

硬件连接
  • 绿色 LED → 芯片 12 号引脚
  • 红色 LED → 芯片 13 号引脚
  • 蓝色 LED → 芯片 14 号引脚
# ================================
# 三色LED流水灯示例
# 功能:让红、绿、蓝三颗LED轮流亮起,形成跑马灯效果
# 硬件连接:
#   绿色LED -> 芯片12号引脚
#   红色LED -> 芯片13号引脚  
#   蓝色LED -> 芯片14号引脚
# ================================

# 导入需要的工具箱
# fpioa_manager 是"引脚功能分配管理员",负责管理芯片引脚的工作
from fpioa_manager import fm
#GPIO 是"通用输入输出"功能
from Maix import GPIO
# utime 是时间工具,用来让程序暂停一段时间
import utime


# ===== 定义我们要用的LED灯连接在哪些引脚上 =====
# 绿色LED灯连接在芯片的第12号引脚
led_green = 12
# 红色LED灯连接在芯片的第13号引脚
led_red = 13
# 蓝色LED灯连接在芯片的第14号引脚
led_blue = 14

# ===== 关键步骤:告诉芯片每个引脚要做什么工作 =====
# fm.register(引脚号, 要分配的功能)
# 把第12号引脚(连接绿色LED)分配给GPIO0功能
# 把第13号引脚(连接红色LED)分配给GPIO1功能
# 把第14号引脚(连接蓝色LED)分配给GPIO2功能
# 就像给插座贴上"电灯专用"的标签,并编号0、1、2
fm.register(led_green, fm.fpioa.GPIO0)
fm.register(led_red, fm.fpioa.GPIO1)
fm.register(led_blue, fm.fpioa.GPIO2)

# ===== 创建LED控制对象 =====
# GPIO(使用的GPIO编号, 模式)
# GPIO.GPIO0 表示使用刚才分配的0号GPIO(控制绿色LED)
# GPIO.OUT 表示这个引脚要作为"输出"使用(控制LED亮灭)

# GPIO.GPIO1 控制绿色LED
led_g = GPIO(GPIO.GPIO0, GPIO.OUT)

# GPIO.GPIO1 控制红色LED
led_r = GPIO(GPIO.GPIO1, GPIO.OUT)

# GPIO.GPIO2 控制蓝色LED
led_b = GPIO(GPIO.GPIO2, GPIO.OUT)


# ===== 主循环:让LED一直闪烁 =====
while (1):
    # --- 第1步:只有绿灯亮,其他两个灭 ---
    # value(0) 表示输出低电平,在根据电路中低电平会让LED点亮
    # value(1) 表示输出高电平,会熄灭LED

    led_g.value(0)   # 绿灯亮
    led_r.value(1)   # 红灯灭
    led_b.value(1)   # 蓝灯灭
    utime.sleep_ms(500)  # 让灯保持这个状态 500毫秒(0.5秒),方便我们观察
    
    # --- 第2步:只有红灯亮,其他两个灭 ---
    led_g.value(1)   # 绿灯灭
    led_r.value(0)   # 红灯亮
    led_b.value(1)   # 蓝灯灭
    utime.sleep_ms(500)  # 延时0.5秒
    
    # --- 第3步:只有蓝灯亮,其他两个灭 ---
    led_g.value(1)   # 绿灯灭
    led_r.value(1)   # 红灯灭
    led_b.value(0)   # 蓝灯亮
    utime.sleep_ms(500)  # 延时0.5秒


# ================================
# 【小白实操提示】
# 1. 如果灯亮灭相反,可以把 value(0) 与 value(1) 对调
# 2. 想改变闪烁速度,可修改 sleep_ms(500) 里的数值,例如200会更闪,1000会更慢
# ================================

二、IO 口输入:按键输入检测(按键控制 LED 灯翻转)

功能说明

通过读取按键引脚的电平状态,实现按键触发时蓝色 LED 状态(亮 / 灭)的翻转,包含按键防抖处理以避免误触发。

硬件连接
  • 绿色 LED → 芯片 12 号引脚
  • 红色 LED → 芯片 13 号引脚
  • 蓝色 LED → 芯片 14 号引脚
  • BOOT 按键 → 芯片 16 号引脚(按键一端接地,按下时输入低电平)
# ================================
# 三色LED + 按键控制示例
# 功能说明:
#   初始状态:三个LED全灭(高电平熄灭,具体取决于电路)
#   按下 BOOT 按键(连接在 IO16)时,蓝色LED 状态翻转(亮变灭、灭变亮)
#   按键有防抖处理,避免误触发
# 硬件连接:
#   绿色LED -> 芯片引脚12 (IO_12)
#   红色LED -> 芯片引脚13 (IO_13)
#   蓝色LED -> 芯片引脚14 (IO_14)
#   BOOT按键 -> 芯片引脚16 (IO_16),按键一端接地,按下时输入低电平
# ================================

# 导入需要的工具箱
# fpioa_manager 负责管理芯片引脚的工作
from fpioa_manager import fm
# GPIO 是"通用输入输出"功能
from Maix import GPIO
# utime 是时间工具,用来让程序暂停一段时间
import utime


# ===== 定义硬件连接的引脚编号 =====
# 绿色LED灯连接在芯片的第12号引脚(对应IO_12)
led_green = 12
# 红色LED灯连接在芯片的第13号引脚(对应IO_13)
led_red = 13
# 蓝色LED灯连接在芯片的第14号引脚(对应IO_14)
led_blue = 14
# BOOT按键连接在芯片的第16号引脚(对应IO_16)
io_boot_key = 16


# ===== 关键步骤:告诉芯片每个引脚要做什么工作 =====
# fm.register(引脚号, 要分配的功能)
# 把引脚分配给指定的GPIO功能,相当于给引脚贴上用途标签

# 把12号引脚(绿色LED)分配给GPIO0功能
fm.register(led_green, fm.fpioa.GPIO0)
# 把13号引脚(红色LED)分配给GPIO1功能
fm.register(led_red, fm.fpioa.GPIO1)
# 把14号引脚(蓝色LED)分配给GPIO2功能
fm.register(led_blue, fm.fpioa.GPIO2)
# 把16号引脚(BOOT按键)分配给GPIO3功能,作为输入使用
fm.register(io_boot_key, fm.fpioa.GPIO3)


# ===== 创建LED控制对象 =====
# GPIO(使用的GPIO编号, 模式)
# GPIO.OUT 表示该引脚用于控制输出(LED亮灭)
led_g = GPIO(GPIO.GPIO0, GPIO.OUT)  # 控制绿色LED
led_r = GPIO(GPIO.GPIO1, GPIO.OUT)  # 控制红色LED
led_b = GPIO(GPIO.GPIO2, GPIO.OUT)  # 控制蓝色LED

# 创建按键输入对象
# GPIO.IN 表示该引脚作为输入使用(读取按键状态)
key = GPIO(GPIO.GPIO3, GPIO.IN)


# ===== 初始化LED状态 =====
# 初始让所有LED熄灭
# 常见开发板是低电平点亮,所以初始给高电平(1)是熄灭
led_g.value(1)   # 绿灯灭
led_r.value(1)   # 红灯灭
led_b.value(1)   # 蓝灯灭


# 定义一个变量记录蓝色LED的状态
# True 表示亮,False 表示灭
led_state = True  # bool类型,只有True和False两个值


# ===== 进入程序死循环 =====
while True:
    # 检测按键是否被按下
    # key.value() 读取按键引脚的电平状态

    # 这里假设按键按下时引脚为低电平(0),未按下为高电平(1)
    if key.value() == 0:  # 检测到按键按下(低电平)
        utime.sleep_ms(20)  # 延时20毫秒进行"消抖"
        # 机械按键按下时会抖动,产生多次高低电平变化,延时后再判断一次可避免误触发
        
        if key.value() == 0:  # 再次确认按键确实还按着
            # 翻转蓝色LED的状态:原来是亮的变灭,原来是灭的变亮
            led_state = not led_state
            # 把新的状态写入蓝色LED
            led_b.value(led_state)
            
            # 等待按键释放(防止按住不放时反复触发)
            while(key.value() == 0):  # 如果按键仍然按着(低电平)
                utime.sleep_ms(20)   # 继续等待,直到松手变成高电平
            # 按键释放后,循环继续检测下一次按键


# ================================
# 【小白实操提示】
# 1. 如果LED亮灭与预期相反:
#    - 调换 value(0) 与 value(1) 的赋值
# 2. 按键无反应排查:
#    - 检查引脚是否接对,BOOT键是否接IO16
#    - 确认电路支持读取低电平为按下
# ================================

三、外部中断:按键外部中断控制 LED 翻转

中断选型说明

GPIOHS 每个引脚具备独立中断源,响应速度快、实时性好,适配高频 / 实时响应场景;而普通 GPIO 共用中断源,需软件判断触发引脚,效率较低,不适用于高精度中断场景。

功能说明

采用 GPIOHS 实现按键中断触发,按下 BOOT 按键时蓝色 LED 状态翻转,启用内部上拉电阻避免引脚悬空,包含防抖处理。

硬件连接
  • 绿色 LED → 芯片 12 号引脚 → GPIO0
  • 红色 LED → 芯片 13 号引脚 → GPIO1
  • 蓝色 LED → 芯片 14 号引脚 → GPIO2
  • BOOT 按键 → 芯片 16 号引脚 → GPIOHS0(按键一端接地,按下为低电平)
# ================================
# 三色LED + 按键中断控制示例
# 功能说明:
#   初始状态:三个LED全灭
#   使用中断方式检测 BOOT 按键(连接在 IO16),按下时蓝色LED状态翻转(亮 ↔ 灭)
#   采用 GPIOHS(高速GPIO)提高响应速度,并使用上拉电阻避免悬空
# 硬件连接:
#   绿色LED -> 芯片引脚12 (IO_12) -> GPIO0
#   红色LED -> 芯片引脚13 (IO_13) -> GPIO1
#   蓝色LED -> 芯片引脚14 (IO_14) -> GPIO2
#   BOOT按键 -> 芯片引脚16 (IO_16) -> GPIOHS0(按键一端接地,按下为低电平)
# ================================

# 导入需要的工具箱
# fpioa_manager 负责管理芯片引脚的工作
from fpioa_manager import fm
#GPIO 是"通用输入输出"功能
from Maix import GPIO
# utime 是时间工具,用来让程序暂停一段时间
import utime


# ===== 定义硬件连接的引脚编号 =====
led_green = 12   # 绿色LED接芯片第12脚(IO_12)
led_red   = 13   # 红色LED接芯片第13脚(IO_13)
led_blue  = 14   # 蓝色LED接芯片第14脚(IO_14)
io_boot_key = 16 # BOOT按键接芯片第16脚(IO_16)


# ===== 关键步骤:告诉芯片每个引脚要做什么工作 =====
# fm.register(引脚号, 要分配的功能)
# 把引脚分配给指定的功能,这里是分配给GPIO或GPIOHS

fm.register(led_green,  fm.fpioa.GPIO0)   # 12脚 -> 普通GPIO0(控制绿灯)
fm.register(led_red,    fm.fpioa.GPIO1)   # 13脚 -> 普通GPIO1(控制红灯)
fm.register(led_blue,   fm.fpioa.GPIO2)   # 14脚 -> 普通GPIO2(控制蓝灯)
fm.register(io_boot_key, fm.fpioa.GPIOHS0) # 16脚 -> 高速GPIO0(读取按键)


# ===== 创建LED控制对象 =====
# GPIO(使用的GPIO编号, 模式)
# GPIO.OUT 表示用作输出,用来控制LED亮灭
led_g = GPIO(GPIO.GPIO0, GPIO.OUT)  # 绿灯控制对象
led_r = GPIO(GPIO.GPIO1, GPIO.OUT)  # 红灯控制对象
led_b = GPIO(GPIO.GPIO2, GPIO.OUT)  # 蓝灯控制对象

# 创建按键输入对象(使用高速GPIO)
# GPIO(使用的GPIOHS编号, 模式, 上拉配置)
# GPIO.IN 表示输入模式,读取按键状态
# GPIO.PULL_UP 表示启用内部上拉电阻,这样按键未按下时引脚为高电平,按下接地变低电平
key = GPIO(GPIO.GPIOHS0, GPIO.IN, GPIO.PULL_UP)


# ===== 初始化LED状态 =====
# 初始让所有LED熄灭
# 电路是低电平点亮(共阴接法),则初始给高电平(1)是熄灭
led_g.value(1)   # 绿灯灭
led_r.value(1)   # 红灯灭
led_b.value(1)   # 蓝灯灭


# 定义一个变量记录蓝色LED的状态
# True 表示亮,False 表示灭(根据电路也可反过来)
led_state = True  # bool类型,只有True和False两个值


# ===== 中断回调函数 =====
# 当按键触发中断时,这个函数会被自动调用
def test_irq(key):
    # 声明使用全局变量 led_state,这样才能在函数内修改它
    global led_state
    
    # 延时20ms消除按键机械抖动(抖动会造成多次误触发)
    utime.sleep_ms(20)
    
    # 再次确认按键仍然是按下的状态(低电平)
    # 因为中断可能在抖动时触发,所以要验证
    if key.value() == 0:  
        # 翻转蓝灯状态:取反(True变False,False变True)
        led_state = not led_state
        # 将新状态写入蓝灯
        led_b.value(led_state)


# ===== 进入程序死循环 =====
# 虽然中断可以实时响应按键,但这里需要开启中断功能
while True:
    # key.irq(回调函数名, 触发方式)
    # test_irq   -> 按键按下时要调用的函数
    # GPIO.IRQ_FALLING -> 下降沿触发(电平从高变低,即按键按下瞬间)
    key.irq(test_irq, GPIO.IRQ_FALLING)
    
    # 如果之后想关闭中断,可以用 key.disirq()
    # key.disirq()  # 取消中断功能(目前被注释掉,不执行)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐