ZYNQ-7000 GPIO使用

1 ZYNQ-7000 GPIO介绍

  • GPIO(Generous Purpose Input Output)是指CPU引出的,可以配置为输入或输出的端口,用于CPU与外界进行数据的传输。
  • ZYNQ-7000 架构由 PL+PS 组成,所以它的 GPIO 与一般的 ARM 不同。ZYNQ 的 GPIO,分为两种,MIO(multiuse I/O)和 EMIO(extendable multiuse I/O)
  • MIO 有54个,分配在 GPIO 的 Bank0 和 Bank1 隶属于 PS 部分,这些 IO 与 PS 直接相连。不需要添加引脚约束,MIO 信号对 PL 部分是透明的,不可见。
  • EMIO有64个,EMIO连接PS到PL,作为ZYNQ的拓展MIO,当 MIO 不够用时,PS 可以通过驱动 EMIO 控制 PL 部分的引脚。因此使用PS的EMIO时,需要添加PL引脚约束。
    在这里插入图片描述
  • Bank0:MIO [31:0] GPIO PIN 脚号:0~31
    Bank1:MIO [32:53] GPIO PIN 脚号:32~53
    Bank2:EMIO [31:0] GPIO PIN 脚号:54~85
    Bank3:EMIO [63:32] GPIO PIN脚号:86~ 117
  • 因此我们要注意,在分配外设控制器管脚时,EMIO的那些要在PL端进行约束,MIO也要仔细阅读米联开发板相关文档。注意引脚的连接是否正确。
    在这里插入图片描述
  • SD卡控制器,串口控制器和网口控制器直接通过MIO与外设互联,不需要PL约束。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • SPI控制器通过EMIO引出到PL,并在PL进行管脚约束。
    在这里插入图片描述
    在这里插入图片描述

2 ZYNQ-7000 GPIO控制器介绍

  • MIO和EMIO的内部构造如下图所示
    在这里插入图片描述
  • 主要的配置寄存器有下列几个:
    DATA_RO:通过这个寄存器获取GPIO的输入值,当GPIO被配置为输出时,这个寄存器的值会反应输出的 PIN 脚的情况。
    DATA:此寄存器控制输出到 GPIO 的值,读这个寄存器的值可以读到最后一次写入该寄存器的值。
    MASK_DATA_LSW:低16位根据高16位的掩码情况写入DATA的低16位,被掩盖的位保持之前的值。
    MASK_DATA_MSW:低16位根据高16位的掩码情况写入DATA的高16位,被掩盖的位保持之前的值。
    DIRM:此寄存器控制GPIO为输入或输出,输入总是使能的,所以它只控制是否输出,DIRM[x]==0时输出被禁止。
    OEN:输出使能控制寄存器,当 OEN[x]==0 的时候输出关闭,PIN 脚处于三态。
  • 因此 ,如果要读IO状态就得读DATA_RO的值,如果是对某一位进行操作就是写 MASK_DATA_LSW、MASK_DATA_MSW。
  • EMIO与 MIO 大部分类似,输出不能设置成三态,EMIO 在 PL 部分,输入与 OEN 寄存器无关。

3 MIO的使用

3.1 PL逻辑设计

  • 米联MZ7100FA开发板上有一个 MIO 是与开发板上的一个 LD9 相连的,这个 MIO 就是 MIO7。实验通过操作该 MIO 来实现LD9 的闪烁。输出为高电平时该LED灯亮。
    在这里插入图片描述
  • 搭建zynq最小系统后,勾选GPIO MIO,会自动将未用到的MIO管脚选中。
    在这里插入图片描述
  • 生成bitstream后导出到SDK,在SDK中创建裸机PS工程。

3.2 PS程序设计

//main.c
#include "xgpiops.h"
#include "sleep.h"
int main()
{
	static XGpioPs psGpioInstancePtr;
	XGpioPs_Config* GpioConfigPtr;
	int iPinNumber= 7;			//LD9连接的是MIO7
	u32 uPinDirection = 0x1;	//1表示输出,0表示输入
	int xStatus;

	//--MIO的初始化
    GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
	if(GpioConfigPtr == NULL)
		return XST_FAILURE;
	xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr, GpioConfigPtr->BaseAddr);
	if(XST_SUCCESS != xStatus)
		print(" PS GPIO INIT FAILED \n\r");
		
	//--MIO的输入输出操作
     XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);//配置MIO输出方向
	 XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);//配置MIO的第7位输出
	 
	 while(1)
	 {
		XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);//点亮MIO的第7位输出1
		sleep(1);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭MIO的第7位输出0
		sleep(1);	//延时
	 }

    return 0;
}
  • XGpioPs是一个局部的静态结构体,用户操作的每一个GPIO端口都要分配一个这样的结构体。
    在这里插入图片描述
XGpioPs_LookupConfig
  • 根据device_id在SDK导出的bsp库中查找相关板级信息,并返回指向该数据的指针。
    在这里插入图片描述
XGpioPs_CfgInitialize
  • 根据指向板级信息的指针初始化用户的XGpioPs结构体。
    在这里插入图片描述
  • 根据芯片的不同类型初始化Bank和MaxPinNum。
    在这里插入图片描述
  • 关闭所有Banks的中断。
    在这里插入图片描述
    在这里插入图片描述
XGpioPs_SetDirectionPin
  • 设置某一pin脚的方向。
    在这里插入图片描述
  • XGpioPs_GetBankPin函数用于计算PinNumber在哪一个Bank的第几号位置。
    在这里插入图片描述
  • XGpioPs_ReadReg读取特定地址的寄存器值,在这里读取XGPIOPS_DIRM_OFFSET寄存器的值。根据用户输入输出配置进行相关设置后,再用XGpioPs_WriteReg写回到该寄存器中。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
XGpioPs_SetOutputEnablePin
  • 设置特定管脚的输出使能。
    在这里插入图片描述
  • 读取XGPIOPS_OUTEN_OFFSET寄存器后,进行相关设置后写回。
    在这里插入图片描述
XGpioPs_WritePin
  • 向特定的GPIO管脚写数据,注意一次写1bit,但形参是unsigned int,有效的是最低位。
    在这里插入图片描述
XGpioPs_ReadPin
  • 读取特定GPIO管脚的数据,注意一次读取1bit,但返回类型是unsigned int,有效的是最低位。注意最后和1进行了按位与。在这里插入图片描述
    在这里插入图片描述

4 EMIO的使用

4.1 PL逻辑设计

  • PS通过EMIO连接到了PL端,所以使用EMIO需要在PL端进行FPGA引脚约束,在米联MZ7100FA开发板上PL端连接了4个LED灯,在PS端通过EMIO控制它们实现流水灯。
    在这里插入图片描述
  • 选择使用4bit的EMIO,然后引出至PL,并添加xdc引脚约束。
    在这里插入图片描述
    在这里插入图片描述
set_property PACKAGE_PIN E13 [get_ports {EMIO_0_tri_io[0]}]
set_property IOSTANDARD LVCMOS15 [get_ports {EMIO_0_tri_io[0]}]

set_property PACKAGE_PIN E12 [get_ports {EMIO_0_tri_io[1]}]
set_property IOSTANDARD LVCMOS15 [get_ports {EMIO_0_tri_io[1]}]

set_property PACKAGE_PIN F13 [get_ports {EMIO_0_tri_io[2]}]
set_property IOSTANDARD LVCMOS15 [get_ports {EMIO_0_tri_io[2]}]

set_property PACKAGE_PIN H13 [get_ports {EMIO_0_tri_io[3]}]
set_property IOSTANDARD LVCMOS15 [get_ports {EMIO_0_tri_io[3]}]

4.2 PS程序设计

  • 程序逻辑与MIO基本相同,但要注意,EMIO的起始编号从54开始,所以我们使用的4bit GPIO实际编号是54-57。
#include "xgpiops.h"
#include "sleep.h"

int main()
{
	static XGpioPs psGpioInstancePtr;
	XGpioPs_Config* GpioConfigPtr;
	int xStatus;

	//-- EMIO的初始化
    GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
	if(GpioConfigPtr == NULL)
		return XST_FAILURE;
	xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr, GpioConfigPtr->BaseAddr);
	if(XST_SUCCESS != xStatus)
		print(" PS GPIO INIT FAILED \n\r");
		
	//--EMIO的输入输出操作
	 XGpioPs_SetDirectionPin(&psGpioInstancePtr, 54,1);
     XGpioPs_SetDirectionPin(&psGpioInstancePtr, 55,1);
     XGpioPs_SetDirectionPin(&psGpioInstancePtr, 56,1);
     XGpioPs_SetDirectionPin(&psGpioInstancePtr, 57,1);

     //使能EMIO输出
     XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 54,1);
     XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 55,1);
     XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 56,1);
     XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 57,1);

	 while(1)
	 {
		XGpioPs_WritePin(&psGpioInstancePtr, 54, 1);//EMIO的第0位输出1
		usleep(200000);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, 54, 0);//EMIO的第0位输出0
		usleep(200000);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, 55, 1);//EMIO的第1位输出1
		usleep(200000);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, 55, 0);//EMIO的第1位输出0
		usleep(200000);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, 56, 1);//EMIO的第2位输出1
		usleep(200000);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, 56, 0);//EMIO的第2位输出0
		usleep(200000);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, 57, 1);//EMIO的第3位输出1
		usleep(200000);	//延时
		XGpioPs_WritePin(&psGpioInstancePtr, 57, 0);//EMIO的第3位输出0
		usleep(200000);	//延时
	 }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值