2. GPIO输入检测与按键消抖

任务定义

本案例在TI C2000系列MCU(以TMS320F280049C为例)上实现GPIO输入检测与按键消抖功能。目标为:配置一个GPIO引脚作为按键输入,通过软件延时消抖方式识别一次有效按键动作,并翻转一个LED输出引脚的状态。每次有效按键按下,LED状态翻转一次;按键抖动或长按不产生重复触发。

硬件连接

  • 按键接GPIO24(对应开发板上的S2按键),按下为低电平,默认上拉输入。
  • LED接GPIO23(对应开发板上的LED4),输出高电平点亮。

实现原理

按键消抖采用经典的“检测-延时-再确认”方法:首次检测到按键电平变化后,延时20ms跳过抖动期,再次读取电平状态;若与延时前状态一致,则确认电平变化有效。对于按下动作,仅在检测到电平由高变低且确认有效时,翻转LED状态。松开过程同样经过消抖处理,但不触发LED翻转,从而避免一次按下过程中因抖动产生多次触发。

代码实现

// file: gpio_key_led.c
// 目标平台:TMS320F280049C + TI C2000Ware
// 功能:GPIO按键输入消抖,翻转LED

#include "F28004x_Device.h"
#include "F28004x_Examples.h"

#define KEY_PIN     24   // 按键输入引脚
#define LED_PIN     23   // LED输出引脚
#define DEBOUNCE_MS 20   // 消抖延时(ms)

volatile uint32_t key_state;      // 当前确认的按键电平(1:高, 0:低)
volatile uint32_t led_status;     // LED状态(1:亮, 0:灭)

// 简单阻塞延时函数,系统时钟90MHz
void delay_ms(uint32_t ms)
{
    uint32_t i, j;
    for(i = 0; i < ms; i++)
        for(j = 0; j < 9000; j++);
}

void init_gpio(void)
{
    // 配置LED引脚为GPIO输出
    GPIO_SetupPinMux(LED_PIN, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(LED_PIN, GPIO_OUTPUT, GPIO_PUSH_PULL);

    // 配置按键引脚为GPIO输入,使能内部上拉
    GPIO_SetupPinMux(KEY_PIN, GPIO_MUX_CPU1, 0);
    GPIO_SetupPinOptions(KEY_PIN, GPIO_INPUT, GPIO_PULL_UP);

    // 初始状态:LED灭,按键电平读取为高
    led_status = 0;
    GPIO_WritePin(LED_PIN, led_status);
    key_state = GPIO_ReadPin(KEY_PIN);
}

void main(void)
{
    // 初始化设备与GPIO
    InitSysCtrl();
    InitGpio();
    init_gpio();

    // 关闭中断(本案例不使用中断)
    DINT;

    while(1)
    {
        uint32_t raw_level = GPIO_ReadPin(KEY_PIN);

        // 检测到电平变化,进入消抖确认
        if(raw_level != key_state)
        {
            delay_ms(DEBOUNCE_MS);          // 等待抖动结束
            uint32_t confirm_level = GPIO_ReadPin(KEY_PIN);

            // 延时后电平与变化方向一致,确认有效
            if(confirm_level == raw_level)
            {
                // 仅在按下沿(高→低)时翻转LED
                if(key_state == 1 && confirm_level == 0)
                {
                    led_status ^= 1;        // 翻转LED状态
                    GPIO_WritePin(LED_PIN, led_status);
                }
                key_state = confirm_level;  // 更新确认状态
            }
            // 若不一致,说明是抖动,不更新key_state
        }
    }
}

工程配置与编译

  1. 在CCS中新建工程,芯片选择TMS320F280049C。
  2. 添加本案例的gpio_key_led.c文件,并包含C2000Ware驱动库路径。
  3. 链接F28004x_Device.h与F28004x_Examples.h对应的头文件目录。
  4. 编译工程,生成.out文件。

运行与验证

将编译生成的.out文件通过CCS的Debug功能烧录至开发板并运行。验证步骤如下:

  1. 观察开发板LED4(GPIO23)初始为熄灭状态。
  2. 快速按下并松开按键S2(GPIO24),LED4应变为点亮状态。
  3. 再次快速按下并松开按键,LED4应熄灭。
  4. 快速连续按动按键(模拟抖动),LED状态应只翻转一次,不会出现多次翻转。
  5. 长按按键不松开,LED状态只翻转一次,不会重复触发。

判定标准:每次按下并松开按键,LED状态恰好翻转一次;快速抖动或长按不会导致LED状态多次翻转,即消抖逻辑正确。

关键点说明

  • 延时消抖时间20ms可根据实际按键机械特性调整,范围通常为10~50ms。
  • 本案例采用轮询方式,不占用中断资源,适合教学演示;实际产品中可改用定时器中断实现非阻塞消抖。
  • GPIO_SetupPinOptions中GPIO_PULL_UP使能内部上拉,确保按键未按下时引脚为确定高电平。
GPIO按键消抖状态检测流程 GPIO24 按键输入 按下=低电平 读取raw_level 与key_state比较 电平变化? raw≠key_state 否 继续轮询 是 延时20ms 等待抖动结束 读取confirm_level 与raw_level比较 确认有效? confirm==raw 是 按下沿? 高→低 翻转LED 否 不更新状态 更新key_state 流程:读取→消抖→确认→按下沿→翻转LED