1. LED流水灯控制
任务目标
在Zynq-7000系列开发板上,通过PS(Processing System)端的MIO GPIO或EMIO GPIO控制4个LED实现流水灯效果。本案例使用纯PS方案,不涉及PL(可编程逻辑)端逻辑设计,帮助掌握GPIO输出控制、延时函数和寄存器配置的基本方法。
硬件连接与前置条件
- 开发板:Zynq-7020/7010(如ZedBoard、正点原子ZYNQ开发板)
- 4个LED分别连接至PS端MIO引脚(具体引脚号因板卡而异,本案例以MIO0~MIO3为例,实际使用时需根据板卡原理图修改)
- Vivado 2018.3+ / Vitis IDE,已创建Zynq最小系统(仅PS使能,无需PL配置)
- 串口终端(115200波特率)用于观察运行状态
核心实现代码
以下代码在Vitis中作为独立应用程序运行,通过访问Zynq GPIO控制器寄存器实现LED流水灯控制:
#include <stdio.h>
#include "xil_io.h"
#include "sleep.h"
#include "xparameters.h"
// GPIO寄存器地址映射(Zynq-7000 PS GPIO基地址)
#define GPIO_BASE_ADDR 0xE000A000
// 寄存器偏移
#define DATA_OFFSET 0x00 // 数据寄存器(低16位对应MIO0~15)
#define DIRM_OFFSET 0x204 // 方向控制寄存器(1=输出)
#define OEN_OFFSET 0x208 // 输出使能寄存器(1=使能输出)
// 板卡LED连接引脚(根据实际硬件修改)
#define LED0_PIN 0 // MIO0
#define LED1_PIN 1 // MIO1
#define LED2_PIN 2 // MIO2
#define LED3_PIN 3 // MIO3
// 将4个LED对应引脚置为输出模式
void GPIO_Init(void) {
u32 dir_reg, oen_reg;
// 读取当前方向寄存器,将LED引脚对应位设为1(输出)
dir_reg = Xil_In32(GPIO_BASE_ADDR + DIRM_OFFSET);
dir_reg |= (1 << LED0_PIN) | (1 << LED1_PIN) |
(1 << LED2_PIN) | (1 << LED3_PIN);
Xil_Out32(GPIO_BASE_ADDR + DIRM_OFFSET, dir_reg);
// 读取输出使能寄存器,将LED引脚对应位设为1(使能输出)
oen_reg = Xil_In32(GPIO_BASE_ADDR + OEN_OFFSET);
oen_reg |= (1 << LED0_PIN) | (1 << LED1_PIN) |
(1 << LED2_PIN) | (1 << LED3_PIN);
Xil_Out32(GPIO_BASE_ADDR + OEN_OFFSET, oen_reg);
}
// 点亮指定引脚对应的LED(低电平点亮,根据板卡极性调整)
void LED_On(int pin) {
u32 data_reg = Xil_In32(GPIO_BASE_ADDR + DATA_OFFSET);
data_reg |= (1 << pin); // 置1点亮(若板卡为低电平点亮则改为置0)
Xil_Out32(GPIO_BASE_ADDR + DATA_OFFSET, data_reg);
}
// 熄灭指定引脚对应的LED
void LED_Off(int pin) {
u32 data_reg = Xil_In32(GPIO_BASE_ADDR + DATA_OFFSET);
data_reg &= ~(1 << pin); // 置0熄灭
Xil_Out32(GPIO_BASE_ADDR + DATA_OFFSET, data_reg);
}
int main(void) {
int led_pins[4] = {LED0_PIN, LED1_PIN, LED2_PIN, LED3_PIN};
int i;
printf("LED流水灯实验开始...\r\n");
GPIO_Init();
while (1) {
// 依次点亮每个LED,形成流水效果
for (i = 0; i < 4; i++) {
LED_On(led_pins[i]);
usleep(200000); // 延时200ms
LED_Off(led_pins[i]);
}
}
return 0;
}
运行与验证
- 在Vitis中新建Application Project,平台选择已导出的硬件平台(包含Zynq PS配置)
- 将上述代码替换生成的
helloworld.c,保存并编译 - 连接开发板JTAG和串口,下载程序运行
- 观察4个LED是否按顺序依次点亮并熄灭,形成循环流水效果
通过条件:LED0→LED1→LED2→LED3依次点亮,每个LED亮200ms后熄灭,循环往复;串口终端输出“LED流水灯实验开始...”。若LED不亮,检查引脚号是否与板卡原理图一致,以及LED极性(高/低电平点亮)是否需要反转LED_On/LED_Off中的置位逻辑。
常见问题
- LED不亮:确认MIO引脚号正确,且方向寄存器和输出使能寄存器已正确配置;检查LED极性,部分板卡需要低电平点亮
- 编译报错:确认已包含
xil_io.h和xparameters.h头文件路径,Vitis BSP已正确生成 - 流水速度过快/过慢:调整
usleep()参数值(单位微秒)