基于ZYNQ的GPIO多中断使用

时间:2024-03-30 07:42:05

1、工程如下
基于ZYNQ的GPIO多中断使用
2、将gpio_0、gpio_1、gpio_2和gpio_3位宽都配置为1,同时引出0和1的中断,并接入zynq的irq中断控制器。
3、生成bitstream,并生成xsa文件。
4、
main.c

#include <stdio.h>
#include “xil_printf.h”
#include “xparameters.h”

#include “intc.h”
#include “gpio.h”
#include “gpio1.h”

static XScuGic Intc;

int main()
{
int status;
status = Intc_Init(&Intc);
xil_printf(" %d \r\n",status);
status = Gpio_Init(&Intc);
xil_printf(" %d \r\n",status);
status = Gpio1_Init(&Intc);
xil_printf(" %d \r\n",status);
while(1);
return 0;
}

intc.c

#include “xscutimer.h”
#include “xscugic.h”
#include “xil_exception.h”
#include “xparameters.h”
#include “xil_printf.h”

#define INTC_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID

int Intc_Init(XScuGic *Intc){
int Status;
//init intc
XScuGic_Config *Intc_ConfigPtr;
//初始化中断
Intc_ConfigPtr = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == Intc_ConfigPtr) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(Intc,Intc_ConfigPtr,Intc_ConfigPtr->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
//初始化ARM处理器的异常处理
Xil_ExceptionInit();
//连接到Xilinx提供的通用中断处理程序XScuGic_InterruptHandler,
//所有产生的中断都要经过GIC,GIC负责使能中断,废弃中断,赋予优先级,发送到CPU,
//中断发生时ARM处理器会先询问中断控制器哪一个外设产生的中断,第三个参数是传递给处理程序的
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, Intc);
Xil_ExceptionEnable();
return XST_SUCCESS;
}

intc.h

#ifndef _INTC_H
#define _INTC_H

#include “xscugic.h”

int Intc_Init(XScuGic *Intc);

#endif

gpio.c

#include “xgpio.h”
#include “xscugic.h”
#include “xil_exception.h”
#include “xparameters.h”
#include “xil_printf.h”

#include “gpio.h”
#include “sleep.h”

#define GPIO_DEVICE_ID_1 XPAR_GPIO_1_DEVICE_ID
#define GPIO_DEVICE_ID_3 XPAR_GPIO_3_DEVICE_ID

#define INTC_GPIO_INTERRUPT_ID_1 XPAR_FABRIC_AXI_GPIO_1_IP2INTC_IRPT_INTR

#define GPIO_CHANNEL_1 1
#define GPIO_CHANNEL_3 1

static XGpio Gpio_1;
static XGpio Gpio_3;

static int dispaly_0 = 0;
u32 InputData;

static void GpioHandler1(void *CallBackRef);

void GpioHandler1(void *CallbackRef)
{
XGpio *Gpio_11 = (XGpio *)CallbackRef;
//去抖
usleep(10);
//读输入
if(XGpio_DiscreteRead(Gpio_11,GPIO_CHANNEL_1) == 0x1){
//设定输出,跳变
XGpio_DiscreteWrite(&Gpio_3,GPIO_CHANNEL_3,dispaly_0&0x1);
xil_printf(" %d \r\n",dispaly_0);
dispaly_0++;
}
XGpio_InterruptClear(Gpio_11, GPIO_CHANNEL_1);
}
int Gpio_Init(XScuGic *Intc){
int Status;
//初始化gpio_1
Status = XGpio_Initialize(&Gpio_1, GPIO_DEVICE_ID_1);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
//配置gpio_1为输入
XGpio_SetDataDirection(&Gpio_1,GPIO_CHANNEL_1,1);
//初始化gpio_3
Status = XGpio_Initialize(&Gpio_3, GPIO_DEVICE_ID_3);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
//配置gpio_3为输出
XGpio_SetDataDirection(&Gpio_3,GPIO_CHANNEL_3,0);
//配置中断类型
XScuGic_SetPriorityTriggerType(Intc,INTC_GPIO_INTERRUPT_ID_1,0xA0, 0x3);
//将gpio_1中断连接到中断处理程序1
Status = XScuGic_Connect(Intc, INTC_GPIO_INTERRUPT_ID_1, (Xil_ExceptionHandler)GpioHandler1, &Gpio_1);
if (Status != XST_SUCCESS) {
return Status;
}
//在GIC上使能gpio_1中断
XScuGic_Enable(Intc, INTC_GPIO_INTERRUPT_ID_1);
//在goio_1上使能中断
XGpio_InterruptEnable(&Gpio_1, GPIO_CHANNEL_1);
//在goio_1上使能全局中断
XGpio_InterruptGlobalEnable(&Gpio_1);
return XST_SUCCESS;
}

gpio.h

#ifndef _GPIO_H
#define _GPIO_H

#include “xscugic.h”

int Gpio_Init(XScuGic *Intc);

#endif

gpio1.c

#include “xgpio.h”
#include “xscugic.h”
#include “xil_exception.h”
#include “xparameters.h”
#include “xil_printf.h”

#include “gpio.h”
#include “sleep.h”

#define GPIO_DEVICE_ID_0 XPAR_GPIO_0_DEVICE_ID
#define GPIO_DEVICE_ID_2 XPAR_GPIO_2_DEVICE_ID

#define INTC_GPIO_INTERRUPT_ID_0 XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR

#define GPIO_CHANNEL_0 1
#define GPIO_CHANNEL_2 1

static XGpio Gpio_0;
static XGpio Gpio_2;

static int dispaly_0 = 0;
u32 InputData;

static void GpioHandler0(void *CallBackRef);

void GpioHandler0(void *CallbackRef)
{
XGpio *Gpio_00 = (XGpio *)CallbackRef;
//去抖
usleep(10);
//读输入
InputData = XGpio_DiscreteRead(Gpio_00,GPIO_CHANNEL_0);
if(InputData == 0x01){
//设定输出,跳变
XGpio_DiscreteWrite(&Gpio_2,GPIO_CHANNEL_2,dispaly_0&0x1);
xil_printf(" %d \r\n",dispaly_0);
dispaly_0++;
}
XGpio_InterruptClear(Gpio_00, GPIO_CHANNEL_0);
}
int Gpio1_Init(XScuGic *Intc){
int Status;
//初始化gpio_0
Status = XGpio_Initialize(&Gpio_0, GPIO_DEVICE_ID_0);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
//配置gpio_0为输入
XGpio_SetDataDirection(&Gpio_0,GPIO_CHANNEL_0,1);
//初始化gpio_2
Status = XGpio_Initialize(&Gpio_2, GPIO_DEVICE_ID_2);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
//配置gpio_2为输出
XGpio_SetDataDirection(&Gpio_2,GPIO_CHANNEL_2,0);
//配置中断类型
XScuGic_SetPriorityTriggerType(Intc,INTC_GPIO_INTERRUPT_ID_0,0xA0, 0x3);
//将gpio_0中断连接到中断处理程序0
Status = XScuGic_Connect(Intc, INTC_GPIO_INTERRUPT_ID_0, (Xil_ExceptionHandler)GpioHandler0, &Gpio_0);
if (Status != XST_SUCCESS) {
return Status;
}
//在GIC上使能gpio_0中断
XScuGic_Enable(Intc, INTC_GPIO_INTERRUPT_ID_0);
//在goio_0上使能中断
XGpio_InterruptEnable(&Gpio_0, GPIO_CHANNEL_0);
//在goio_0上使能全局中断
XGpio_InterruptGlobalEnable(&Gpio_0);
return XST_SUCCESS;
}

gpio1.h

#ifndef _GPIO1_H
#define _GPIO1_H

#include “xscugic.h”

int Gpio1_Init(XScuGic *Intc);

#endif

5、现象就是连接gpio_2和gpio_3的两个led随着gpio_0和gpio_1的按压,交替的亮灭。