Funpack5-3 - 基于MAX32690EVKIT实现按键控制LED闪烁
该项目使用了ADI的评估套件MAX32690EVKIT,实现了按键控制LED闪烁的设计,它的主要功能为:单次按键 → LED开始闪烁;再次按键 → LED停止闪烁。
标签
Funpack活动
按键
MAX32690
maxim micros sdk
GPIO中断
子午鼠
更新2026-08-12
30

一、项目介绍

1.1 活动背景

本项目是参加硬禾科技联合DigiKey发起的Funpack活动第五季第3期Funpack S5 #3第五季第3期的板卡是来自 Analog Devices 的评估套件 MAX32690EVKIT

MAX32690 评估套件提供了一个平台,用于评估 MAX32690 微控制器的功能,该微控制器是一款先进的片内系统 。它采用了 Arm Cortex-M4F CPU,可高效计算复杂的功能和算法,并采用了最新一代的 Bluetooth 5 低功耗(蓝牙 LE)射频,专为可穿戴和便携式健身设备、便携式和可穿戴式医疗设备、工业传感器/网络、物联网  和资产追踪而设计。

image.png

1.2 项目概述

本项目基于 MAX32690EVKIT 开发板,实现了 任务1:按键控制LED闪烁 基础功能

本项目实现功能:

  • 单次按键  LED 开始闪烁(频率约 1Hz)
  • 再次按键  LED 停止闪烁(保持熄灭状态)
  • 功能要求
    • ✅ 正确初始化 GPIO 中断
    • ✅ LED 控制逻辑清晰,不出现误触发
    • ✅ 闪烁频率约 1Hz

1.3 项目成果

通过本项目的开发,成功完成了 Funpack S5 #3 活动任务1的基础题目要求:

  • ✅ 了解 MAX32690EVKIT 开发板的硬件结构和特性
  • ✅ 掌握 Maxim MSDK 的 GPIO 驱动开发
  • ✅ 实现 GPIO 中断的正确初始化与配置
  • ✅ 实现按键消抖机制,避免误触发
  • ✅ 实现 1Hz 频率的 LED 闪烁控制
  • ✅ 掌握程序烧录与独立运行验证方法

二、硬件介绍

2.1 微控制器:MAX32690

MAX32690 是基于 Arm® Cortex®-M4F 处理器的超低功耗微控制器,具备以下核心特性:

  • 处理器:Arm® Cortex®-M4F,带 FPU,最高 100MHz
  • 存储器:2MB 双 bank Flash,512KB SRAM
  • 无线连接:Bluetooth 5 低功耗(蓝牙 LE)射频
  • 超低功耗:多种低功耗模式,适合电池供电设备
  • 丰富外设:SPI、UART、I2C、GPIO、定时器、PWM、ADC 等
  • 调试接口:SWD 调试支持

image.png

2.2 MAX32690EVKIT 开发板概述

MAX32690EVKIT 是用于评估 MAX32690 MCU 的官方硬件平台,板载资源包括:

名称

特性

MAX32690 MCU

Arm® Cortex®-M4F 微控制器,带 BLE 5.0

User LED

红色 LED(GPIO0_14,低电平点亮)

User Switch

SW2 用户按键(GPIO4_0,按下为低电平)

显示屏

128 x 128(1.45 英寸)TFT 彩色显示屏

音频

MAX9867 立体声音频编解码器,3.5mm 插孔

存储器

板载 HyperRAM

调试接口

MAX32625PICO 调试器接口,支持 CMSIS-DAP

image.png

2.3 引脚分配

本项目主要用到板载按键 SW2 和红色 LED0:

  • 按键 SW2:连接至 GPIO4_0(P4.0),按下时为低电平
  • 红色 LED0:连接至 GPIO0_14(P0.14),低电平点亮

额外用到绿色LED1:

  • 绿色 LED1:连接至 GPIO2_12(P2.12),进入中断指示灯

image.png

2.4 原理图

MAX32690EVKIT 原理图主要包括电源原理图、MCU 原理图和调试器原理图。其中最应关注的是 MCU 原理图中的两个引脚 GPIO4_0(按键)和 GPIO0_14(LED)。

GPIO4_0脚通过杜邦线连接至GPIO2_11,因此实际的按键输入为P2.11


三、方案框图和项目设计思路

3.1 方案框图

根据项目要求,确定方案框图如下:

image.png

3.2 项目设计思路

硬件设计:

  • 使用板载按键 SW2(连接至 GPIO4_0)作为输入,配置为下降沿触发中断,GPIO4_0脚通过杜邦线连接至GPIO2_11,因此实际的按键输入为P2.11
  • 使用板载红色 LED0(连接至 GPIO0_14)作为输出,低电平点亮
  • 使用板载绿色 LED1(连接至 GPIO2_12),进入中断指示灯

软件设计:

  • GPIO 初始化GPIO2_11 配置为输入模式,使能内部上拉,配置下降沿中断;GPIO0_14 配置为推挽输出模式
  • 中断服务函数
    • 进入中断后立即禁用该引脚中断,防止抖动再次触发
    • 清除中断标志
    • 软件消抖延时(约 20ms)
    • 再次读取引脚电平,确认是有效按键(低电平)
    • 切换 LED 状态标志 led_blink_enable
    • 重新使能中断
  • 主循环控制
    •  led_blink_enable == 1:LED 以 500ms 间隔翻转(1Hz 闪烁)
    •  led_blink_enable == 0:LED 保持熄灭
  • 消抖机制:采用 中断内禁用 + 软件延时 + 电平二次确认 的消抖策略,有效滤除按键的机械抖动和噪声

3.3 调试引脚设计(可选)

为便于调试观察中断是否触发,可配置 GPIO2_12(P2.12)作为调试指示引脚:

  • 每次有效按键处理后翻转 P2.12 电平
  • 可用示波器或逻辑分析仪观察中断触发情况

四、开发环境介绍、软件流程图及关键代码

4.1 开发环境介绍

4.1.1 开发环境

本项目使用 Analog Devices 官方提供的 Maxim Micros SDK  作为软件开发框架。

软件

版本

用途

Eclipse

2023-06

集成开发环境

Maxim MSDK

最新版

MAX32690 驱动库和示例代码

OpenOCD

0.12.0 

调试和烧录工具

GCC ARM

10.3.1

ARM Cortex-M 编译器

MAX32625PICO

CMSIS-DAP v2.1.0

调试器硬件

4.1.2 项目新建

1.将 MAX32690EVKIT 通过 USB 连接到电脑,确保 MAX32625PICO 调试器已连接

image.png

2.打开 Eclipse IDE,新建项目:File——New——Project...,选择工程类别

3.配置项目名称和路径

4.选择芯片型号、开发板型号、工程模板、调试器型号等

image.png

4.2 程序流程图

4.2.1 主程序流程图

image.png

4.2.2 GPIO 中断服务函数流程图

image.png

4.3 关键代码介绍

以下为主程序完整代码,并对代码进行详细解析。

/**
* @file main.c
* @brief Funpack S5 #3 - 任务1:按键控制LED闪烁
* 单次按键 → LED开始闪烁 (1Hz)
* 再次按键 → LED停止闪烁
* 调试: P2.12 翻转指示中断触发
*/

#include <stdio.h>
#include <string.h>
#include "mxc_device.h"
#include "nvic_table.h"
#include "board.h"
#include "gpio.h"
#include "mxc_delay.h"

/***** 硬件引脚定义 *****/
#define MXC_GPIO_PORT_IN MXC_GPIO4 // 按键输入端口 (SW2)
#define MXC_GPIO_PIN_IN MXC_GPIO_PIN_0 // 按键引脚

#define MXC_GPIO_PORT_OUT MXC_GPIO0 // LED输出端口
#define MXC_GPIO_PIN_OUT MXC_GPIO_PIN_14 // LED引脚 (红色LED0)

#define MXC_GPIO_PORT_DBG MXC_GPIO2 // 调试端口
#define MXC_GPIO_PIN_DBG MXC_GPIO_PIN_12 // 调试引脚 (可选)

/***** 全局状态变量 *****/
volatile uint8_t led_blink_enable = 0; // 0: 停止, 1: 闪烁

/***** 函数声明 *****/
void GPIO4_IRQHandler(void); // GPIO4 中断服务函数

/***** 主函数 *****/
int main(void)
{
mxc_gpio_cfg_t gpio_in;
mxc_gpio_cfg_t gpio_out;
mxc_gpio_cfg_t gpio_dbg;

// ---------- 1. 配置输出引脚 (LED) ----------
gpio_out.port = MXC_GPIO_PORT_OUT;
gpio_out.mask = MXC_GPIO_PIN_OUT;
gpio_out.pad = MXC_GPIO_PAD_NONE;
gpio_out.func = MXC_GPIO_FUNC_OUT;
gpio_out.vssel = MXC_GPIO_VSSEL_VDDIO;
gpio_out.drvstr = MXC_GPIO_DRVSTR_0;
MXC_GPIO_Config(&gpio_out);
MXC_GPIO_OutSet(gpio_out.port, gpio_out.mask); // 初始熄灭 (高电平)

// ---------- 2. 配置调试引脚 (P2.12, 可选) ----------
gpio_dbg.port = MXC_GPIO_PORT_DBG;
gpio_dbg.mask = MXC_GPIO_PIN_DBG;
gpio_dbg.pad = MXC_GPIO_PAD_NONE;
gpio_dbg.func = MXC_GPIO_FUNC_OUT;
gpio_dbg.vssel = MXC_GPIO_VSSEL_VDDIO;
gpio_dbg.drvstr = MXC_GPIO_DRVSTR_0;
MXC_GPIO_Config(&gpio_dbg);
MXC_GPIO_OutSet(gpio_dbg.port, gpio_dbg.mask);

// ---------- 3. 配置输入引脚 (按键) ----------
gpio_in.port = MXC_GPIO_PORT_IN;
gpio_in.mask = MXC_GPIO_PIN_IN;
gpio_in.pad = MXC_GPIO_PAD_PULL_UP; // 内部上拉
gpio_in.func = MXC_GPIO_FUNC_IN;
gpio_in.vssel = MXC_GPIO_VSSEL_VDDIOH;
gpio_in.drvstr = MXC_GPIO_DRVSTR_0;
MXC_GPIO_Config(&gpio_in);

// 清除中断标志,配置下降沿触发
MXC_GPIO_ClearFlags(gpio_in.port, gpio_in.mask);
MXC_GPIO_IntConfig(&gpio_in, MXC_GPIO_INT_FALLING);
MXC_GPIO_EnableInt(gpio_in.port, gpio_in.mask);

// 使能 GPIO4 中断
NVIC_EnableIRQ(GPIO4_IRQn);

// ---------- 4. 主循环 (使用延时实现1Hz闪烁) ----------
while (1) {
if (led_blink_enable) {
MXC_GPIO_OutClr(MXC_GPIO_PORT_OUT, MXC_GPIO_PIN_OUT); // LED 亮
MXC_Delay(MXC_DELAY_MSEC(500)); // 延时 500ms
MXC_GPIO_OutSet(MXC_GPIO_PORT_OUT, MXC_GPIO_PIN_OUT); // LED 灭
MXC_Delay(MXC_DELAY_MSEC(500)); // 延时 500ms
} else {
MXC_GPIO_OutSet(MXC_GPIO_PORT_OUT, MXC_GPIO_PIN_OUT); // 保持熄灭
MXC_Delay(MXC_DELAY_MSEC(10)); // 短暂延时,避免忙等待
}
}
}

/***** GPIO4 中断服务函数 *****/
void GPIO4_IRQHandler(void)
{
// 1. 立即禁用按键引脚中断,防止后续抖动再次触发
MXC_GPIO_DisableInt(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);

// 2. 清除中断标志
uint32_t flags = MXC_GPIO_GetFlags(MXC_GPIO_PORT_IN);
if (flags & MXC_GPIO_PIN_IN) {
MXC_GPIO_ClearFlags(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);
}

// 3. 软件消抖延时 (约20ms)
MXC_Delay(MXC_DELAY_MSEC(20));

// 4. 再次读取引脚电平,确认是有效按下 (低电平)
if (MXC_GPIO_InGet(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN) == 0) {
// ---- 有效按键处理 ----
// 翻转调试指示引脚 (用于观察中断触发)
MXC_GPIO_OutToggle(MXC_GPIO_PORT_DBG, MXC_GPIO_PIN_DBG);

// 切换 LED 状态
led_blink_enable = !led_blink_enable;

// 若停止闪烁,立即熄灭 LED
if (!led_blink_enable) {
MXC_GPIO_OutSet(MXC_GPIO_PORT_OUT, MXC_GPIO_PIN_OUT);
}
}

// 5. 清除可能因消抖期间产生的额外中断标志
MXC_GPIO_ClearFlags(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);

// 6. 重新使能按键引脚中断
MXC_GPIO_EnableInt(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);
}

4.3.1 硬件引脚定义

#define MXC_GPIO_PORT_IN     MXC_GPIO4      // 按键输入端口 (SW2)
#define MXC_GPIO_PIN_IN MXC_GPIO_PIN_0 // 按键引脚
#define MXC_GPIO_PORT_OUT MXC_GPIO0 // LED输出端口
#define MXC_GPIO_PIN_OUT MXC_GPIO_PIN_14 // LED引脚 (红色LED0)

定义项目使用的硬件引脚,便于代码移植和维护。

4.3.2 全局状态变量

volatile uint8_t led_blink_enable = 0;   // 0: 停止, 1: 闪烁

使用 volatile 关键字修饰,确保编译器不会优化掉该变量,保证中断和主循环之间的数据一致性。

4.3.3 GPIO 初始化

// LED 配置为推挽输出
gpio_out.port = MXC_GPIO_PORT_OUT;
gpio_out.mask = MXC_GPIO_PIN_OUT;
gpio_out.pad = MXC_GPIO_PAD_NONE;
gpio_out.func = MXC_GPIO_FUNC_OUT;
gpio_out.vssel = MXC_GPIO_VSSEL_VDDIO;
gpio_out.drvstr = MXC_GPIO_DRVSTR_0;
MXC_GPIO_Config(&gpio_out);
MXC_GPIO_OutSet(gpio_out.port, gpio_out.mask); // 初始熄灭

// 按键配置为输入,内部上拉
gpio_in.port = MXC_GPIO_PORT_IN;
gpio_in.mask = MXC_GPIO_PIN_IN;
gpio_in.pad = MXC_GPIO_PAD_PULL_UP; // 内部上拉
gpio_in.func = MXC_GPIO_FUNC_IN;
MXC_GPIO_Config(&gpio_in);

// 配置下降沿中断
MXC_GPIO_ClearFlags(gpio_in.port, gpio_in.mask);
MXC_GPIO_IntConfig(&gpio_in, MXC_GPIO_INT_FALLING);
MXC_GPIO_EnableInt(gpio_in.port, gpio_in.mask);
NVIC_EnableIRQ(GPIO4_IRQn);

关键点:

  • LED 配置为推挽输出,初始高电平(LED 熄灭,因为低电平点亮)
  • 按键配置为输入模式,使能内部上拉电阻
  • 配置下降沿触发中断(按键按下时电平从高变低)
  • 使能 GPIO4 中断向量

4.3.4 GPIO 中断服务函数

void GPIO4_IRQHandler(void)
{
// 1. 立即禁用按键引脚中断,防止后续抖动再次触发
MXC_GPIO_DisableInt(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);

// 2. 清除中断标志
uint32_t flags = MXC_GPIO_GetFlags(MXC_GPIO_PORT_IN);
if (flags & MXC_GPIO_PIN_IN) {
MXC_GPIO_ClearFlags(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);
}

// 3. 软件消抖延时 (约20ms)
MXC_Delay(MXC_DELAY_MSEC(20));

// 4. 再次读取引脚电平,确认是有效按下 (低电平)
if (MXC_GPIO_InGet(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN) == 0) {
// 翻转调试指示引脚
MXC_GPIO_OutToggle(MXC_GPIO_PORT_DBG, MXC_GPIO_PIN_DBG);
// 切换 LED 状态
led_blink_enable = !led_blink_enable;
if (!led_blink_enable) {
MXC_GPIO_OutSet(MXC_GPIO_PORT_OUT, MXC_GPIO_PIN_OUT);
}
}

// 5. 清除可能因消抖期间产生的额外中断标志
MXC_GPIO_ClearFlags(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);

// 6. 重新使能按键引脚中断
MXC_GPIO_EnableInt(MXC_GPIO_PORT_IN, MXC_GPIO_PIN_IN);
}

关键点:

  • 进入中断立即禁用该引脚中断:防止在消抖和处理期间再次触发中断,彻底杜绝误触发
  • 双重清除中断标志:在开始和结束都清除标志,确保挂起标志被清除干净
  • 软件消抖延时:延时 20ms 后再次读取电平,确认是真实按键
  • 电平二次确认:只有读取到低电平才执行有效按键处理
  • 重新使能中断:处理完成后重新打开中断,准备下一次按键

五、功能展示与说明

按下按键 ,红色LED 开始闪烁(频率约 1Hz);再次按下按键,红色LED 停止闪烁(保持熄灭状态)。LED 控制逻辑清晰,不出现误触发。同时,每次按下按键,进入一次中断,中断指示灯绿色LED状态翻转。


六、项目总结

6.1 遇到的问题与解决方案

问题

解决方案

编译错误:MXC_GPIO_IntClear 未定义

使用 MXC_GPIO_ClearFlags 替代

中断服务函数命名不匹配

使用启动文件中定义的 GPIO4_IRQHandler

按键误触发(多次进入中断)

中断内禁用引脚中断 + 软件消抖 + 电平二次确认

断电后程序无法独立运行

检查安全启动签名,使用正确烧录方式

6.2 项目收获

通过本项目的开发,深入了解了:

  • MAX32690EVKIT 的硬件架构和引脚功能
  • MSDK 的 GPIO 驱动库使用方法
  • GPIO 中断的正确配置与消抖处理
  • 嵌入式程序从开发到烧录的完整流程
  • 中断服务函数与主循环的数据同步机制

6.3 可扩展方向(Funpack 进阶题目)

根据 Funpack S5 #3 活动的进阶题目要求,本项目可进一步扩展:

  • 长按调节频率:在基础题之上,实现长按按键调节 LED 闪烁频率
  • 频率线性变化:短按控制开关,长按实现 1Hz → 5Hz 线性变化
  • 反向调节:到达最快后,保持长按可实现 5Hz → 1Hz 反向变化
  • 平滑过渡:频率变化过程应平滑,无明显跳变

七、参考资料

  1. Funpack S5 #3 活动页面 - 硬禾科技
  2. MAX32690EVKIT 用户指南 - Analog Devices
  3. Maxim Micros SDK  用户手册
  4. ARM Cortex-M4 技术参考手册
  5. OpenOCD 用户手册
  6. Eclipse CDT 开发指南
附件下载
Funpack5-3 - 基于MAX32690EVKIT实现按键控制LED闪烁_项目代码.rar
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号