***AXI GPIO 😗**AXI GPIO是一个软核,ZYNQ芯片在出厂时并不存在这样的硬件电路,是由用户通过配置PL端的逻辑资源来实现的一个功能模块。
添加AXI GPIO IP核
配置AXI_GPIO IP核
点击自动连接
连接完成:
连接AXI GPIO 中断
- 双击ZYNQ IP 核 打开配置界面
- 配置 PL to PS IRQ0 为 1
- 点ok
将这两个连接
连接完成后Ctrl + S 保存 之后点击验证
输出之后 通过XDC文件进行引脚绑定
绑定引脚时 引脚名字要使用顶层文件中的引脚名
#压缩比特流文件
set_property BITSTREAM.GENERAL.COMPRESS TURE [current_design]
#约束PL引脚
set_property PACKAGE_PIN AF12 [get_ports {AXI_GPIO_KEY_tri_io[0]}]
#约束PL引脚电平
set_property IOSTANDARD LVCMOS33 [get_ports {AXI_GPIO_KEY_tri_io[*]}]
编译并生成比特流文件
导出XSA文件(包含比特流文件)
创建VITIS工程(步骤略)
代码编写
#include "xparameters.h" //器件参数信息
#include "xgpiops.h" //包含PS GPIO的函数声明
#include "xstatus.h" //包含XST_FAILURE和XST_SUCCESS的宏定义
#include "xplatform_info.h"
#include <xil_printf.h> //包含print()函数
#include "sleep.h" //sleep()函数
#include "xscugic.h"
#include "xil_exception.h"
#include "xgpio.h"
#define SCUGIC_ID XPAR_SCUGIC_0_DEVICE_ID //中断控制器ID
#define GPIOS_ID XPAR_XGPIOPS_0_DEVICE_ID //PS端GPIO 器件ID
#define GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL端AXI GPIO 器件ID
#define GPIO_INT_ID XPAR_FABRIC_GPIO_0_VEC_ID //PL端AXI GPIO 中断ID
#define PS_LED 40 //PS端LED
#define KEY_CHANNEL 1 //PL按键使用AXI GPIO 通道1
#define KEY_MASK XGPIO_IR_CH1_MASK //通道1 未定义
XScuGic Scugic; //中断控制器 驱动实例
XScuGic_Config * Scugic_Config; //中断控制器 配置信息
XGpioPs Gpios; //PS端GPIO 驱动实例
XGpioPs_Config * Gpios_Config; //PS端GPIO 配置信息
XGpio Gpio; //PL端AXI GPIO 驱动实例
int LED_FLAG = 0;
//函数声明
void Instance_init(); //初始化器件驱动
void AXI_GPIO_Handler(void *CallbackRef);
int main()
{
Instance_init();
print("AXI GPIO TEST ! ");
//设置指定引脚的方向
XGpioPs_SetDirectionPin(&Gpios, PS_LED, 1);
//设置指定引脚的输出使能
XGpioPs_SetOutputEnablePin(&Gpios, PS_LED, 1);
//设置AXI GPIO 通道1为输入
XGpio_SetDataDirection(&Gpio, KEY_CHANNEL, 1);
//使能通道1中断
XGpio_InterruptEnable(&Gpio, KEY_MASK);
//使能AXI GPIO 全局中断
XGpio_InterruptGlobalEnable(&Gpio);
//设置中断优先级和触发类型(高电平触发) 0xA0 : 中断优先级 0x1:中断类型为高有效电平敏感类型
XScuGic_SetPriorityTriggerType(&Scugic, SCUGIC_ID, 0xA0, 0x1);
//关联中断ID和中断服务子程序
XScuGic_Connect(&Scugic, GPIO_INT_ID, AXI_GPIO_Handler, &Gpio);
//使能AXI GPIO 中断
XScuGic_Enable(&Scugic, XPAR_FABRIC_GPIO_0_VEC_ID);
//设置并打开中断异常处理功能
Xil_ExceptionInit();
//给IRQ异常注册处理程序
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
&Scugic);
Xil_ExceptionEnable();
while(1);
return 0;
}
//初始化各器件驱动
void Instance_init()
{
//初始化中断控制器驱动
Scugic_Config = XScuGic_LookupConfig(SCUGIC_ID);
XScuGic_CfgInitialize(&Scugic, Scugic_Config, Scugic_Config->CpuBaseAddress);
//初始化PS端GPIO驱动
Gpios_Config = XGpioPs_LookupConfig(GPIOS_ID);
XGpioPs_CfgInitialize(&Gpios, Gpios_Config, Gpios_Config->BaseAddr);
//初始化PL端AXI GPIO驱动
XGpio_Initialize(&Gpio, GPIO_ID);
}
//中断服务函数
void AXI_GPIO_Handler(void *CallbackRef)
{
//定义按键标志位
int KEY_FLAG = 1;
XGpio *GpioPtr = (XGpio *)CallbackRef;
print("Interrupt! \r\n");
XGpio_InterruptDisable(GpioPtr, KEY_MASK); //进入中断后 除能AXI GPIO 中断
KEY_FLAG = XGpio_DiscreteRead(GpioPtr, KEY_MASK); //读取按键数据
if(KEY_FLAG == 0) //判断按键是否按下
{
LED_FLAG = ~ LED_FLAG; //如果按下 改变LED标志位
XGpioPs_WritePin(&Gpios, PS_LED, LED_FLAG);
}
XGpio_InterruptClear(GpioPtr, KEY_MASK); //清除中断标志位
XGpio_InterruptEnable(GpioPtr, KEY_MASK); //重新使能AXI GPIO中断
}