本实验任务:使用GPIO的EMIO中断功能,实现按键控制LED的亮灭。即按键下一次灯亮,再按一次灯灭,如此反复。
本实验中的PL端设计步骤与学习笔记3中的步骤基本一致,不同的是本次实验只需要两个EMIO端口,即一个按键(D19),一个LED灯(R14),因此在引脚约束中也需要做相应改动。如下图所示:
接下来便是SDK的软件设计部分,根据官方给出的ug585-Zynq文档的介绍步骤,如下图所示:
在SDK中创建空工程添加suorce文件后,敲入以下代码:
#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#include "xscugic.h"
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define GPIO_INTERRUPT_ID XPAR_XGPIOPS_0_INTR //GPIO的中断号52
//核心板上PS EMIO0引脚:LED EMIO1引脚:按键(EMIO从54开始计数)
#define EMIO0_LED 54
#define EMIO1_KEY 55
XGpioPs_Config * ConfigPtr;
XScuGic_Config *IntcConfig; //Instance of the interrupt controller
XGpioPs Gpio; //The driver instance for GPIO Device.
XScuGic Intc;
//函数声明
static void SetupInterruptSystem(XScuGic *Intc, XGpioPs *Gpio, u16 GpioIntrId);
static void IntrHandler();
u32 key_press=0;
int main(){
u32 led_value=1;
printf("GPIO interrupt test\n");
//查找器件的ID,查找器件的配置信息
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
//初始化GPIO驱动
XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
//把GPIO的方向设置为输出(最后一个参数:0表示输入,1表示输出)
XGpioPs_SetDirectionPin(&Gpio, EMIO0_LED, 1);
//把GPIO的方向设置为输入(最后一个参数:0表示输入,1表示输出)
XGpioPs_SetDirectionPin(&Gpio, EMIO1_KEY, 0);
//设置输出使能(最后一个参数:0表示关闭使能,1表示打开)
XGpioPs_SetOutputEnablePin(&Gpio, EMIO0_LED, 1);
//设置中断系统
SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID);
while(1){
if(key_press){
led_value = ~led_value;
key_press = 0;
//清除之前的中断状态寄
XGpioPs_IntrClearPin(&Gpio, EMIO1_KEY);
//延时按键消抖
usleep(200000);
//使能按键中断
XGpioPs_IntrEnablePin(&Gpio, EMIO1_KEY);
}
//将led_value的状态写入LED
XGpioPs_WritePin(&Gpio, EMIO0_LED,led_value);
}
return 0;
}
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio,u16 GpioIntrId){
//查找器件GIC器件配置信息,并进行初始化
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
//初始化ARM处理器异常句柄
Xil_ExceptionInit();
//给IRQ异常注册处理程序,它会将中断控制器GIC的中断处理程序与ARM处理器中的硬件中断处理逻辑连接起来
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,GicInstancePtr);
//使能处理器中断
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
//关联中断处理函数 其中IntrHandler为中断子程序
XScuGic_Connect(GicInstancePtr, GpioIntrId,
(Xil_ExceptionHandler)IntrHandler,(void *)Gpio);
//为GPIO器件使能中断
XScuGic_Enable(GicInstancePtr, GpioIntrId);
//设置MIO引脚中断触发类型为下降沿触发
XGpioPs_SetIntrTypePin(Gpio, EMIO1_KEY, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
//打开MIO引脚的中断使能信号
XGpioPs_IntrEnablePin(Gpio, EMIO1_KEY);
}
void IntrHandler(){
printf("interrupt test!\n\r");
key_press = 1;
XGpioPs_IntrDisablePin(&Gpio,EMIO1_KEY); //屏蔽按键中断
}
再依次Program FPGA,下载软件程序即可实现预计功能。