1. LED流水灯控制
任务目标
在Zynq开发板上驱动4个LED实现流水灯效果,掌握PS端MIO/EMIO GPIO作为输出控制的基本配置与操作方法。本案例以Xilinx Zynq-7000系列(如XC7Z020)为硬件平台,通过Vivado搭建最小硬件系统,使用Vitis编写C程序完成GPIO输出控制。
硬件设计(Vivado Block Design)
在Vivado中创建Block Design,添加Zynq7 Processing System IP。按以下要点配置,其余保持默认:
- PS-PL接口:不勾选任何PL外设(本案例不使用PL逻辑)
- MIO配置:在Peripheral I/O Pins中取消勾选UART、USB、SD等所有外设,仅保留GPIO MIO(默认勾选)
- 时钟:保留默认CPU_6x4x时钟配置(无需修改)
完成配置后,右键Block Design中的processing_system7_0,选择Create HDL Wrapper,生成顶层文件。添加约束文件(XDC),仅需约束系统时钟引脚(若使用开发板默认时钟可跳过)。综合、实现并生成比特流。
硬件导出与SDK设置
- File → Export Hardware,勾选Include bitstream,导出到工程目录
- Launch Vitis,创建新的Application Project
- 平台选择导出的硬件平台文件(.xsa),创建空应用(Empty Application)
- 添加以下main.c源文件
关键完整代码(main.c)
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
#define LED_PIN_MASK 0xF0 // MIO[7:4] 对应4个LED
static XGpioPs Gpio;
int main(void)
{
XGpioPs_Config *Config;
int Status;
u32 LedValue = 0x10; // 初始点亮LED0(MIO4)
// 初始化GPIO控制器
Config = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
if (Config == NULL) return -1;
Status = XGpioPs_CfgInitialize(&Gpio, Config, Config->BaseAddr);
if (Status != XST_SUCCESS) return -1;
// 将MIO[7:4]设置为输出方向
XGpioPs_SetDirection(&Gpio, LED_PIN_MASK, LED_PIN_MASK);
// 使能MIO[7:4]输出
XGpioPs_SetOutputEnable(&Gpio, LED_PIN_MASK, LED_PIN_MASK);
while (1) {
// 将当前LED值写入GPIO输出
XGpioPs_Write(&Gpio, LED_PIN_MASK, LedValue);
usleep(200000); // 延时200ms
// 循环左移,实现流水灯效果
if (LedValue == 0x80) {
LedValue = 0x10; // 回到第一个LED
} else {
LedValue <<= 1;
}
}
return 0;
}
硬件连接说明
上述代码使用MIO[7:4]驱动4个LED。若你的开发板LED连接在MIO其他引脚或EMIO上,需修改LED_PIN_MASK和初始值LedValue。例如:
- LED连接在MIO[3:0]:
LED_PIN_MASK = 0x0F,初始值LedValue = 0x01 - LED连接在EMIO(PL侧):需在Vivado中勾选EMIO GPIO并分配引脚,代码中改用
XGpioPs_Write的Bank参数为1(EMIO bank),掩码和初始值需对应实际引脚编号
运行与验证
- 连接开发板电源和JTAG下载器
- 在Vitis中:Xilinx → Program FPGA,加载比特流
- 右键工程 → Run As → Launch on Hardware(System Debugger)
- 通过标准:4个LED按顺序依次点亮并循环(LED0→LED1→LED2→LED3→LED0…),每个LED点亮约200ms,肉眼可清晰分辨流水效果
常见问题
- LED不亮:检查MIO引脚掩码是否与硬件连接一致;确认已执行Program FPGA加载比特流
- 编译报错:确认Vitis平台选择的是导出的.xsa文件,且BSP已正确生成
- 流水速度异常:
usleep参数单位为微秒,200000即200ms;若系统时钟配置不同,延时精度会受影响,但不影响功能验证