ZYNQ7020开发板实战:手把手教你用EMIO GPIO和AXI GPIO点亮LED(附完整Vivado/Vitis代码)
ZYNQ7020开发板实战从零掌握EMIO与AXI GPIO的LED控制技术第一次拿到ZYNQ7020开发板时面对PS与PL的复杂交互关系很多工程师都会感到无从下手。本文将带你从最基础的LED控制实验入手通过两种典型GPIO连接方式EMIO和AXI GPIO的对比实践快速建立对ZYNQ架构的直观理解。无论你是FPGA新手还是有一定经验的开发者这个实验都能帮助你掌握硬件配置、软件驱动编写和中断处理等核心技能。1. 开发环境与硬件准备在开始实验前我们需要确保开发环境正确配置。推荐使用Vivado 2020.1及以上版本配合Vitis统一开发平台。硬件方面小梅哥ZYNQ7020开发板提供了丰富的GPIO接口和LED资源非常适合本实验。必备工具清单Vivado Design Suite含VitisUSB转JTAG下载器如Digilent HS2小梅哥ZYNQ7020开发板配套电源适配器提示安装Vivado时务必勾选ZYNQ-7000器件支持包否则无法识别开发板型号。硬件连接步骤将JTAG下载器通过USB接口连接到PC开发板供电选择跳线设置为5V外部电源模式连接电源适配器并打开开发板开关确认电源指示灯PWR正常点亮2. EMIO GPIO控制实战EMIOExtended MIO是ZYNQ PS端GPIO通过PL引出的扩展接口它保留了PS GPIO的所有特性同时提供了更大的灵活性。让我们从硬件配置开始逐步完成一个完整的EMIO控制LED的流程。2.1 Vivado硬件工程配置首先在Vivado中创建新工程选择xc7z020clg400-2器件型号。添加ZYNQ7 Processing System IP核后双击进入配置界面# ZYNQ PS配置关键参数 set_property CONFIG.PCW_USE_MIO_GPIO 1 [get_bd_cells processing_system7_0] set_property CONFIG.PCW_GPIO_EMIO_GPIO_IO 2 [get_bd_cells processing_system7_0] set_property CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH 2 [get_bd_cells processing_system7_0]在Block Design中完成连接后需要创建约束文件定义物理管脚。例如将EMIO[0]连接到开发板LED1EMIO[1]连接到按键set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_io[0]}] set_property PACKAGE_PIN Y14 [get_ports {GPIO_0_tri_io[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_io[1]}] set_property PACKAGE_PIN Y13 [get_ports {GPIO_0_tri_io[1]}]2.2 Vitis软件开发生成硬件平台后在Vitis中创建应用工程。EMIO的软件操作与普通MIO GPIO完全相同只是引脚编号从54开始#include xgpio.h #include xparameters.h #define LED_PIN 54 // EMIO[0] #define BTN_PIN 55 // EMIO[1] int main() { XGpioPs_Config *Config; XGpioPs Gpio; // 初始化GPIO驱动 Config XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID); XGpioPs_CfgInitialize(Gpio, Config, Config-BaseAddr); // 设置引脚方向 XGpioPs_SetDirectionPin(Gpio, LED_PIN, 1); // 输出 XGpioPs_SetDirectionPin(Gpio, BTN_PIN, 0); // 输入 // 主循环 while(1) { if(!XGpioPs_ReadPin(Gpio, BTN_PIN)) { XGpioPs_WritePin(Gpio, LED_PIN, 1); usleep(500000); XGpioPs_WritePin(Gpio, LED_PIN, 0); usleep(500000); } } return 0; }2.3 EMIO中断实现EMIO支持独立引脚中断配置流程如下void IntrHandler(void *CallbackRef) { XGpioPs *GpioPtr (XGpioPs *)CallbackRef; XGpioPs_IntrClearPin(GpioPtr, BTN_PIN); // 中断处理逻辑 } // 在main函数中添加中断配置 XGpioPs_SetIntrTypePin(Gpio, BTN_PIN, XGPIOPS_IRQ_TYPE_EDGE_FALLING); XGpioPs_SetCallbackHandler(Gpio, (void *)Gpio, IntrHandler); XGpioPs_IntrEnablePin(Gpio, BTN_PIN);3. AXI GPIO控制实战AXI GPIO是PL端实现的软核IP通过AXI总线与PS交互。相比EMIO它更适合需要大量GPIO或特殊定制的场景。3.1 Vivado中添加AXI GPIO在Block Design中添加AXI GPIO IP核关键配置参数如下表参数名推荐值说明GPIO Width1每个通道的GPIO位数Enable Dual Channel是启用两个独立通道Interrupt Present是启用中断支持连接AXI GPIO到ZYNQ PS的GPIO接口并启用PL-PS中断connect_bd_intf_net [get_bd_intf_pins axi_gpio_0/S_AXI] [get_bd_intf_pins ps7_0_axi_periph/M00_AXI] connect_bd_net [get_bd_pins axi_gpio_0/ip2intc_irpt] [get_bd_pins xlconcat_0/In0]3.2 AXI GPIO软件驱动AXI GPIO的API与PS GPIO不同需要特别注意通道管理#include xgpio.h #define LED_CHANNEL 1 #define BTN_CHANNEL 2 int main() { XGpio Gpio; // 初始化 XGpio_Initialize(Gpio, XPAR_AXI_GPIO_0_DEVICE_ID); // 设置方向 XGpio_SetDataDirection(Gpio, LED_CHANNEL, 0x0); // 输出 XGpio_SetDataDirection(Gpio, BTN_CHANNEL, 0x1); // 输入 // 主循环 while(1) { if(!XGpio_DiscreteRead(Gpio, BTN_CHANNEL)) { XGpio_DiscreteWrite(Gpio, LED_CHANNEL, 0x1); usleep(500000); XGpio_DiscreteClear(Gpio, LED_CHANNEL, 0x1); usleep(500000); } } return 0; }3.3 AXI GPIO中断配置AXI GPIO中断以通道为单位配置流程更为复杂void GpioHandler(void *CallbackRef) { XGpio *GpioPtr (XGpio *)CallbackRef; XGpio_InterruptClear(GpioPtr, BTN_CHANNEL); // 中断处理逻辑 } // 中断初始化函数 int SetupInterrupt(XScuGic *IntcPtr, XGpio *GpioPtr) { XScuGic_Config *IntcConfig; // 初始化中断控制器 IntcConfig XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); XScuGic_CfgInitialize(IntcPtr, IntcConfig, IntcConfig-CpuBaseAddress); // 设置中断处理函数 XScuGic_Connect(IntcPtr, XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR, (Xil_ExceptionHandler)GpioHandler, GpioPtr); // 启用中断 XScuGic_Enable(IntcPtr, XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR); XGpio_InterruptEnable(GpioPtr, BTN_CHANNEL); XGpio_InterruptGlobalEnable(GpioPtr); return XST_SUCCESS; }4. EMIO与AXI GPIO深度对比通过前面的实践我们已经掌握了两种GPIO的基本用法。下表总结了它们的关键差异特性EMIO GPIOAXI GPIO物理位置PS端PL端连接方式直接连线AXI总线最大数量64个理论上无限制中断粒度单引脚级通道级(32位)时钟频率PS时钟(最高667MHz)AXI时钟(通常100-200MHz)灵活性中等高资源占用仅PS资源消耗PL逻辑资源典型应用简单控制复杂定制需求在实际项目中我通常会根据以下原则选择GPIO类型需要高性能、低延迟控制时优先选择EMIO需要大量GPIO或特殊功能时选择AXI GPIO考虑PL资源余量避免过度消耗查找表(LUT)