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的中断状态,从而导致连续进入中断服务函数好几次。😎

  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Zynq芯片中,GPIO引脚的中断是通过AXI_GPIO模块和PS相连的中断信号线的电平变换引发的。可以通过配置中断触发方式来设置GPIO引脚的中断。具体来说,可以使用XScuGic_SetPriorityTriggerType函数来设置中断触发优先级和触发类型。例如,可以通过设置中断触发类型为上升沿触发来使得当GPIO引脚的电平变为上升沿时触发中断。 需要注意的是,GPIO引脚的中断方式已经由硬件决定好了,无法在此处进行配置。参考函数的注释中提到,只有两种方式可以设置中断,即高电平和上升沿,这里的高电平和上升沿指的是AXI_GPIO模块和PS相连的中断信号线的电平变换引发PS中断,而不是GPIO引脚的中断方式。 因此,在配置中断触发方式时,需要确定好AXI_GPIO模块和PS相连的中断信号线的电平变换方式并设置相应的中断触发类型。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [zynq-7000.rar_linux 中断 zynq_zynq DMA_zynq DMA Linux_zynq gpio_i2](https://download.csdn.net/download/weixin_42651887/86201535)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [ZYNQ_GPIO_中断](https://blog.csdn.net/Master_0_/article/details/125125000)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值