zynq设计学习笔记5——AXI_GPIO之按键中断控制LED灯实验

在本实验中,我们将通过调用AXI GPIO IP核,使用中断机制,实现底板上PL端按键控制PS端GPIO,并使用EMIO控制LED灯的亮灭。首先,axi_gpio与之前的GPIO的区别:之前的GPIO是硬核,是ps端实际存在的外设电路;而axi_gpio是软核,实现的时候需要由fpga的pl端去搭建。下面为实验步骤:

第一步:根据建立Vivado工程,本设计所使用的开发板为pynq-z2。再Create Block Design,先添加zynq,并对其进行设置:(1)添加UART,并设置1位宽的EMIO GPIO。(2)根据各自开发板更改Clock Congfiguration中Basic Clocking的输入频率。(3)根据各自开发板对DDR进行配置。(4)设置中断,如下图所示:
上述其他配置配置过程均在前面的笔记中有详细介绍,不懂可参考往期学习笔记。
在这里插入图片描述

第二步:搜索添加AXI GPIO,并对其进行如下设置:
在这里插入图片描述

第三步:自动引脚连线,如下图所示:
在这里插入图片描述
在这里插入图片描述
则将形成如下图所示的Block Design,此时会发现增加了两个IP核,其中AXI Interconnect IP核用于将一个或多个AXI存储器映射的主器件连接到一个或多个存储器映射的从器件。而互联实际上是一个开关,它管理并指挥所连接的AXI接口之间的通信。图中设计表明:AXI互联实现了由主器件ZYNQ7 PS到从器件AXI GPIO一对一的连接。它也可以实现一对多、多对一以及多对多的AXI接口连接。Processor System Reset IP为整个处理器系统提供复位信号,它会处理输入端的各种复位条件,并在输出端产生相应的复位信号。Processor System Reset 接收ZYNQ PS输出的异步复位信号FCLK_RESET0_N,然后产生一个同步到PL时钟源FCLK_CLK0的复位信号peripheral_aresetn,用于复位PL端的各外设模块。
在这里插入图片描述
然后进行如下设置:(1)与往期笔记相同的是,先将ZYNQ上GPIO_0的引脚Make External,该引脚将于PL端LED灯相连,因此可命名为GPIO_LED。(2)此外,在本实验中,上图中axi_gpio_0 IP的GPIO引脚将与PL端按键直接相连,因此可将该引脚改名为:AXI_GPIO_KEY,方便之后引脚分配;(3)而其中断将与第一步-4中设置的PL中断输入相连,将按键作为中断变量,因此将下图高亮的连线手动相连:
在这里插入图片描述

第四步:对该Block Design 依次Generate Output Products,Create HDL Wrapper,再在RTL ANALYSIS中Open Elaborated Design进行引脚分配:
在这里插入图片描述
完成上述步骤后,点击保存,再Generate Bitstream,在耐心等待之后再Export Hardware,记住选择Include bitstream。再launch SDK。

第五步:SDK中新建Empty Application。在src文件夹下添加新source file。参考pg144-axi-gpio中设计流程和官方例程,可设计出如下代码。
在这里插入图片描述

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

#define GPIO_DEVICE_ID  		XPAR_XGPIOPS_0_DEVICE_ID					//PS GPIO	器件ID
#define INTC_DEVICE_ID			XPAR_SCUGIC_SINGLE_DEVICE_ID				//中断控制器	器件ID
#define AXI_GPIO_DEVICE_ID		XPAR_GPIO_0_DEVICE_ID						//AXI_GPIO	器件ID
#define AXI_GPIO_INTERRUPT_ID	XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR	//AXI GPIO的中断号61

//核心板上PS EMIO0引脚:LED (EMIO从54开始计数)
#define EMIO0_LED      54
//AXI GPIO通道1
#define GPIO_CHANNEL1		1

XGpioPs_Config * ConfigPtr;
XScuGic_Config *IntcConfig; 		//Instance of the interrupt controller
XGpioPs Gpio;						//The driver instance for GPIO Device.
XScuGic Intc;
XGpio 	AXI_Gpio; 					// The Instance of the GPIO Driver

//函数声明
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,u16 AXI_GpioIntrId);
static void IntrHandler();
u32 key_press=0;

int main(){
	u32 led_value=1;

	printf("AXI GPIO interrupt test\n");

	//查找PS端GPIO的配置,并初始化
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);

	//对AXI GPIO进行初始化
	XGpio_Initialize(&AXI_Gpio, AXI_GPIO_DEVICE_ID);

	//把GPIO的方向设置为输出,并打开输出使能(1表示输出、1表示打开使能)
	XGpioPs_SetDirectionPin(&Gpio, EMIO0_LED, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, EMIO0_LED, 1);

	//对AXI GPIO进行配置(最后一个参数对32位的AXI接口方向进行设置,1为输入)
	XGpio_SetDataDirection(&AXI_Gpio, GPIO_CHANNEL1 ,0x00000001);

	//将led_value的状态写入LED
	XGpioPs_WritePin(&Gpio, EMIO0_LED,led_value);

	//设置中断系统
	SetupInterruptSystem(&Intc, &AXI_Gpio, AXI_GPIO_INTERRUPT_ID);

	while(1){
		if(key_press){
			//判断当前按键的状态,如果是按键按下,就改变
			if(XGpio_DiscreteRead(&AXI_Gpio, GPIO_CHANNEL1) == 0){
				led_value = ~led_value;
				key_press = 0;

				//清除之前的中断状态寄
				XGpio_InterruptClear(&AXI_Gpio,0x00000001);

				//将led_value的状态写入LED
				XGpioPs_WritePin(&Gpio, EMIO0_LED,led_value);

				//延时按键消抖
				usleep(200000);

				//使能AXI_GPIO中断
				XGpio_InterruptEnable(&AXI_Gpio,0x00000001);
			}
		}
	}
	return 0;
}

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

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

	//初始化ARM处理器异常句柄
	Xil_ExceptionInit();
	//给IRQ异常注册处理程序,它会将中断控制器GIC的中断处理程序与ARM处理器中的硬件中断处理逻辑连接起来
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,GicInstancePtr);
	//使能处理器中断
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

	//关联中断处理函数  其中IntrHandler为中断子程序
	XScuGic_Connect(GicInstancePtr, AXI_GpioIntrId,
				(Xil_ExceptionHandler)IntrHandler,(void *)AXI_Gpio);
	//为AXI_GPIO器件使能中断
	XScuGic_Enable(GicInstancePtr, AXI_GpioIntrId);

	//第三个参数表示中断优先级,0优先级最高,8位宽
	//第四个参数表示中断类型:0x1类型为高有效电平敏感类型
	XScuGic_SetPriorityTriggerType(GicInstancePtr, AXI_GpioIntrId,0xA0, 0x1);

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

void IntrHandler(){
	printf("interrupt test!\n\r");
	key_press = 1;
	XGpio_InterruptDisable(&AXI_Gpio,0x00000001);  //屏蔽中断

}

然后连接上开发板,此时下载程序需要先配置PL,即在SDK工具栏的Xilinx中选择Program FPGA,默认参数就行,直接点击Program。完成后开发板上DONE灯将亮起,其是FPGA配置完成的标志。再按照学习笔记1的步骤下载软件程序即可实现功能:按下按键灯由亮变灭,再按一次灯由灭变亮,同时每按一次串口上都会打印一个 interrupt test!

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Zynq芯片中,GPIO引脚的中断是通过AXI_GPIO模块和PS相连的中断信号线的电平变换引发的。可以通过配置中断触发方式来设置GPIO引脚的中断。具体来说,可以使用XScuGic_SetPriorityTriggerType函数来设置中断触发优先级和触发类型。例如,可以通过设置中断触发类型为上升沿触发来使得当GPIO引脚的电平变为上升沿时触发中断。 需要注意的是,GPIO引脚的中断方式已经由硬件决定好了,无法在此处进行配置。参考函数的注释中提到,只有两种方式可以设置中断,即高电平和上升沿,这里的高电平和上升沿指的是AXI_GPIO模块和PS相连的中断信号线的电平变换引发PS中断,而不是GPIO引脚的中断方式。 因此,在配置中断触发方式时,需要确定好AXI_GPIO模块和PS相连的中断信号线的电平变换方式并设置相应的中断触发类型。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [zynq-7000.rar_linux 中断 zynq_zynq DMA_zynq DMA Linux_zynq gpio_i2](https://download.csdn.net/download/weixin_42651887/86201535)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [ZYNQ_GPIO_中断](https://blog.csdn.net/Master_0_/article/details/125125000)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值