一、EMIO简介
ZYNQ GPIO 接口信号被分成四组,分别是从 BANK0 到 BANK3。其中 BANK0 和 BANK1 中共计 54个信号通过 MIO 连接到 ZYNQ 器件的引脚上,这些引脚属于 PS 端; 而 BANK2 和 BANK3 中共计 64 个信号则通过 EMIO 连接到了 ZYNQ 器件的 PL 端, 如下图所示:

在大多数情况下, PS 端经由 EMIO 引出的接口会直接连接到 PL 端的器件引脚上, 通过 IO 管脚约束来指定所连接 PL 引脚的位置。 通过这种方式, EMIO 可以为 PS 端实现额外的 64 个输入引脚或 64 个带有输出使能的输出引脚。 EMIO 还有一种使用方式,就是用于连接 PL 内实现的功能模块( IP 核) , 此时 PL 端的 IP 作为 PS 端的一个外部设备, 如图 4.1.2 所示:

EMIO:扩展MIO,是PS与PL端的接口,当PS引脚不够用时,可以拓展EMIO使用PL端引脚


二、实验任务
本章的实验任务是使用 Z100 底板上的两个用户按键分别控制 PS 端两个 LED 的亮灭。其中一个按键PL_KEY0 连接到了 PL 端, 需要通过 EMIO 进行扩展,另外一个按键是底板上 PS 端的用户按键 PS_KEY0,这两个按键分别控制 PS_LED0 和 PS_LED1,底板上的 PS_KEY0 控制 PS_LED0、 PL_KEY0 控制 PS_LED1。两个 LED 灯在按键按下的时候点亮,释放后熄灭
三、程序设计

1、整体框图:

2、硬件设计
根据实际需要选择位宽




对EMIO进行管脚约束
set_property -dict {PACKAGE_PIN J13 IOSTANDARD LVCMOS18} [get_ports GPIO_0_0_tri_io[0]] 





 
 

代码编写:
注意bank地址!!!
#include <stdio.h>
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#define GPIO_DEVICE_ID		XPAR_XGPIOPS_0_DEVICE_ID
#define MIO_LED1      7//MIO7
#define MIO_LED2      8//MIO8
#define MIO_LED0      0//MIO0
#define MIO_KEY0      12//MIO12
#define EMIO_KEY0     54//EMIO54
XGpioPs Gpio;	/* The driver instance for GPIO Device. */
int main(){
	XGpioPs_Config *ConfigPtr;
	u32 ps_key;
	u32 pl_key;
	//初始化GPIO驱动配置
	//根据器件ID来查找器件配置信息
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	//对GPIO的驱动进行初始化
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
	//设置引脚方向
	XGpioPs_SetDirectionPin(&Gpio, MIO_LED1, 1);
	XGpioPs_SetDirectionPin(&Gpio, MIO_LED2, 1);
	XGpioPs_SetDirectionPin(&Gpio, MIO_LED0, 1);
	//设置PS_KEY
	XGpioPs_SetDirectionPin(&Gpio, MIO_KEY0, 0);
	//设置PL_KEY
	XGpioPs_SetDirectionPin(&Gpio, EMIO_KEY0, 0);
	//设置输出使能   0:输入    1:输出
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED1, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED2, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED0, 1);
	printf("GPIO MIO TEXT!\n");
	while(1){
		ps_key = XGpioPs_ReadPin(&Gpio,MIO_KEY0);
		pl_key = XGpioPs_ReadPin(&Gpio,EMIO_KEY0);
		XGpioPs_WritePin(&Gpio, MIO_LED1, ps_key);
		XGpioPs_WritePin(&Gpio, MIO_LED2, pl_key);
		XGpioPs_WritePin(&Gpio, MIO_LED0, ps_key);
	}
	return 0 ;
}
 


四、下载验证

五、总结

六、拓展训练


约束管脚
set_property -dict {PACKAGE_PIN J13 IOSTANDARD LVCMOS18} [get_ports GPIO_0_0_tri_io[0]]
set_property -dict {PACKAGE_PIN H13 IOSTANDARD LVCMOS18} [get_ports GPIO_0_0_tri_io[1]] 
重新生成硬件信息

代码编写:
#include <stdio.h>
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#define GPIO_DEVICE_ID		XPAR_XGPIOPS_0_DEVICE_ID
#define MIO_LED1      7//MIO7
#define MIO_LED2      8//MIO8
#define MIO_LED0      0//MIO0
#define MIO_KEY0      12//MIO12
#define EMIO_KEY0     54//EMIO54
#define EMIO_KEY1     55//EMIO54
XGpioPs Gpio;	/* The driver instance for GPIO Device. */
int main(){
	XGpioPs_Config *ConfigPtr;
	u32 ps_key;
	u32 pl_key1;
	u32 pl_key2;
	//初始化GPIO驱动配置
	//根据器件ID来查找器件配置信息
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	//对GPIO的驱动进行初始化
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
	//设置引脚方向
	XGpioPs_SetDirectionPin(&Gpio, MIO_LED1, 1);
	XGpioPs_SetDirectionPin(&Gpio, MIO_LED2, 1);
	XGpioPs_SetDirectionPin(&Gpio, MIO_LED0, 1);
	//设置PS_KEY
	XGpioPs_SetDirectionPin(&Gpio, MIO_KEY0, 0);
	//设置PL_KEY
	XGpioPs_SetDirectionPin(&Gpio, EMIO_KEY0, 0);
	XGpioPs_SetDirectionPin(&Gpio, EMIO_KEY1, 0);
	//设置输出使能   0:输入    1:输出
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED1, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED2, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED0, 1);
	printf("GPIO MIO TEXT!\n");
	while(1){
		ps_key = XGpioPs_ReadPin(&Gpio,MIO_KEY0);
		pl_key1 = XGpioPs_ReadPin(&Gpio,EMIO_KEY0);
		pl_key2 = XGpioPs_ReadPin(&Gpio,EMIO_KEY1);
		XGpioPs_WritePin(&Gpio, MIO_LED1, ps_key);
		XGpioPs_WritePin(&Gpio, MIO_LED2, pl_key1);
		XGpioPs_WritePin(&Gpio, MIO_LED0, pl_key2);
	}
	return 0 ;
}
 
编译执行:
















![[LLM 学习笔记] Transformer 基础](https://i-blog.csdnimg.cn/direct/4b3335aae0e840e884d9f4450fc02c97.png)




