McuStudioMcuStudio
指南
开发者
组件
API
  • 版本发布
指南
开发者
组件
API
  • 版本发布
  • 概述
  • 快速开始
  • 添加厂商的芯片到平台
  • 芯片模板教程

    • 芯片模板开发教程
    • 创建引脚封装
    • 配置时钟树
    • 配置 GPIO 外设
    • 配置 ADC 外设
    • 配置通信外设
    • 配置 TIM 外设
  • 开发参考

    • 框架与规则
    • 芯片包结构
    • 芯片描述
    • 芯片包配置
    • 引脚配置详解
    • 外设配置详解
    • 外设元素参考
    • GPIO 开发参考
    • ADC 开发参考
    • TIM 开发参考
    • 固件库开发指南
    • 版本管理机制
    • Define 映射指南
    • 多语言(i18n)

配置 GPIO 外设

本教程将引导您完成 GPIO(通用输入输出)外设的芯片模板配置。GPIO 是所有 MCU 外设中最基础、使用最频繁的模块,掌握 GPIO 配置方法是学习芯片模板开发的起点。

概述

GPIO UI 配置文件用于定义图形化配置界面中的 GPIO 外设参数和操作逻辑。通过创建基础配置文件和特定版本配置文件,可以为不同系列的芯片提供差异化的 GPIO 配置功能。

文件结构

ips/
└── GPIO/
    ├── ui/
    │   ├── gpio_base.cjs          # GPIO 基础配置文件(通用)
    │   └── {series}.cjs           # 特定系列配置文件(差异化)
    └── code/
        └── {version}/
            ├── pre.cjs            # 初始化脚本(入口)
            ├── std.c.ejs          # Standard 固件代码模板
            ├── hal.c.ejs          # HAL 固件代码模板
            └── ll.c.ejs           # LL 固件代码模板

配置文件结构

GPIO UI 配置文件导出一个对象,包含以下三个主要部分:

1. project — 外设项目配置

project: {
  generate_code: { value: true, fixed: false },  // 是否生成代码
  rank: { value: 2, fixed: true },               // 外设排名(显示顺序)
  do_not_generate_function_call: { value: false },// 是否不生成函数调用
  function_name: { value: 'Studio_GPIO_Init' },  // 初始化函数名称
  firmware: {                                      // 固件类型选项
    value: 'std',
    options: [
      { label: 'Standard', value: 'std' },
      { label: 'HAL', value: 'hal' },
      { label: 'LL', value: 'll' }
    ]
  },
  file_name: 'gpio',                              // 生成文件名
  ip_type: 'GPIO'                                 // 外设类型
}

2. parameters — 外设参数配置

定义 GPIO 配置界面中的可配置参数:

mode — GPIO 模式

值标签说明
AINanalog input模拟输入
IN_FLOATINGfloating input浮空输入
IPDpull-down input下拉输入
IPUpull-up input上拉输入
OUT_ODoutput open-drain开漏输出
OUT_PPoutput push-pull推挽输出
AF_ODalternate open-drain复用开漏输出
AF_PPalternate push-pull复用推挽输出
IT_RisingIT Rising Edge上升沿中断
IT_FallingIT Falling Edge下降沿中断
IT_BothIT Both Edge双边沿中断
EVT_RisingEvent Rising Edge上升沿事件
EVT_FallingEvent Falling Edge下降沿事件
EVT_BothEvent Both Edge双边沿事件
NAn/a不适用

speed — GPIO 速度

值说明
GPIO_OSPEED_10MHZ10MHz
GPIO_OSPEED_2MHZ2MHz
GPIO_OSPEED_50MHZ50MHz
NA不适用

level — 输出电平

值说明
Low低电平
High高电平
NA不适用

3. functions — 功能函数

GPIO 表格定义

GPIO 配置界面以表格形式呈现,表头定义如下:

{
  name: {
    label: 'Pin',
    type: 'text'
  },
  mode: {
    label: 'Mode',
    type: 'select',
    options: [ /* 上述14种模式 */ ]
  },
  speed: {
    label: 'Speed',
    type: 'select',
    options: [ /* 上述4种速度 */ ]
  },
  level: {
    label: 'OutputLevel',
    type: 'select',
    options: [ /* 上述3种电平 */ ]
  },
  alternate: {
    label: 'Alternate',
    type: 'text'
  }
}

引脚选择逻辑

手动选择引脚

当用户在芯片引脚图上手动点击某个引脚并选择一个复用功能时,系统调用 headPeripheralPinAf(pin, af) 函数:

headPeripheralPinAf(pin, af) {
  // 如果 af 是 Reset_State,表示复位引脚
  if (af.name === 'Reset_State') {
    // 从 GPIO 表中删除该引脚
    this.deletePinByName(pin.name)
    return
  }

  // 获取该复用功能的默认参数
  const params = this.getPinParameter(af)

  // 如果该复用功能是唯一的(不支持多引脚)
  if (isUniqueAlternate(af)) {
    // 删除原来绑定该功能的引脚
    this.deletePinByAlternate(af.name)
  }

  // 更新当前引脚的复用功能
  this.updatePinByAlternate(pin, af)
}

自动选择引脚

由系统自动调用 auto_set_pins(target, name) 函数:

auto_set_pins(target, name) {
  if (target) {
    // 启用时:查找支持该功能的空闲引脚并添加
    this.addPinByAlternate(name)
  } else {
    // 禁用时:删除未锁定的引脚
    if (!this.hasLockedPin(name)) {
      this.deletePinByAlternate(name)
    }
  }
}

GPIO 数据合并优化

在生成 GPIO 初始化代码时,相同 PORT 下配置相同的引脚可以合并为一条初始化语句,减少代码体积:

合并前(不合并):

gpio_init(GPIOE, GPIO_MODE_OUT_OD, GPIO_OSPEED_10MHZ, GPIO_PIN_2);
gpio_init(GPIOE, GPIO_MODE_OUT_OD, GPIO_OSPEED_10MHZ, GPIO_PIN_3);
gpio_init(GPIOE, GPIO_MODE_OUT_OD, GPIO_OSPEED_10MHZ, GPIO_PIN_4);

合并后:

gpio_init(GPIOE, GPIO_MODE_OUT_OD, GPIO_OSPEED_10MHZ, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4);

合并规则:相同 PORT + Mode + Speed 的引脚可以合并。User Label、Level、Alternate 参数不影响合并判断。

代码生成流程

GPIO 初始化代码的生成遵循以下流程:

// pre.cjs 入口函数
module.exports = ({ ip, ide, locals }) => {
  const global = locals.global

  // 1. 获取 GPIO 初始化数据(包含所有引脚配置)
  let ip_pins = global.GPIO.get_ip_gpios([
    ip.$name, 'EVENTOUT', 'IR', 'MCO'
  ])

  // 2. 转换为对应固件平台的参数
  global.GPIO.set_gpio_define_map(
    locals.defineMap,
    ip.firmware.value,
    ip_pins.pins
  )

  // 3. 将数据合并到 ip 对象
  Object.assign(ip, ip_pins)

  // 4. 生成中断处理函数
  set_nvic_handlers(global, ip)
}

get_ip_gpios 函数内部流程

  1. 根据 gpioTypes 过滤出所有符合要求的引脚
  2. 生成引脚描述数据(用于代码注释)
  3. 根据引脚 PORT 进行分组
  4. 对相同 PORT 下的引脚,按配置进行分组合并
  5. 检查引脚是否有 EXTI 中断
  6. 生成 resetPins 和 setPins(用于设置初始电平)

注意事项

  1. 函数命名:auto_set_pins 函数名不可修改,由程序自动调用
  2. 引脚可见性:系统引脚(NRST、BOOT0、SWDIO、SWCLK)默认不在表格中显示
  3. 引脚锁定:通过 _locked: true 标记的引脚不能被删除
  4. 正则匹配:支持 ${num} 模式匹配多个实例(如 TIM${num}_CH1)
  5. 参数映射:需要配合 chip/{系列}/define.cjs 中的 GPIO.mode 和 GPIO.speed 映射

下一步

  • 继续学习 配置 ADC 外设 — 掌握更复杂的外设模式依赖
  • 查阅 GPIO 开发参考 — 了解更深入的优化策略
  • 查阅 引脚配置详解 — 了解引脚选型和复用功能配置
Prev
配置时钟树
Next
配置 ADC 外设