前言
本文将详细介绍PS端使用GPIO的三种方式
一、VIVADO设计
使用GPIO的三种方式
总体框图:

MIO:ARM一侧专用引脚
EMIO:扩展MIO口,将FPGA的引脚交由PS端控制,需要在MIO配置中进行选择,并且配置IO口数量,默认64个IO,确定后,框图中PS端就会出现GPIO_0接口,这个引脚是一个三态门形式,在生成顶层的时候,会通过PL端资源将其转化为inout的GPIO接口。

AXI:PS端通过AXI接口,连接AXI_GPIO可以实现GPIO。

打开PS端GP AXI主机接口,PS端会添加一个M_AXI_GP0接口,添加AXI GPIO IP核,该IP核即实现了一个通过AXI控制的GPIO

选择ALL Output,否则是一个三态门接口,宽度设置为1;通过AXI Smartconnect(一从一主)进行连接。
时钟选择:选择通过PS端输出的时钟信号FCLK_CLK0以及相应的复位信号


添加复位模块后完成设计,导出BD products,输出顶层模块,约束PL端引脚,可以将俩个GPIO(AXI和EMIO,MIO属于PS端,无需约束)输出接口连接俩个LED灯,生成bit流,导出硬件信息,由于加入了PL端设计,必须勾选include bit流
二、VITIS设计
1.启动VITIS
创建硬件平台
2.导入GPIO示例

3.GPIO代码设计
注:代码为本人通过学习FPGA奇哥系列网课进行自主编写
main函数,通过示例工程进行学习,主要包括,初始化函数、设置GPIO输入输出方向函数、读取输入数据、输出数据。实现功能为,通过MIO读取PS端按键电平信息,将按键电平信息通过EMIO和AXI_GPIO输出给PL端LED灯,实现PS端按键控制PL端LED灯的功能。
#include "main.h"
#include "gpio.h"
XGpioPs ZYNQ_Gpio;//GPIO控制器结构体
XGpio AXI_Gpio;
int main(){
int key_status = 0;
xil_printf("start\r\n"); //串口打印Start
GpioInit(&ZYNQ_Gpio,XPAR_PS7_GPIO_0_DEVICE_ID); //初始化GPIO
GpioInputSet(&ZYNQ_Gpio,KEY); //设置GPIO方向为输入
GpioOutputSet(&ZYNQ_Gpio,LED); //设置LED为输出
AXIgpioInit(&AXI_Gpio, XPAR_AXI_GPIO_0_DEVICE_ID); //初始化AXI GPIO方向为输入
AXIgpioOutputSet(&AXI_Gpio, 1); //设置LED为输出
while(1){
key_status = GpioReadData(&ZYNQ_Gpio,KEY); //获取按键引脚点平状态(MIO控制的按键)
xil_printf("key:%d\r\n",key_status);
GpioOutputData(&ZYNQ_Gpio, LED , key_status); //使用按键控制LED灯(EMIO控制的LED)
AXIgpioOutputData(&AXI_Gpio, 1, key_status); //使用按键控制LED灯(AXI控制的LED)
}
return 0;
}
main.h文件
#ifndef SRC_GPIO_M_
#define SRC_GPIO_M_
#include "xparameters.h"
#include "xgpiops.h"
#include "xstatus.h"
#include "xplatform_info.h"
#include <xil_printf.h>
#include "xgpio.h"
#define GPIO_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID
#define KEY 51 //MIO pin (0-53)
#define LED 54 //EMIO pin(EMIO0 为54)
#endif
gpio.c
#include "gpio.h"
int GpioInit(XGpioPs *Gpio, u16 DeviceID){
int Status;
XGpioPs_Config *ConfigPtr;
/* Initialize the GPIO driver. */
ConfigPtr = XGpioPs_LookupConfig(DeviceID);
Status = XGpioPs_CfgInitialize(Gpio, ConfigPtr,
ConfigPtr->BaseAddr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
int GpioOutputSet(XGpioPs *Gpio, int pin){
XGpioPs_SetDirectionPin(Gpio, pin, 1);
XGpioPs_SetOutputEnablePin(Gpio, pin, 1);
return XST_SUCCESS;
}
int GpioInputSet(XGpioPs *Gpio, int pin){
XGpioPs_SetDirectionPin(Gpio, pin, 0x0);
return XST_SUCCESS;
}
void GpioOutputData(XGpioPs *Gpio, int pin, int data){
XGpioPs_WritePin(Gpio, pin, data);
}
int GpioReadData(XGpioPs *Gpio, int pin){
return XGpioPs_ReadPin(Gpio, pin);
}
int AXIgpioInit(XGpio *AXIgpio, u16 DeviceID){
/* Initialize the GPIO driver */
int Status;
Status = XGpio_Initialize(AXIgpio, DeviceID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
void AXIgpioOutputSet(XGpio *AXIgpio, int pin){
XGpio_SetDataDirection(AXIgpio, pin, 0);
}
void AXIgpioInputSet(XGpio *AXIgpio, int pin){
XGpio_SetDataDirection(AXIgpio, pin, 1);
}
void AXIgpioOutputData(XGpioPs *AXIgpio, int pin, int data){
XGpio_DiscreteWrite(AXIgpio, pin, data);
}
int AXIgpioReadData(XGpioPs *AXIgpio, int pin){
return XGpio_DiscreteRead(AXIgpio, pin);
}
gpio.h
#ifndef SRC_GPIO_M_
#define SRC_GPIO_M_
#include "xparameters.h"
#include "xgpiops.h"
#include "xstatus.h"
#include "xplatform_info.h"
#include <xil_printf.h>
#include "xgpio.h"
int GpioInit(XGpioPs *Gpio, u16 DeviceID);
int GpioOutputSet(XGpioPs *Gpio, int pin);
int GpioInputSet(XGpioPs *Gpio, int pin);
void GpioOutputData(XGpioPs *Gpio, int pin , int data);
int GpioReadData(XGpioPs *Gpio, int pin);
int AXIgpioInit(XGpio *AXIgpio, u16 DeviceID);
void AXIgpioOutputSet(XGpio *AXIgpio, int pin);
void AXIgpioInputSet(XGpio *AXIgpio, int pin);
void AXIgpioOutputData(XGpioPs *AXIgpio, int pin, int data);
int AXIgpioReadData(XGpioPs *AXIgpio, int pin);
#endif
501

被折叠的 条评论
为什么被折叠?



