第一步:书写SetupInterruptSystem设置中断系统函数
(1)三个Exception:
①初始化ARM处理器异常句柄
②给IRQ异常处理注册程序(IRQ:中断请求)
③使能处理器中断
代码如下:
/*
* 初始化ARM处理器异常句柄
*/
Xil_ExceptionInit();
/*
* 通过调用该函数,给IRQ异常处理注册程序(IRQ:中断请求)
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
GicInstancePtr);
/*
* 使能处理器中断
*/
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
(2)查找器件配置信息,并进行初始化:
/*
* 查找器件配置信息,并进行初始化。
*/
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
(3)两个XScuGic:
①关联中断处理函数。
②为GPIO使能中断。
/*
* 关联中断处理函数
*/
XScuGic_Connect(GicInstancePtr, GpioIntrId,
(Xil_ExceptionHandler)IntrHandler, //IntrHandler是我们自己要编写的中断服务函数!
(void *)Gpio);
/*
* 为GPIO器件使能中断
*/
XScuGic_Enable(GicInstancePtr, GpioIntrId);
【注:后续添加头文件xscugic.h】
【注:后续书写中断服务函数IntrHandler】
(4)两个XGpioPs:
①设置MIO引脚“中断触发类型”。
②打开MIO中断使能信号。
/*
* 设置MIO引脚“中断触发类型”。(在xgpiops.h中寻找相关宏定义)
*/
XGpioPs_SetIntrTypePin(Gpio, Key, XGPIOPS_IRQ_TYPE_EDGE_FALLING); //下降沿触发
/*
* 打开MIO中断使能信号。
*/
XGpioPs_IntrEnablePin(Gpio, Key);
【注:Key是“触发引脚”,稍后会定义为全局变量】
其中,“中断触发类型”在xgpios.h中找到:
(5)补充头文件、宏定义和全局变量: Debug溯源法。
【完整函数代码】
#include"xgpiops.h"
#include"xscugic.h"
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
XGpioPs Gpio;
static u32 Key = 2;
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio, u16 GpioIntrId)
{
/*
* 查找器件配置信息,并进行初始化。
*/
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
/*
* 初始化ARM处理器异常句柄
*/
Xil_ExceptionInit();
/*
* 通过调用该函数,给IRQ异常处理注册程序(IRQ:中断请求)
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
GicInstancePtr);
/*
* 使能处理器中断
*/
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
/*
* 关联中断处理函数
*/
XScuGic_Connect(GicInstancePtr, GpioIntrId,
(Xil_ExceptionHandler)IntrHandler, //IntrHandler是我们自己要编写的中断服务函数!
(void *)Gpio);
/*
* 为GPIO器件使能中断
*/
XScuGic_Enable(GicInstancePtr, GpioIntrId);
/*
* 设置MIO引脚“中断触发类型”。(在xgpiops.h中寻找相关宏定义)
*/
XGpioPs_SetIntrTypePin(Gpio, Key, XGPIOPS_IRQ_TYPE_EDGE_FALLING); //下降沿触发
/*
* 打开MIO中断使能信号。
*/
XGpioPs_IntrEnablePin(Gpio, Key);
}
第二步:自己书写中断服务函数
注意!要和先前写的SetupInterruptSystem函数匹配!
注意,此处博主这是书写了最简单的服务函数。服务函数内部当然可以编写任何你想实现的程序!
xxxx InterHandler(xxxx){
xxxxx;
}
第三步:在main中的GPIO一般配置完成后,使用SetupInterruptSystem
GPIO的一般配置在笔记(二)中已经写过:
【ZYNQ-嵌入式】zynq学习笔记(二)—— GIPO的硬件配置和软件配置
【注:需要添加一些宏定义和全局变量!】
XScuGic Intc;
static u32 Output_Pin_m = 0; //GPIO管脚位号,具体要查看手册
static u32 Input_Pin_m = 1;
static u32 Key = 2; //用于触发中断
int main(void)
{
printf("GPIO-MIO-TEST\n\r");
GPIO_INPUT_INIT(Input_Pin_m);
GPIO_OUTPUT_INIT(Output_Pin_m);
printf("GPIO-MIO-INTERUPT-TEST\n\r");
SetupInterruptSystem(&Intc,&Gpio,GPIO_INTERRUPT_ID);
u32 key_value;
while(1){
//读取按键状态
key_value = GPIO_Read(Input_Pin_m);
//按键状态写入LED
GPIO_Write(Output_Pin_m , ~key_value);
}
return 0;
}
附录:GPIO中断配置函数集【重要】
#include<stdio.h>
#include"xgpiops.h"
#include"xscugic.h"
#include"xparameters.h"
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define GPIO_INTERRUPT_ID XPAR_XGPIOPS_0_INTR //GPIO中断号:52U
XGpioPs Gpio;
XScuGic Intc;
static u32 Output_Pin_m = 0; //GPIO管脚位号,具体要查看手册
static u32 Input_Pin_m = 1;
static u32 Key = 2;
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio, u16 GpioIntrId);
void IntrHandler(void); //中断处理函数
/***********************************
* 设置中断系统函数
***********************************/
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio, u16 GpioIntrId)
{
/*
* 查找器件配置信息,并进行初始化。
*/
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
/*
* 初始化ARM处理器异常句柄
*/
Xil_ExceptionInit();
/*
* 通过调用该函数,给IRQ异常处理注册程序(IRQ:中断请求)
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
GicInstancePtr);
/*
* 使能处理器中断
*/
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
/*
* 关联中断处理函数
*/
XScuGic_Connect(GicInstancePtr, GpioIntrId,
(Xil_ExceptionHandler)IntrHandler, //IntrHandler是我们自己要编写的中断服务函数!
(void *)Gpio);
/*
* 为GPIO器件使能中断
*/
XScuGic_Enable(GicInstancePtr, GpioIntrId);
/*
* 设置MIO引脚“中断触发类型”。(在xgpiops.h中寻找相关宏定义)
*/
XGpioPs_SetIntrTypePin(Gpio, Key, XGPIOPS_IRQ_TYPE_EDGE_FALLING); //下降沿触发
/*
* 打开MIO中断使能信号。
*/
XGpioPs_IntrEnablePin(Gpio, Key);
}
/****************************************
* 中断处理函数(中断服务函数)
****************************************/
void IntrHandler(){
printf("INTERUPT!\n\r");
}
【注:必须先配置常规GPIO,才能进一步配置GPIO中断!】