2. 按键输入检测

任务目标

在Zynq平台上通过GPIO读取按键输入状态,控制LED的亮灭。按下按键时LED点亮,松开时LED熄灭,以此掌握GPIO输入模式配置与轮询检测方法。

硬件连接

  • 按键一端连接GPIO引脚(本例使用MIO引脚,内部上拉),另一端接地
  • LED正极通过限流电阻连接GPIO引脚,负极接地
  • 按键按下时引脚读到低电平(0),松开时读到高电平(1)

实现原理

Zynq的GPIO控制器通过MIO(多功能IO)引脚访问外部设备。本案例将按键接入MIO引脚并配置为输入方向,LED接入另一MIO引脚并配置为输出方向。主循环中持续读取按键引脚电平,根据电平状态决定LED引脚的输出值。由于按键按下时引脚为低电平,因此当读到0时点亮LED(输出1),读到1时熄灭LED(输出0)。

完整代码


#include "xgpio.h"
#include "xparameters.h"
#include "sleep.h"

#define GPIO_DEVICE_ID  XPAR_XGPIO_0_DEVICE_ID
#define KEY_CHANNEL     1   // 按键接在通道1
#define LED_CHANNEL     2   // LED接在通道2
#define KEY_PIN_MASK    0x01 // 使用bit0
#define LED_PIN_MASK    0x01 // 使用bit0

static XGpio gpio;

int main(void)
{
    int status;
    u32 key_value;

    // 初始化GPIO实例
    status = XGpio_Initialize(&gpio, GPIO_DEVICE_ID);
    if (status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    // 配置按键引脚为输入方向
    XGpio_SetDataDirection(&gpio, KEY_CHANNEL, KEY_PIN_MASK);

    // 配置LED引脚为输出方向
    XGpio_SetDataDirection(&gpio, LED_CHANNEL, 0x0);

    // 初始熄灭LED
    XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0x0);

    while (1) {
        // 轮询读取按键状态
        key_value = XGpio_DiscreteRead(&gpio, KEY_CHANNEL);

        // 按键按下时读到0,点亮LED;松开时读到1,熄灭LED
        if ((key_value & KEY_PIN_MASK) == 0) {
            XGpio_DiscreteWrite(&gpio, LED_CHANNEL, LED_PIN_MASK);
        } else {
            XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0x0);
        }

        usleep(10000); // 10ms延时,消除抖动影响
    }

    return 0;
}

硬件配置说明

在Vivado中创建Block Design时,添加Zynq PS核并启用MIO引脚。将按键连接到MIO的bit0(对应GPIO通道1的bit0),LED连接到MIO的bit8(对应GPIO通道2的bit0)。在Xilinx SDK中,xparameters.h会根据硬件配置自动生成XPAR_XGPIO_0_DEVICE_ID等参数,无需手动修改。

运行与验证

  1. 在Vivado中完成硬件设计并导出到SDK
  2. 在SDK中新建应用工程,将上述代码替换默认的helloworld.c
  3. 连接开发板,下载比特流并运行程序
  4. 验证标准:按下按键时LED立即点亮,松开后LED熄灭,循环响应无延迟

常见问题

  • 按键无响应:检查MIO引脚编号是否与代码中通道/bit对应,确认按键接线是否正确(一端接MIO,另一端接地)
  • LED常亮或常灭:检查LED引脚方向配置是否正确,确认XGpio_SetDataDirection参数中通道号与硬件连接一致
  • 电平逻辑相反:若按键按下时读到高电平,说明按键接法为接VCC而非接地,需反转判断条件