Funpack5-3 - 基于MAX32690EVKIT实现按键控制LED闪烁
该项目使用了MAX32690EVKIT,实现了按键控制LED闪烁的设计,它的主要功能为:嵌入式系统中常见的人机交互功能:通过按键的短按和长按操作,实现对LED闪烁状态的开关控制以及闪烁频率的连续调节。
标签
串口
按键控制
闪烁
GPIO
Shell
MAX32690EVKIT
Blink
Funpack5-3
Analog
鲜de芒果
更新2026-08-11
27

一、项目简介

1.1 项目背景

本项目基于Analog Devices(原Maxim Integrated)的MAX32690EVKIT开发板,利用MaximSDK软件平台,实现了一个按键控制LED闪烁频率的嵌入式应用示例。该项目展示了嵌入式系统中常见的人机交互功能:通过按键的短按和长按操作,实现对LED闪烁状态的开关控制以及闪烁频率的连续调节。


1.2 硬件平台

  • 主控芯片: MAX32690(ARM Cortex-M4内核,32-bit MCU)
  • 开发板: MAX32690EVKIT(Evaluation Kit)
  • 外设资源: 板载LED(红色LED_RED)、板载按键(PB0)、UART串口


1.3 软件平台

  • SDK: MaximSDK(Analog Devices MSDK)
  • 编译器: ARM GCC(arm-none-eabi-gcc 10.3)
  • 构建工具: GNU Make

二、项目介绍

2.1 功能概览

功能

按键操作

实现效果

LED闪烁开关

短按按键(<500ms)

切换LED闪烁开启/关闭状态

频率正向调节

长按按键(>500ms)

LED闪烁频率从1Hz线性增加到5Hz

频率反向调节

保持长按

到达5Hz后自动反向,从5Hz降低到1Hz

循环调节

持续长按

频率在1Hz~5Hz之间循环往复调节

调试信息输出

按键事件触发

UART串口输出按键类型和当前频率信息

2.2 设计思路

2.2.1 按键处理设计

采用中断驱动+状态机的方式实现按键处理:

  • 中断驱动: 使用GPIO中断检测按键的上升沿和下降沿,避免轮询占用CPU资源
  • 状态机: 定义三个状态(空闲、按下、长按),通过状态转移实现短按/长按的区分
  • 软件去抖: 设置20ms去抖延时,防止按键机械抖动引起的误触发


2.2.2 LED闪烁设计

采用定时器中断实现LED闪烁:

  • 定时器选择: 使用TMR0定时器,配置为连续计数模式
  • 中断频率: 根据目标闪烁频率动态计算定时器周期
  • 状态控制: 通过使能标志控制LED是否响应定时器中断


2.2.3 频率调节设计

采用时间间隔触发+方向反转的方式实现连续频率调节:

  • 调节间隔: 每隔50ms微调一次频率,确保调节过程平滑
  • 调节步长: 0.1Hz的小步长,避免频率跳变
  • 边界反转: 到达频率边界(1Hz或5Hz)时自动反向调节

三、功能实现

3.1 软件流程图

3.1.1 系统初始化流程


3.1.2 按键处理流程


3.1.3 长按频率调节流程


3.2 软件代码实现

3.2.1 配置参数定义

#define LONG_PRESS_THRESHOLD   500        /* 长按判定阈值,单位:毫秒 */
#define DEBOUNCE_DELAY 20 /* 按键去抖延时,单位:毫秒 */
#define FREQ_MIN 1.0f /* LED闪烁频率最小值,单位:Hz */
#define FREQ_MAX 5.0f /* LED闪烁频率最大值,单位:Hz */
#define FREQ_STEP 0.1f /* 频率调节步长,单位:Hz */
#define FREQ_ADJUST_INTERVAL 50 /* 频率调节间隔,单位:毫秒 */

设计说明:

  • LONG_PRESS_THRESHOLD: 设置为500ms,是区分短按和长按的时间界限
  • DEBOUNCE_DELAY: 设置为20ms,有效过滤按键机械抖动
  • FREQ_MIN/MAX: 频率调节范围1Hz~5Hz,覆盖人眼可感知的闪烁频率范围
  • FREQ_STEP: 设置为0.1Hz,确保频率变化平滑无跳变
  • FREQ_ADJUST_INTERVAL: 设置为50ms,平衡调节响应速度和平滑度


3.2.2 按键状态机定义

typedef enum {
BTN_IDLE, /* 按键空闲状态 */
BTN_PRESSED, /* 按键已按下(等待判定短按/长按) */
BTN_LONG_PRESS /* 长按状态(持续调节频率) */
} btn_state_t;

状态转移说明:

  • BTN_IDLE → BTN_PRESSED: 按键按下且经过去抖延时
  • BTN_PRESSED → BTN_LONG_PRESS: 按键按下时间超过长按阈值(500ms)
  • BTN_PRESSED → BTN_IDLE: 按键释放且按下时间小于长按阈值(短按)
  • BTN_LONG_PRESS → BTN_IDLE: 按键释放(长按结束)


3.2.3 毫秒级时间基准实现

volatile uint32_t ms_ticks = 0;

void SysTick_Handler(void)
{
ms_ticks++;
}

uint32_t Get_Ticks(void)
{
return ms_ticks;
}

实现说明:

  • 使用ARM Cortex-M4内置的SysTick定时器
  • 配置为1ms中断周期,提供精确的毫秒级时间基准
  • ms_ticks为全局volatile变量,确保中断和主循环访问的一致性


3.2.4 LED闪烁定时器实现

void LED_Blink_Handler(void)
{
MXC_TMR_ClearFlags(MXC_TMR0); /* 清除定时器中断标志 */
if (led_blink_enabled) { /* 仅在闪烁使能时切换LED */
LED_Toggle(LED_RED); /* 切换红色LED状态 */
}
}

void Set_LED_Frequency(float freq)
{
if (freq < FREQ_MIN) freq = FREQ_MIN;
if (freq > FREQ_MAX) freq = FREQ_MAX;

current_freq = freq;

MXC_TMR_Stop(MXC_TMR0);
MXC_TMR_Shutdown(MXC_TMR0);

mxc_tmr_cfg_t tmr;
uint32_t periodTicks = MXC_TMR_GetPeriod(MXC_TMR0, MXC_TMR_APB_CLK, 32, (uint32_t)(freq * 2));

tmr.pres = TMR_PRES_32;
tmr.mode = TMR_MODE_CONTINUOUS;
tmr.bitMode = TMR_BIT_MODE_32;
tmr.clock = MXC_TMR_APB_CLK;
tmr.cmp_cnt = periodTicks;
tmr.pol = 0;

MXC_TMR_Init(MXC_TMR0, &tmr, 0);
MXC_TMR_EnableInt(MXC_TMR0);
MXC_TMR_Start(MXC_TMR0);
}

实现说明:

  • 使用TMR0定时器实现周期性中断
  • 定时器配置为连续模式,32位计数,预分频系数32
  • freq * 2的原因:每个定时器周期切换一次LED状态,因此1Hz闪烁需要2Hz的中断频率


3.2.5 按键回调函数实现

void PB_Callback(void *pb)
{
uint32_t now = Get_Ticks();

if (PB_Get(0)) { /* 按键按下 */
if ((now - btn_press_time) > DEBOUNCE_DELAY) {
btn_state = BTN_PRESSED;
btn_press_time = now;
last_freq_update = now;
freq_direction = 1;
printf("Button pressed\n");
}
} else { /* 按键释放 */
if (btn_state == BTN_LONG_PRESS) {
btn_state = BTN_IDLE;
printf("Long press released, freq=%.1fHz\n", (double)current_freq);
} else if (btn_state == BTN_PRESSED) {
uint32_t press_duration = now - btn_press_time;
if (press_duration < LONG_PRESS_THRESHOLD) {
led_blink_enabled = !led_blink_enabled;
if (led_blink_enabled) {
printf("LED blink ON, freq=%.1fHz\n", (double)current_freq);
} else {
LED_Off(LED_RED);
printf("LED blink OFF\n");
}
}
btn_state = BTN_IDLE;
}
}
}

实现说明:

  • 使用PB_RegisterCallbackRiseFall注册回调,同时检测上升沿和下降沿
  • 按键按下时记录时间戳,按键释放时计算按下时长判断短按/长按
  • 通过PB_Get(0)读取当前按键状态,确认按键的实际电平


3.2.6 主函数实现

int main(void)
{
printf("Button LED Frequency Control Example\n");
printf("Short press: Toggle LED blink on/off\n");
printf("Long press: Adjust blink frequency (1Hz->5Hz->1Hz)\n");

SysTick_Config(SystemCoreClock / 1000);

LED_Init();
PB_Init();

MXC_NVIC_SetVector(TMR0_IRQn, LED_Blink_Handler);
NVIC_EnableIRQ(TMR0_IRQn);

Set_LED_Frequency(current_freq);

PB_RegisterCallbackRiseFall(0, PB_Callback);

while (1) {
if (btn_state == BTN_PRESSED) {
uint32_t now = Get_Ticks();
uint32_t press_duration = now - btn_press_time;

if (press_duration >= LONG_PRESS_THRESHOLD && btn_state != BTN_LONG_PRESS) {
btn_state = BTN_LONG_PRESS;
printf("Long press detected, adjusting frequency...\n");
}
}

if (btn_state == BTN_LONG_PRESS) {
uint32_t now = Get_Ticks();

if ((now - last_freq_update) >= FREQ_ADJUST_INTERVAL) {
float new_freq = current_freq + (FREQ_STEP * freq_direction);

if (new_freq >= FREQ_MAX) {
new_freq = FREQ_MAX;
freq_direction = -1;
} else if (new_freq <= FREQ_MIN) {
new_freq = FREQ_MIN;
freq_direction = 1;
}

if (new_freq != current_freq) {
Set_LED_Frequency(new_freq);
printf("Freq: %.1fHz\r", (double)current_freq);
}

last_freq_update = now;
}
}

MXC_Delay(MXC_DELAY_MSEC(1));
}
}

实现说明:

  • 主循环采用非阻塞方式,通过状态机处理长按频率调节
  • 每1ms检查一次按键状态,确保响应实时性
  • 使用\r回车符实现频率信息的实时覆盖显示

四、功能展示


4.1 UART输出示例

系统启动后,串口输出欢迎信息:

Button LED Frequency Control Example
Short press: Toggle LED blink on/off
Long press: Adjust blink frequency (1Hz->5Hz->1Hz)


短按按键:

Button pressed
LED blink ON, freq=1.0Hz


再次短按:

Button pressed
LED blink OFF


长按按键:

Button pressed
Long press detected, adjusting frequency...
Freq: 1.1Hz
Freq: 1.2Hz
...
Freq: 5.0Hz
Freq: 4.9Hz
...
Long press released, freq=3.5Hz


4.2 LED闪烁效果

操作

LED状态

说明

系统上电

熄灭

默认关闭状态

短按按键

1Hz闪烁

开启闪烁,默认频率1Hz

长按按键

频率逐渐增加

从1Hz线性增加到5Hz

继续长按

频率逐渐降低

到达5Hz后反向降低到1Hz

再次短按

停止闪烁

关闭LED


五、总结

本项目成功实现了基于MAX32690EVKIT的按键控制LED闪烁频率功能。代码编译成功,无错误和警告,占用资源极少,可直接下载到MAX32690EVKIT开发板上运行测试。

  1. 按键短按识别: 成功识别短按事件(<500ms),实现LED闪烁开关控制
  2. 按键长按识别: 成功识别长按事件(>500ms),实现频率连续调节
  3. 频率循环调节: 频率在1Hz~5Hz之间平滑循环调节,到达边界自动反向
  4. 软件去抖: 20ms去抖延时,有效防止按键抖动误触发
  5. UART调试: 完整的调试信息输出,便于功能验证
附件下载
Funpack_5-3.zip
项目源码
团队介绍
业余电子爱好者
团队成员
鲜de芒果
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号