硬件平台说明:本备考文档中所有 12 道实验题目及 2026.6.15 期末考试题均基于General_Platform(即CPU_INT_TIMER平台)开发。General_Platform/CPU_INT_TIMER不含串行通信模块(无 UART、无 SPI),是涉及全部微机原理实验考试题目都通用的硬件平台。其硬件配置为:AXI GPIO×3(开关+LED、数码管位选+段码、按键)+ AXI Timer + AXI INTC,采用普通中断(Normal Interrupt)方式驱动。详细说明见CPU_INT_TIMER/readme.md。
| 题号 | 考查内容 | 涉及外设 | 核心功能 |
|---|---|---|---|
| 1 | 按键编码字符显示(全部显示) | 开关、LED、数码管、按键 | LED = 开关值(直通映射) 8个数码管全部显示同一按键字符(C/U/L/D/R) |
| 2 | 按键编码字符显示(依次显示) | 开关、LED、数码管、按键 | LED = 开关值(直通映射) 数码管依次逐个显示按键字符(循环移位) |
| 3 | 进制转换(二进制/十六进制/十进制) | 开关、数码管、按键 | BC → 二进制显示开关值的低4位 BU → 十六进制显示开关值的低8位 BL → 十进制显示开关值的低8位(逐位分解查段码表) |
| 4 | 程序控制方式(无中断轮询) | 开关、LED、按键 | 按键读取两组开关值 做加法/乘法 → LED 显示结果(C=加法,R=乘法) |
| 5 | 十六进制显示+定时器递增 | 开关、数码管、按键、定时器 | C → 十六进制显示开关值的低8位(右2位数码管) L → 每秒+1递增(0→255→0循环),由T1定时器驱动 |
| 6 | 数码管左右移位 | 开关、数码管、按键 | C → 显示开关值的最右4位到最右侧数码管 L → 循环左移(左端移回右端) R → 循环右移(右端移回左端) |
| 7 | 带符号二进制→十进制(原码/反码/补码) | 开关、数码管、按键 | 左4位数码管显示二进制 C → 带符号十进制(正数直接=值,负数=16-值) L → 切换显示取反/补码(符号位不变,低3位处理) |
| 8 | 数码管滚动显示(无按键控制) | 数码管、定时器 | 每秒滚动显示 "3456"(循环左移),由T1定时器驱动 |
| 9 | 综合系统(流水灯变速/移位/反码/符号十进制滚动) | 开关、LED、数码管、按键、定时器 | C → 流水灯变速(1s→0.5s→0.25s循环切换) U → LED 整体左移/右移切换 L → LED 循环左移/右移(单灯循环) R → 开关值二进制/按位取反切换显示 D → 符号十进制滚动(带负号处理,数码管滚动) |
| 10 | 数码管自动左右滚动 | 开关、数码管、按键、定时器 | C → 十六进制显示开关值的低8位(右2位数码管) R → 切换左移/右移方向(自动滚动,1Hz) |
| 11 | LED映射+循环右移 | 开关、LED、按键 | C → 低8位开关值 映射到 LED高8位(低8位LED保持) R → LED 循环右移(16位整体旋转) |
| 12 | 数码管滚动显示+按键控制方向 | 数码管、按键、定时器 | 显示 "3456" C → 开始滚动(由T1定时器驱动) L → 左移(循环) R → 右移(循环) |
| 2026.6.15 | LED中断控制+自动循环移位 | LED、按键、定时器 | BTNC → LED低8位显示 1111 0000(其余熄灭) BTNL→三态循环:1Hz自动左移/1Hz自动右移/停止显示当前值 要求:普通中断方式实现 |
2.1 必需头文件
#include "xil_io.h" // Xil_In8/16/32, Xil_Out8/16/32
#include "stdio.h" // 标准输入输出
#include "xintc_l.h" // 中断控制器(低层)
#include "xtmrctr_l.h" // 定时器(低层)
#include "xtmrctr.h" // 定时器(高层,含常量定义)
#include "xgpio_l.h" // GPIO(低层)
#include "xgpio.h" // GPIO(高层,含常量定义)
#include "xil_printf.h" // xil_printf
#include "xparameters.h" // 参数定义(XPAR_... 地址常量)
#include "mb_interface.h" // MicroBlaze接口(中断使能等)
2.2 外设基地址(由 xparameters.h 提供)
// GPIO0: 独立开关(16位) CH1 + LED灯(16位) CH2
#define GPIO0_BASE XPAR_AXI_GPIO_0_BASEADDR
// GPIO1: 数码管位选(8位) CH1 + 数码管段码(8位) CH2
#define GPIO1_BASE XPAR_AXI_GPIO_1_BASEADDR
// GPIO2: 独立按键(5位) CH1
#define GPIO2_BASE XPAR_AXI_GPIO_2_BASEADDR
// Timer0: 双通道定时器(T0=通道0, T1=通道1)
#define TIMER0_BASE XPAR_AXI_TIMER_0_BASEADDR
// Interrupt Controller
#define INTC_BASE XPAR_AXI_INTC_0_BASEADDR
2.3 GPIO寄存器偏移
#define XGPIO_TRI_OFFSET 0x00 // 方向寄存器(1=输入, 0=输出)
#define XGPIO_DATA_OFFSET 0x08 // 数据寄存器(CH1)
#define XGPIO_TRI2_OFFSET 0x04 // 方向寄存器(CH2)
#define XGPIO_DATA2_OFFSET 0x0C // 数据寄存器(CH2)
#define XGPIO_ISR_OFFSET 0x10 // 中断状态寄存器
#define XGPIO_IER_OFFSET 0x14 // 中断使能寄存器
#define XGPIO_GIE_OFFSET 0x18 // 全局中断使能
#define XGPIO_IR_CH1_MASK 0x01 // 通道1中断屏蔽
#define XGPIO_GIE_GINTR_ENABLE_MASK 0x80000000 // 全局中断使能位
2.4 定时器寄存器偏移
#define XTC_TCSR_OFFSET 0x00 // 控制和状态寄存器
#define XTC_TLR_OFFSET 0x04 // 装载寄存器
#define XTC_TCR_OFFSET 0x08 // 计数器寄存器
// T1(Timer1) = 通道1,地址偏移0x10
#define XTC_TIMER_COUNTER_OFFSET 0x10
// TCSR 控制/状态位
#define XTC_CSR_ENABLE_TMR_MASK 0x00000001 // 使能定时器
#define XTC_CSR_ENABLE_INT_MASK 0x00000010 // 使能中断
#define XTC_CSR_AUTO_RELOAD_MASK 0x00000002 // 自动重载
#define XTC_CSR_DOWN_COUNT_MASK 0x00000008 // 减计数
#define XTC_CSR_INT_OCCURED_MASK 0x00000020 // 中断发生标志
#define XTC_CSR_LOAD_MASK 0x00000040 // 加载初值
2.5 中断控制器寄存器偏移
#define XIN_IER_OFFSET 0x08 // 中断使能寄存器
#define XIN_IAR_OFFSET 0x0C // 中断应答寄存器
#define XIN_MER_OFFSET 0x1C // 主使能寄存器
#define XIN_ISR_OFFSET 0x00 // 中断状态寄存器
#define XIN_INT_MASTER_ENABLE_MASK 0x00000001 // 主使能
#define XIN_INT_HARDWARE_ENABLE_MASK 0x00000002 // 硬件使能
3.1 十六进制段码表(共阳极)
/* 共阳极数码管段码:dp g f e d c b a,0=亮、1=灭 */
char segtable_hex[16] = {
0xc0, // 0
0xf9, // 1
0xa4, // 2
0xb0, // 3
0x99, // 4
0x92, // 5
0x82, // 6
0xf8, // 7
0x80, // 8
0x90, // 9
0x88, // A
0x83, // B
0xc6, // C
0xa1, // D
0x86, // E
0x8e // F
};
3.2 特殊段码定义
#define SEG_C 0xC6 // 大写C
#define SEG_U 0xC1 // 大写U
#define SEG_L 0xC7 // 大写L
#define SEG_D 0x86 // 小写d
#define SEG_R 0x86 // 小写r
#define SEG_MINUS 0xBF // 负号 "-"(仅g段亮)
说明: 段码0xBF的位排列为 1 0 1 1 1 1 1 1,dp=1(灭) g=0(亮) f=1 e=1 d=1 c=1 b=1 a=1 → 仅中间横线(g段)亮起,显示负号。
3.3 段码缓冲区 segcode[8]
/* segcode[0~7]:数码管显示缓冲区,对应最左边~最右边8个数码管的段码。0xff=全灭 */
char segcode[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3.4 位选码表 poscode[8]
/* poscode[0~7]:数码管位选码,低电平选中对应位 */
short poscode[8] = {0x7F, 0xBF, 0xDF, 0xEF, 0xf7, 0xfb, 0xfd, 0xfe};
| poscode[i] | 对应位 | 二进制 | 说明 |
|---|---|---|---|
| poscode[0] | 第1位 | 0111 1111 | 最左 |
| poscode[1] | 第2位 | 1011 1111 | |
| poscode[2] | 第3位 | 1101 1111 | |
| poscode[3] | 第4位 | 1110 1111 | |
| poscode[4] | 第5位 | 1111 0111 | |
| poscode[5] | 第6位 | 1111 1011 | |
| poscode[6] | 第7位 | 1111 1101 | |
| poscode[7] | 第8位 | 1111 1110 | 最右 |
/* GPIO2_CH1 低5位对应5个独立按键 */
#define BTNC_MASK 0x01 // 中间按键 C(bit0)
#define BTNU_MASK 0x02 // 上键 U(bit1)
#define BTNL_MASK 0x04 // 左键 L(bit2)
#define BTNR_MASK 0x08 // 右键 R(bit3)
#define BTND_MASK 0x10 // 下键 D(bit4)
/* 中断源编号(对应中断控制器连接顺序) */
#define GPIO_2_IRQ_MASK 0x2 // GPIO2(按键)中断掩码
#define TIMER_0_IRQ_MASK 0x4 // Timer0(T0+T1共用同一根中断线)中断掩码
注意: GPIO2是中断源1(bit1=0x2),Timer0是中断源2(bit2=0x4)。中断源编号取决于硬件连接,不同工程可能不同。
6.1 定时器重装载值
// T0:数码管动态扫描(~10μs/位)
#define RESET_VALUE0 1000 - 2 // 100MHz → 100kHz → 10μs
// T1:基础周期
#define RESET_VALUE1 100000000 - 2 // 100MHz → 1s
#define T1_TICK_halfS 50000000 - 2 // 0.5s
#define T1_TICK_quarterS 25000000 - 2 // 0.25s
计算公式: 重装载值 = 时钟频率 × 目标周期 - 2
- 时钟频率 = 100MHz = 100,000,000 Hz
- 目标周期10μs:100M × 10μs - 2 = 1000 - 2
- 目标周期1s:100M × 1s - 2 = 100M - 2
- 目标周期0.5s:100M × 0.5s - 2 = 50M - 2
6.2 两个定时器的分工
| 定时器 | 用途 | 中断频率 | 功能 |
|---|---|---|---|
| T0 | 数码管动态扫描 | ~10μs/位(100kHz) | 逐位刷新8个数码管,利用视觉暂留稳定显示 |
| T1 | 周期控制(滚动/递增/流水灯) | 1s/0.5s/0.25s | 驱动数码管滚动显示、LED流水灯步进、计数器递增等 |
6.3 定时器初始化代码模板
// ===== T0初始化 =====
// 1) 关闭定时器
Xil_Out32(TIMER0_BASE + XTC_TCSR_OFFSET,
Xil_In32(TIMER0_BASE + XTC_TCSR_OFFSET) & ~XTC_CSR_ENABLE_TMR_MASK);
// 2) 设置重装载值
Xil_Out32(TIMER0_BASE + XTC_TLR_OFFSET, RESET_VALUE0);
// 3) 加载初值
Xil_Out32(TIMER0_BASE + XTC_TCSR_OFFSET,
Xil_In32(TIMER0_BASE + XTC_TCSR_OFFSET) | XTC_CSR_LOAD_MASK);
// 4) 配置并启动:中断使能 | 自动重载 | 减计数 | 清中断标志 | 使能
Xil_Out32(TIMER0_BASE + XTC_TCSR_OFFSET,
(Xil_In32(TIMER0_BASE + XTC_TCSR_OFFSET) & ~XTC_CSR_LOAD_MASK) |
XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK |
XTC_CSR_DOWN_COUNT_MASK | XTC_CSR_INT_OCCURED_MASK |
XTC_CSR_ENABLE_TMR_MASK);
// ===== T1初始化 =====
// 注:T1寄存器地址 = T0基址 + XTC_TIMER_COUNTER_OFFSET(0x10)
// 1) 关闭
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET,
Xil_In32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET) & ~XTC_CSR_ENABLE_TMR_MASK);
// 2) 设置重装载值
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TLR_OFFSET, RESET_VALUE1);
// 3) 加载
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET,
Xil_In32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET) | XTC_CSR_LOAD_MASK);
// 4) 配置并启动
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET,
(Xil_In32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET) & ~XTC_CSR_LOAD_MASK) |
XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK |
XTC_CSR_DOWN_COUNT_MASK | XTC_CSR_INT_OCCURED_MASK |
XTC_CSR_ENABLE_TMR_MASK);
| 类型 | 常用场景 | 示例 |
|---|---|---|
char |
段码值、按键值、低4位开关值、8位计数值 | char segcode[8], char button |
unsigned char |
无符号8位值 | unsigned char sw_val |
short |
位选码(16位) | short poscode[8] |
unsigned short |
LED状态、16位开关值 | unsigned short led_val |
int |
模式变量、计数器、循环变量、定时器状态 | int mode, int pos, int count |
注意: 在MicroBlaze中,char默认是signed char,范围-128~127;当处理0~255范围时建议用unsigned char。
8.1 中断服务函数声明
void My_ISR() __attribute__ ((interrupt_handler));
8.2 中断初始化步骤
microblaze_enable_interrupts()8.3 主中断服务函数框架
void My_ISR()
{
int status = Xil_In32(INTC_BASE + XIN_ISR_OFFSET);
if ((status & GPIO_2_IRQ_MASK) == GPIO_2_IRQ_MASK)
button_handle();
if ((status & TIMER_0_IRQ_MASK) == TIMER_0_IRQ_MASK)
timer_handle();
Xil_Out32(INTC_BASE + XIN_IAR_OFFSET, status); // 应答中断
}
8.4 定时器中断分发
void timer_handle(void)
{
int timer_status;
// 检查T0是否触发中断
timer_status = Xil_In32(TIMER0_BASE + XTC_TCSR_OFFSET);
if ((timer_status & XTC_CSR_INT_OCCURED_MASK) == XTC_CSR_INT_OCCURED_MASK)
timer0_handle();
// 检查T1是否触发中断(用if,不用else if,因为可能同时触发)
timer_status = Xil_In32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET);
if ((timer_status & XTC_CSR_INT_OCCURED_MASK) == XTC_CSR_INT_OCCURED_MASK)
timer1_handle();
}
8.5 T0中断处理(数码管动态扫描)
void timer0_handle(void)
{
// 消影
Xil_Out8(GPIO1_BASE + XGPIO_DATA_OFFSET, 0xff);
Xil_Out8(GPIO1_BASE + XGPIO_DATA2_OFFSET, 0xff);
// 输出位码和段码
Xil_Out8(GPIO1_BASE + XGPIO_DATA_OFFSET, poscode[pos]);
Xil_Out8(GPIO1_BASE + XGPIO_DATA2_OFFSET, segcode[pos]);
// 更新扫描位置
pos++;
if (pos == 8) pos = 0;
// 清除中断标志
Xil_Out32(TIMER0_BASE + XTC_TCSR_OFFSET,
Xil_In32(TIMER0_BASE + XTC_TCSR_OFFSET) | XTC_CSR_INT_OCCURED_MASK);
}
8.6 按键中断处理框架
void button_handle(void)
{
char button = Xil_In8(GPIO2_BASE + XGPIO_DATA_OFFSET) & 0x1f;
// 按键松开:清除中断后返回
if (button == 0) {
Xil_Out32(GPIO2_BASE + XGPIO_ISR_OFFSET,
Xil_In32(GPIO2_BASE + XGPIO_ISR_OFFSET));
return;
}
// 按优先级判断:C → U → L → R → D
if (button & BTNC_MASK) {
// BTNC功能
}
else if (button & BTNU_MASK) {
// BTNU功能
}
else if (button & BTNL_MASK) {
// BTNL功能
}
else if (button & BTNR_MASK) {
// BTNR功能
}
else if (button & BTND_MASK) {
// BTND功能
}
// 清除中断标志
Xil_Out32(GPIO2_BASE + XGPIO_ISR_OFFSET,
Xil_In32(GPIO2_BASE + XGPIO_ISR_OFFSET));
}
从开关值中提取指定位,每个位显示"0"(0xc0)或"1"(0xf9)到对应数码管。
// 方法:遍历4位,检查每位是否为1
char low4 = Xil_In8(GPIO0_BASE + XGPIO_DATA_OFFSET) & 0xf;
for (int i = 0; i < 4; i++) {
if (low4 & (0x8 >> i)) // 检查第i位(从高位开始)
segcode[i] = segtable_hex[1]; // 显示"1"
else
segcode[i] = segtable_hex[0]; // 显示"0"
}
将开关值的低8位或低4位直接作为索引查段码表。
// 低4位十六进制显示到最右1位
char low4 = Xil_In8(GPIO0_BASE + XGPIO_DATA_OFFSET) & 0xf;
segcode[7] = segtable_hex[low4];
// 低8位十六进制显示到右2位
char low8 = Xil_In8(GPIO0_BASE + XGPIO_DATA_OFFSET);
segcode[6] = segtable_hex[(low8 >> 4) & 0xf]; // 高4位
segcode[7] = segtable_hex[low8 & 0xf]; // 低4位
// 16位十六进制显示到高4位
unsigned short sw = Xil_In16(GPIO0_BASE + XGPIO_DATA_OFFSET);
for (int i = 0; i < 4; i++) {
segcode[i] = segtable_hex[(sw >> (12 - 4*i)) & 0xf];
}
将数值按位分解,每位查段码表显示。
// 方法:从高位到低位逐位提取
unsigned short val = ...; // 待显示数值
for (int i = 0; i < 5; i++) {
int digit = val % 10;
segcode[7 - i] = segtable_hex[digit]; // 从最右开始
val /= 10;
}
char temp = segcode[0]; // 保存最左端
for (int i = 0; i < 7; i++) {
segcode[i] = segcode[i + 1]; // 后一位覆盖前一位
}
segcode[7] = temp; // 原最左端到最右端
char temp = segcode[7]; // 保存最右端
for (int i = 0; i < 7; i++) {
segcode[7 - i] = segcode[6 - i]; // 前一位覆盖后一位(从右向左遍历)
}
segcode[0] = temp; // 原最右端到最左端
// 方法:切换T1的重装载值
// 1s模式
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TLR_OFFSET, T1_BASE_TICK);
// 0.5s模式
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TLR_OFFSET, T1_TICK_halfS);
// 0.25s模式
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TLR_OFFSET, T1_TICK_quarterS);
使用计数器实现循环切换:
static int speed_count = 0;
if (speed_count == 0) {
Xil_Out32(..., T1_BASE_TICK); // 1s
speed_count = 1;
}
else if (speed_count == 1) {
Xil_Out32(..., T1_TICK_halfS); // 0.5s
speed_count = 2;
}
else {
Xil_Out32(..., T1_TICK_quarterS); // 0.25s
speed_count = 0;
}
// 题目7:符号位(bit3)不取反,低3位取反
char low4 = ...; // 读取低4位
char sign = low4 & 0x8; // 提取符号位
char number = low4 & 0x7; // 提取数值部分(低3位)
char inverted = sign | (~number & 0x7); // 符号位不变,低3位取反
// 补码 = 取反 + 1(统一处理低3位)
char twos_comp = sign | ((~number + 1) & 0x7);
T1中断中驱动LED流水灯步进,通过按键切换T1速度。
void timer1_handle(void) {
if (mode == MODE_C) {
ledbits++;
if (ledbits == 16) ledbits = 0;
Xil_Out16(GPIO0_BASE + XGPIO_DATA2_OFFSET, 1 << ledbits);
}
}
// 循环左移(16位)
unsigned short val = led_val;
val = ((val << 1) & 0xFFFF) | ((val >> 15) & 0x0001);
// 循环右移(16位)
unsigned short lsb = led_val & 0x0001;
led_val = (led_val >> 1) | (lsb << 15);
题目要求: 使用普通中断方式,BTNC按下后LED低8位显示1111 0000(其余熄灭);BTNL三态循环切换:1Hz自动左移→1Hz自动右移→停止显示当前值。移位时整体8位循环,最左边移出回到最低位,最右边移出回到最高位。
核心变量: Led_current(8位变量,保存LED低8位当前值)
// 全局变量
unsigned char Led_current; // LED低8位当前值(LED显示用)
unsigned char shift_mode; // 移位模式:0=停止, 1=左移, 2=右移
// BTNC中断处理:设置固定值 1111 0000 = 0xF0
Led_current = 0xF0;
shift_mode = 0; // 停止自动移位
Xil_Out16(GPIO0_BASE + XGPIO_DATA2_OFFSET, (unsigned short)Led_current);
// BTNL中断处理:三态循环
// count%3 决定模式
// 0 → 左移模式
// 1 → 右移模式
// 2 → 停止模式(显示当前值)
static int btnl_count = 0;
btnl_count = (btnl_count + 1) % 3;
if (btnl_count == 0) {
shift_mode = 1; // 左移
} else if (btnl_count == 1) {
shift_mode = 2; // 右移
} else {
shift_mode = 0; // 停止
}
// T1定时器中断(1Hz):根据shift_mode自动移位
void timer1_handle(void)
{
if (shift_mode == 1) {
// 循环左移:左移1位,最高位移到最低位
Led_current = (Led_current << 1) | ((Led_current & 0x80) >> 7);
Xil_Out16(GPIO0_BASE + XGPIO_DATA2_OFFSET, (unsigned short)Led_current);
}
else if (shift_mode == 2) {
// 循环右移:右移1位,最低位移到最高位
Led_current = (Led_current >> 1) | ((Led_current & 0x01) << 7);
Xil_Out16(GPIO0_BASE + XGPIO_DATA2_OFFSET, (unsigned short)Led_current);
}
// shift_mode == 0 时不操作(停止,保持当前值)
// 清除T1中断标志
Xil_Out32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET,
Xil_In32(TIMER0_BASE + XTC_TIMER_COUNTER_OFFSET + XTC_TCSR_OFFSET) | XTC_CSR_INT_OCCURED_MASK);
}
关键点:
Xil_Out16写入GPIO0_CH2,高8位保持0(LED熄灭)(Led_current << 1) | ((Led_current & 0x80) >> 7) — 左移1位,最高位移到最低位(Led_current >> 1) | ((Led_current & 0x01) << 7) — 右移1位,最低位移到最高位btnl_count = (btnl_count + 1) % 3实现0→1→2→0循环,分别对应左移/右移/停止| 外设 | 基地址 | CH1方向 | CH2方向 | CH1用途 | CH2用途 |
|---|---|---|---|---|---|
| GPIO0 | XPAR_AXI_GPIO_0_BASEADDR | 输入(0xffff) | 输出(0x0) | 16位开关 | 16位LED |
| GPIO1 | XPAR_AXI_GPIO_1_BASEADDR | 输出(0x0) | 输出(0x0) | 8位位选 | 8位段码 |
| GPIO2 | XPAR_AXI_GPIO_2_BASEADDR | 输入(0x1f) | — | 5位按键 | — |
// 初始化配置
Xil_Out16(GPIO0_BASE + XGPIO_TRI_OFFSET, 0xffff); // GPIO0_CH1: 开关→输入
Xil_Out16(GPIO0_BASE + XGPIO_TRI2_OFFSET, 0x0); // GPIO0_CH2: LED→输出
Xil_Out8( GPIO1_BASE + XGPIO_TRI_OFFSET, 0x0); // GPIO1_CH1: 位选→输出
Xil_Out8( GPIO1_BASE + XGPIO_TRI2_OFFSET, 0x0); // GPIO1_CH2: 段码→输出
Xil_Out8( GPIO2_BASE + XGPIO_TRI_OFFSET, 0x1f); // GPIO2_CH1: 按键→输入