其他分享
首页 > 其他分享> > zynq中断之gpio中断,emio按键中断详解(解决重复中断)

zynq中断之gpio中断,emio按键中断详解(解决重复中断)

作者:互联网

一.概要
    zynq有三种中断:软中断(software interrtpts),私有外设中断(private peripheral)和共享外设中断(shared perlpherals)。区别在于私有外设中断和共享外设中断含有PL测引入的中断。*每个中断都有自己ID号。*有一个中断控制器(generic interrupt controller)管理着这些中断的使能,分类,分配和优先级。框图如下图所示:
图一
①软中断:
在这里插入图片描述
②私有外设中断:
    私有外设中断包括global timer,private time,watchdog。

③共享外设中断

在这里插入图片描述
在这里插入图片描述
二.emio按键中断
    中断初始化有两种格式,第一种是按照sdk给出的例程的格式,第二种是做了一点小的修改,个人觉得第二种更好用。
1)根据sdk例程的中断初始化

	//初始化异常管理
	Xil_ExceptionInit();
//初始化中断控制器
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	XScuGic_CfgInitialize(&GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
//连接中断控制器到CPU
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				&GicInstancePtr);
//连接中断控制器到中断服务函数(这个很重要,下面要用到)
	XScuGic_Connect(&GicInstancePtr, GpioIntrId,
				(Xil_ExceptionHandler)XGpioPs_IntrHandler,
				&Gpio);
//设置中断类型
	XGpioPs_SetIntrType(&Gpio, GPIO_BANK, 0x00, 0x00000000, 0x00);
//设置中断服务函数地址到gpio实例数据中
	XGpioPs_SetCallbackHandler(&Gpio, (void *)&Gpio, IntrHandler);
//使能gpio的中断
	XGpioPs_IntrEnable(&Gpio, GPIO_BANK, (1 << 0));

//使能中断控制器中的gpio中断
	XScuGic_Enable(&GicInstancePtr, GpioIntrId);
//使能异常处理
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

中断服务函数的地址是通过上面的XGpioPs_SetCallbackHandler()函数添加到GPIO的实例数据的,当经过emio的一个按键按下触发中断时,CPU会转到下面的函数中参数的Xil_ExceptionHandler)XGpioPs_IntrHandler中去(经过单步调试可以知道)

XScuGic_Connect(&GicInstancePtr, GpioIntrId,
				(Xil_ExceptionHandler)XGpioPs_IntrHandler,
				&Gpio);

XGpioPs_IntrHandler函数是塞琳思已经写好的,内部如下所示
在这里插入图片描述
进入XGpioPs_IntrHandler函数以后,又会通过上图红色框中的语句跳到中断服务函数去,中断服务函数就是这样被调用的。但是从XGpioPs_IntrHandler函数进入中断服务函数会有一些小问题,就是中断服务函数会重复执行好几次。原因是因为:
在这里插入图片描述
如上图所示,XGpioPs_IntrHandler函数中有有个for 循坏会检测GPIO的4个bank的中断状态,不知道为什么他这里的bank0和1的中断状态不是0的,所以他就会连续进入好几次中断服务函数。为了解决这个问题,我们需要在中断服务函数中读取gpio中断pin的中断状态,只有在对应中断pinc触发了才会执行if里面的语句,示例代码如下图所示:
在这里插入图片描述
注意:上面if里面程序我用usleep()代替了按键消抖,这里我想说的是必须要先消抖才能执行下面的中断清0和屏蔽函数,反过来的话可能会导致中断清0失败。
2)第二种中断初始化格式
    第二种中断初始化是把第一种中断初始化中的XGpioPs_SetCallbackHandler(&Gpio, (void *)&Gpio, IntrHandler)删去,然后把XScuGic_Connect(&GicInstancePtr, GpioIntrId,
(Xil_ExceptionHandler)XGpioPs_IntrHandler,
&Gpio)中的XGpioPs_IntrHandler改为自定义的中断服务函数的地址。如下图所示:
在这里插入图片描述
这样中断触发的时候,就会直接调用中断服务函数IntrHandler(),避免了第一种触发中断后进入XGpioPs_IntrHandler()中去检测GPIO的4个bank的中断状态,从而导致连续进入中断服务函数好几次。

标签:函数,emio,中断,Xil,IntrHandler,zynq,Gpio,XGpioPs
来源: https://blog.csdn.net/weixin_42628470/article/details/106752575