FPGA入门例程:PL按键中断

前言

学了一个东西,及时用起来,给自己出难题,玩点花的,把知识反复摩擦后,就不容易忘记了

实验

实验目标:每按下一次按键,LED反转一次。即:用PL端的4个按键分别控制PL端的4个LED,按键作为外部中断信息,将中断信号传输给PS,然后PS控制GPIO实现LED反转。


中断:用通俗易懂的话来说,就是本来在吃饭,听到敲门,去开了门后,回来接着刚刚的饭继续吃,停下一件事,去做另一件,做完后回来继续做最开始的那件事

下面是使用的zynq7000-AX7350开发板的led与按键的分布
在这里插入图片描述
本实验中,按键按下,中断发送,因此中断来自PL端

硬件部分

引入ZYNQ的IP核,双击配置处理器的中断
在这里插入图片描述
右键ZYNQ,引出4个端口,连接4个按键
在这里插入图片描述
由于需要使用按键,因此要进行按键消抖
于是我将之前写过的按键消抖代码生成一个IP核
IP核生成的步骤参照:自定义IP核
但是IP核的输入输出都是一位的,而此处有4个按键输入,因此需要用到:拼接IP核、拆分IP核
这两个IP核长这个样子
在这里插入图片描述
使用IP核将按键输入先拆分,然后合并,最后将PL按键信息输入到PS
在这里插入图片描述
当PS得到按键信息后,PS内部通过中断控制ID号,找到对应的中断函数,将点灯信息通过AXI总线传给GPIO,然后上面的GPIO实现点灯操作(GPIO部分的教程在【2】第十章用PS点亮PL端的LED)
下面就是软件,通过vitis网PS中写代码

软件部分

在vitis中修改原有的模板为:

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"

#include "xil_io.h"
#include "xparameters.h"
#include "xscugic.h"

#define INTC_DEVICE_ID	XPAR_SCUGIC_SINGLE_DEVICE_ID
#define XIL_EXCEPTION_ID_INT	XIL_EXCEPTION_ID_IRQ_INT
#define INTC_HANDLER	XScuGic_InterruptHandler
XScuGic Intc;

void Key1Handler(void *CallbackRef)
{

	u32 io = Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
	if(io&0x01){
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io&(~0x01));
	}
	else{
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io|0x01);
	}
}
void Key2Handler(void *CallbackRef)
{
	u32 io = Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
	if(io&0x02){
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io&(~0x02));
	}
	else{
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io|0x02);
	}
}
void Key3Handler(void *CallbackRef)
{
	u32 io = Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
	if(io&0x04){
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io&(~0x04));
	}
	else{
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io|0x04);
	}
}
void Key4Handler(void *CallbackRef)
{
	u32 io = Xil_In32(XPAR_AXI_GPIO_0_BASEADDR);
	if(io&0x08){
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io&(~0x08));
	}
	else{
		Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,io|0x08);
	}
}
int main()
{
    init_platform();
    int i;
    int Result;
    XScuGic_Config *IntcConfig;

	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfig) {
		return XST_FAILURE;
	}
	Result = XScuGic_CfgInitialize(&Intc, IntcConfig,
					IntcConfig->CpuBaseAddress);
	if (Result != XST_SUCCESS) {
		return XST_FAILURE;
	}
	XScuGic_SetPriorityTriggerType(&Intc, 61,
					0xA0, 0x3);
	XScuGic_SetPriorityTriggerType(&Intc, 62,
					0xA0, 0x3);
	XScuGic_SetPriorityTriggerType(&Intc, 63,
					0xA0, 0x3);
	XScuGic_SetPriorityTriggerType(&Intc, 64,
					0xA0, 0x3);
	Result = XScuGic_Connect(&Intc, 61,
				 (Xil_ExceptionHandler)Key1Handler, 0);
	Result = XScuGic_Connect(&Intc, 62,
				 (Xil_ExceptionHandler)Key2Handler, 0);
	Result = XScuGic_Connect(&Intc, 63,
				 (Xil_ExceptionHandler)Key3Handler, 0);
	Result = XScuGic_Connect(&Intc, 64,
				 (Xil_ExceptionHandler)Key4Handler, 0);
	if (Result != XST_SUCCESS) {
		return Result;
	}

	XScuGic_Enable(&Intc, 61);
	XScuGic_Enable(&Intc, 62);
	XScuGic_Enable(&Intc, 63);
	XScuGic_Enable(&Intc, 64);

	Xil_ExceptionInit();

	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			 (Xil_ExceptionHandler)INTC_HANDLER, &Intc);

	Xil_ExceptionEnable();

    Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR+0x04,0x00);

    while(1){
    }
    print("Hello World\n\r");
    print("Successfully ran Hello World application");
    cleanup_platform();
    return 0;
}

上板测试

请添加图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值