ZYNQ-嵌入式学习(4)

GPIO的MIO中断功能


从MIO输入到GPIO的线路有一个通向中断检测模块的分支。
INT_TYPE寄存器表示中断类型。包括边沿和电平两种类型。
INT_POLARITY寄存器表示极性。包括正负极性。电平类型中断包括低电平触发(-)和高电平触发(+)。边沿类型中断包括上升沿极性(+)和下降沿极性(-)。
INT_ANY寄存器针对边沿触发类型的中断。若为1,则两种边沿变换都可触发中断。

INT State寄存器用来保存中断状态。清零端口连接INT_STAT。INT_STAT写1清除中断。
读INT_STAT可获知引脚当前中断状态,即是否有中断产生。

INT_MASK寄存器表示MIO的哪个引脚的中断被屏蔽。读取此寄存器可知哪些引脚的中断被屏蔽。
INT_DIS表示关闭使能,即屏蔽。(disable)
INT_EN表示中断使能。

若某个引脚检测到中断,且同时这个引脚的中断未被屏蔽,则与门输出高电平,即输出一个中断到GIC,即向GIC发送一个IRQ中断请求。GIC即为PS中的中断控制器。#52表示中断ID。
GIC可接收PS和PL的IRQ,通过中断ID获知是谁发起的请求。每个外设的ID都不同,对于GPIO,其中断号为52。

实验:使用GPIO的MIO中断功能,实现按键控制LED的亮灭。

#include "stdio.h"
#include "xparameters.h"
#include "xparameters_ps.h"
#include "xgpiops.h"
#include "xscugic.h"
#include "sleep.h"

#define GPIO_DEVICE_ID		XPAR_XGPIOPS_0_DEVICE_ID
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID
// GPIO中断号(52)
#define GPIO_INTERRUPT_ID	XPAR_XGPIOPS_0_INTR

// 核心板上PS端LED连接到MIO0
#define MIO0_LED 			0

#define MIO12_KEY			12

#define GPIO_BANK	XGPIOPS_BANK0  /* Bank 0 of the GPIO Device */


XGpioPs_Config * ConfigPtr;

XGpioPs Gpio;

// 中断控制器的驱动实例
XScuGic Intc;

// 中断控制器的配置实例
XScuGic_Config *IntcConfig;

XScuGic *GicInstancePtr;

XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */

u32 key_press = 0;

u32 led_value = 0;

void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio, u16 GpioIntrId);

void IntrHandler();

int main(){


	printf("GPIO interrupt test!\n\r");

	// 根据器件的ID,查找器件的配置信息
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);

	// 初始化GPIO驱动
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);

	// 把GPIO某个引脚的方向设置为输出(第二个参数为输出Pin的ID(0~117);第三个参数为方向指示:为0:输入;为1:输出)
	XGpioPs_SetDirectionPin(&Gpio, MIO0_LED, 1);

	// 设置输出使能,第三个参数为1:打开输出使能;为0:关闭输出使能
	XGpioPs_SetOutputEnablePin(&Gpio, MIO0_LED, 1);

	// 设置中断系统
	SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID);

	while(1){
		if(key_press){
			led_value = ~led_value;
			key_press = 0;
			XGpioPs_WritePin(&Gpio, MIO0_LED, led_value);

			// 清除之前的中断状态
			XGpioPs_IntrClearPin(&Gpio, MIO12_KEY);

			// 延时消抖
			usleep(200000);

			// 再次使能按键中断
			XGpioPs_IntrEnablePin(&Gpio, MIO12_KEY);


		}
	}
	return 0;
}

void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio,
				u16 GpioIntrId)
{


	// 查找中断控制器配置信息并进行初始化
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);

	// 初始化ARM处理器异常句柄
	Xil_ExceptionInit();

	// 给IRQ异常注册处理程序
	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);

	// 将bank0中所有引脚都设置为下降沿中断
	//XGpioPs_SetIntrType(Gpio, GPIO_BANK , 0x00, 0xFFFFFFFF, 0x00);

	// 将MIO单个引脚(与按键相连的pin12)设置为下降沿中断
	XGpioPs_SetIntrTypePin(Gpio, MIO12_KEY, XGPIOPS_IRQ_TYPE_EDGE_FALLING);

	/* Enable the GPIO interrupts of Bank 0. */
	//XGpioPs_IntrEnable(Gpio, GPIO_BANK, (1 << Input_Pin));

	// 设置MIO单个引脚的中断使能(主动)
	XGpioPs_IntrEnablePin(Gpio, MIO12_KEY);

	// 设置GIC能够接收GPIO中断(被动)
	XScuGic_Enable(GicInstancePtr, GpioIntrId);


}

void IntrHandler(){
	// 中断处理程序:当检测到pin12出现下降沿时,触发中断,即将key_press变量赋值为1。
	key_press = 1;
	printf("interrupt detected!\n\r");
	// 执行完中断处理函数后,将中断屏蔽掉
	XGpioPs_IntrDisablePin(&Gpio, MIO12_KEY);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值