GPIO的简图如下图所示。
GPIO对应的中断ID是52。
按键中断控制LED的状态
前面实验中已经做了按键控制LED状态的实验,但是LED的状态分为按键按下时和按键松开时的两种状态,并不是按键按一次,LED的状态就翻转一次,要实现这样的功能,需要引入中断。
在这里导入中断的示例代码。
参考导入的代码示例,按键中断控制LED状态的代码如下。
#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#include "xscugic.h"
#include "xil_exception.h"
#define GPIO_INTERRUPT_ID XPAR_XGPIOPS_0_INTR //GPIO的中断号 52U
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID //GPIO1设备ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
static XGpioPs Gpio; //结构体类型,GPIO操作实例
static XScuGic Intc; //结构体类型
static XGpioPs_Config *ConfigPtr; //结构体类型,成员有设备ID和寄存器地址
static XScuGic_Config *IntcConfig; //中断控制器的实例
static u32 PS_LED1 = 0; //PS端LED1连接的输出引脚是0号
static u32 PS_LED2 = 13; //PS端LED2连接的输出引脚是13号
static u32 PS_KEY1 = 50; //PS端KEY1连接的输入引脚是50号
static u32 PS_KEY2 = 51; //PS端KEY2连接的输入引脚是51号
static u32 key_press1 = 0;
static u32 key_press2 = 0;
static u32 key_value1 = 1;
static u32 key_value2 = 1;
static void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio, u16 GpioIntrId, u32 Out_pin);
static void IntrHandler()
{
if(!XGpioPs_ReadPin(&Gpio, PS_KEY1))
{
printf("PS_KEY1 Interrupt detected!\n");
key_press1 = 1;
XGpioPs_IntrDisablePin(&Gpio,PS_KEY1);
}
if(!XGpioPs_ReadPin(&Gpio, PS_KEY2))
{
printf("PS_KEY2 Interrupt detected!\n");
key_press2 = 1;
XGpioPs_IntrDisablePin(&Gpio,PS_KEY2);
}
}
int main()
{
printf("gpio interrupt test!\n");
//查找器件的配置信息
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
//初始化GPIO的驱动
XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
//设置LED的GPIO方向为输出
XGpioPs_SetDirectionPin(&Gpio, PS_LED1, 1); //0-input,1-output
XGpioPs_SetDirectionPin(&Gpio, PS_LED2, 1);
//设置KEY的GPIO方向为输入
XGpioPs_SetDirectionPin(&Gpio, PS_KEY1, 0); //0-input,1-output
XGpioPs_SetDirectionPin(&Gpio, PS_KEY2, 0);
//设置输出使能
XGpioPs_SetOutputEnablePin(&Gpio, PS_LED1, 1); //0-disable,1-enable
XGpioPs_SetOutputEnablePin(&Gpio, PS_LED2, 1);
//查找配置信息,初始化中断控制器驱动
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(&Intc, IntcConfig, IntcConfig->CpuBaseAddress);
//初始化ARM处理器异常句柄
Xil_ExceptionInit();
//给IRQ异常注册处理程序
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&Intc);
//使能处理器中断
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
//配置中断
SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID, PS_KEY1);
SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID, PS_KEY2);
while(1)
{
if(key_press1)
{
key_value1 = ~key_value1;
key_press1 = 0;
XGpioPs_IntrClearPin(&Gpio,PS_KEY1); //清除中断状态,以便读取下次中断
XGpioPs_WritePin(&Gpio, PS_LED1, key_value1); //改变PS LED1的状态
usleep(200000); //延时消抖
XGpioPs_IntrEnablePin(&Gpio, PS_KEY1); //再使能中断
}
if(key_press2)
{
key_value2 = ~key_value2;
key_press2 = 0;
XGpioPs_IntrClearPin(&Gpio,PS_KEY2); //清除中断状态,以便读取下次中断
XGpioPs_WritePin(&Gpio, PS_LED2, key_value2); //改变PS LED2的状态
usleep(200000); //延时消抖
XGpioPs_IntrEnablePin(&Gpio, PS_KEY2)