5.AXI_GPIO实验
简介
AXI(高级可扩展接口)是一种高性能、低功耗的总线协议,用于在不同的硬件模块之间进行通信。PS和PL之间的连接通常使用AXI接口,以实现数据传输和控制信号的交换。这种连接方式可以实现高速数据传输和灵活的系统集成,使得PS和PL之间可以进行有效的通信和协作。
AXI_GPIO
AXI GPIO是一种特定的GPIO(通用输入/输出)控制器,它使用AXI(高级可扩展接口)总线协议进行通信。以下是关于AXI GPIO的一些相关知识:
-
功能:AXI GPIO用于控制和读取GPIO引脚的状态。它可以配置GPIO引脚的输入/输出模式、电平状态和中断触发方式,并可以读取GPIO引脚的当前状态。
-
AXI接口:AXI GPIO使用AXI总线协议进行与处理器或其他外设的通信。AXI是一种高性能、低功耗的总线协议,用于在不同的硬件模块之间进行数据传输和控制信号的交换。
-
寄存器:AXI GPIO通过特定的寄存器来实现控制和读取操作。这些寄存器包括配置寄存器、数据寄存器和中断寄存器等,用于配置GPIO引脚的属性和读取/写入GPIO引脚的状态。
-
中断功能:AXI GPIO可以配置中断触发方式,并在GPIO引脚状态发生变化时产生中断信号。这样可以实现对外部事件的实时响应,例如按键按下、传感器检测等。
-
应用领域:AXI GPIO广泛应用于嵌入式系统中,用于与处理器或其他外设进行通信,以控制和读取GPIO引脚的状态。它可以用于连接各种外设,如LED、按钮、传感器等,实现与外部环境的交互。
实验记录
set_property PACKAGE_PIN D19 [get_ports {AXI_GPIO_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {AXI_GPIO_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_0_tri_io[0]}]
set_property PACKAGE_PIN R14 [get_ports {GPIO_0_0_tri_io[0]}]
代码
#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#include "xscugic.h"
#include "xgpio.h"
//实现功能:用BTN0来控制LED0
//BTN1没有用到
#define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID //PS 端 GPIO 器件 ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中断控制器器件ID
#define AXI_GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //AXI_GPIO 器件ID
//AXI_GPIO 中断号 61
#define AXI_GPIO_INTERRUPT_ID XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
//AXI_GPIO 通道1
#define GPIO_CHANNEL1 1
#define LED0 54
XGpioPs_Config * gpiops_cfg_ptr;
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);
void IntrHandler();
u32 btn_press = 0;
int main()
{
u32 led_vaule = 0;
//根据器件的ID,查找器件的配置信息
gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
//初始化GPIO驱动
XGpioPs_CfgInitialize(&Gpio, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);
//设置LED为输出 ;把GPIO的方向设置为输出 (0:输入/ 1:输出)
XGpioPs_SetDirectionPin(&Gpio, LED0, 1);
//设置LED输出使能(0:关闭/ 1:打开)
XGpioPs_SetOutputEnablePin(&Gpio, LED0, 1);
//对AXI_GPIO 进行初始化
XGpio_Initialize(&AXI_Gpio, AXI_GPIO_ID);
//对AXI_GPIO 进行配置
XGpio_SetDataDirection(&AXI_Gpio, GPIO_CHANNEL1, 0x00000001); //设置为输入
//设置中断系统
SetupInterruptSystem(&Intc, &AXI_Gpio, AXI_GPIO_INTERRUPT_ID);
printf("AXI GPIO INTERRUPT TEST!\n");
//读取按键状态,控制LED
while(1)
{
if(XGpio_DiscreteRead(&AXI_Gpio, GPIO_CHANNEL1) == 0X1)
{
led_vaule = ~led_vaule;
btn_press = 1;
//延时消抖10ms
usleep(10000);
//清除之前的中断状态
XGpio_InterruptClear(&AXI_Gpio, 0x00000001);
//将led_vaule的值写入LED
XGpioPs_WritePin(&Gpio , LED0, led_vaule);
//延时消抖200ms
usleep(200000);
//重新打开通道1中断使能
XGpio_InterruptEnable(&AXI_Gpio, 0x00000001);
}
}
return 0;
}
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,u16 AXI_GpioIntrId)
{
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
//查找GIC器件配置信息,并进行初始化
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
//初始化ARM处理器异常句柄
Xil_ExceptionInit();
//来给IRQ异常注册处理程序
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
GicInstancePtr);
//使能处理器中断
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
//关联中断处理函数
XScuGic_Connect(GicInstancePtr, AXI_GpioIntrId,
(Xil_ExceptionHandler)IntrHandler,
(void *)AXI_Gpio);
//为GPIO器件使能中断
XScuGic_Enable(GicInstancePtr, AXI_GpioIntrId);
//0xA0:指定中断优先级 0x1:中断类型为高有效,电平敏感型
XScuGic_SetPriorityTriggerType(GicInstancePtr, AXI_GpioIntrId,0xA0, 0x1);
//打开XAI_GPIO IP 的中断使能
XGpio_InterruptGlobalEnable(AXI_Gpio); //打开全局中断使能
XGpio_InterruptEnable(AXI_Gpio, 0x00000001); //打开通道中的信号对应的中断使能
}
void IntrHandler()
{
printf("Interrupt detected !\n");
btn_press = 1;
//关闭通道1中断使能信号
XGpio_InterruptDisable(&AXI_Gpio, 0x00000001);
}
操作问题
-
在vivado界面更改过 Block Design 后,要重新 Generate Outputs Products , Create HDL Wrapper,导出硬件;
-
在更改过引脚后,要重新综合,生成Bitstream;
并在vitis中重新导入xsa文件