ZYNQ 用PL按键通过中断控制PS端LED亮灭

关键词:AXI-GPIO;中断;PL按键;PS端LED

实现功能:PL端五个按键,可以触发中断,改变LED灯的亮灭状态

开发板:zedboard

  • vivado硬件连接如图:

AXI Interconnect:实际是一个开关,管理和只会axi接口之间的通信(包括一对一、一对多、多对一、多对多)

processing_system7_0:为整个处理器系统提供复位信号

axi_gpio:软核GPIO,即由FPGA搭建,而不是硬件出厂配置好的

ZYNQ 用PL按键通过中断控制PS端LED亮灭_第1张图片

 

  • 配置:

        axi_gpio:位宽1;中断使能打开;  自动连线之后位宽变为5

                        

ZYNQ 用PL按键通过中断控制PS端LED亮灭_第2张图片

  •  打开PL到PS中断端口,并把axi_gpio中断端口连接到z7

ZYNQ 用PL按键通过中断控制PS端LED亮灭_第3张图片

  •  点击左侧Open Elaborated Design分配管脚,zedboard自动分配完成。pin号如图所示,开发板右下角5个键位

ZYNQ 用PL按键通过中断控制PS端LED亮灭_第4张图片

  •  file-export-export hardware  包含bit文件

 

  • file-launch sdk

 

  • 新建应用工程hello world

 

  • 中断号  61
 #define AXI_GPIO_INTERRUPT_ID	  XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
  • 检测到按键按下之后要先读数据  GPIOX_DATA判断按键状态,调用XGpio_DiscreteRead函数进行判断。否则灯的状态不变
if((XGpio_DiscreteRead(&AXI_Gpio, GPIO_CHANNEL1) )!= 0)
  • main.c完整代码:
#include 
#include "xparameters.h"
#include "xgpiops.h"
#include "xstatus.h"
#include "xplatform_info.h"
#include 
#include "sleep.h"
#include "xscugic.h"
#include "xgpio.h"

#define AXI_GPIO_DEVICE_ID		XPAR_GPIO_0_DEVICE_ID    //axi_gpio  ID

#define GPIO_DEVICE_ID		XPAR_XGPIOPS_0_DEVICE_ID      //PS gpio   ID
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID  //中断控制器ID
#define MIO7_LED            7    //ps端LED
#define	MIO50_KEY           51    //按键

//AXI_GPIO中段号:61
 #define AXI_GPIO_INTERRUPT_ID	  XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
#define GPIO_CHANNEL1		1     //axi_gpio通道1
XGpioPs_Config *ConfigPtr;
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
XGpioPs Gpio;	/* The driver instance for GPIO Device. */
XGpio AXI_Gpio; /* The Instance of the GPIO Driver */

static XScuGic Intc; /* The Instance of the Interrupt Controller Driver */

void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,
				u16 AXI_GpioIntrId);
void IntrHandler();
u32 KEY_PRESS = 0;


int main()
{
	u32 led_value = 0;

	printf("***AXI GPIO INTERRUPT TEST***\r\n");
	//根据器件id,查找PS端器件配置信息。并初始化
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);

//	AXI_GPIO初始化
	XGpio_Initialize(&AXI_Gpio, AXI_GPIO_DEVICE_ID);

	//gpio方向设置为输出(0:输入、1:输出),并打开输出使能
	XGpioPs_SetDirectionPin(&Gpio, MIO7_LED, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO7_LED, 1);

	XGpioPs_WritePin(&Gpio, MIO7_LED, led_value);   //初始化led灯,处于熄灭状态,否则第一次按键led状态不变

//	AXI_GPIO配置
//	XGpio_SetDataDirection(&AXI_Gpio, GPIO_CHANNEL1, 0x00000001);   //	把最低位设置为输入
	XGpio_SetDataDirection(&AXI_Gpio, GPIO_CHANNEL1, 0x0000001f);   //  把后5位设置为输入


	SetupInterruptSystem(&Intc, &AXI_Gpio, AXI_GPIO_INTERRUPT_ID);

	while(1)
	{

		if(KEY_PRESS)
		{
//			判断当前按键状态,如果是按键按下,就改变LED状态
			if((XGpio_DiscreteRead(&AXI_Gpio, GPIO_CHANNEL1)) !=0)
				led_value = ~led_value;
			KEY_PRESS = 0;
//			清除中断状态
			XGpio_InterruptClear(&AXI_Gpio, 0x0000001f);
//			写数据到输出引脚
			XGpioPs_WritePin(&Gpio, MIO7_LED, led_value);
//			延时消抖
			usleep(200000);
//			重新打开使能引脚中断
			XGpio_InterruptEnable(&AXI_Gpio, 0x0000001f);

		}
	}
	return 0;
}



void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,
				u16 AXI_GpioIntrId)
{

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

//	初始化ARM处理器异常句柄
	Xil_ExceptionInit();
//	给中断异常注册一个处理程序
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, GicInstancePtr);
//	使能处理器中断.Enable interrupts in the Processor.
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

//	关联   中断处理函数,对中断进行处理
	XScuGic_Connect(GicInstancePtr, AXI_GpioIntrId,	(Xil_ExceptionHandler)IntrHandler, (void *)AXI_Gpio);

	/* Enable the interrupt for the GPIO device.为GPIO器件使能中断 */
	XScuGic_Enable(GicInstancePtr, AXI_GpioIntrId);

//	设置优先级和触发类型,0x1中断类型:高有效电平敏感型
	XScuGic_SetPriorityTriggerType(GicInstancePtr, AXI_GpioIntrId, 0xA0, 0x1);

//	打开AXI_GPIO  IP的中断使能
	XGpio_InterruptGlobalEnable(AXI_Gpio);                //   打开全局中断
	XGpio_InterruptEnable(AXI_Gpio, 0x0000001f);         //    打开通道中的信号对应中断使能

//	return XST_SUCCESS;
}

void IntrHandler()
{

	printf("interrupt detected!\r\n");
	KEY_PRESS = 1;
	XGpio_InterruptDisable(&AXI_Gpio, 0x0000001f);

}

你可能感兴趣的:(ZYNQ)