ZYNQ7000 系列芯片有54个MIO(multiuse I/O),它们分配在GPIO的Bank0和NBank1 隶属于PS的部分,这些IO与PS直接相连。不需要添加引脚约束,MIO信号对PL部分是透明的,不可见。所以对MIO的操作可以看是对纯PS的操作。
GPIO的控制和状态寄存器的基地址为:0xE000_A000,在SDK下对软件操作底层都是对应于内存地址空间的操作。
可以看到 bank0和bank1属于MIO,一共有54个端口。bank2和bank3属于EMIO,一共有64个端口。
Bank0:MIO[31:0]
Bank1: MIO[53:32]
Bank2: EMIO[31:0]
Bank3: EMIO[63:32]
其中Bank0有32个GPIO引脚,Bank1有22个GPIO引脚,共54个GPIO引脚直接通过MIO连接到PS上,每个引脚可以通过寄存器设置来确定该引脚为输入、输出或者中断。因为54个MIO引脚直接连接到PS上,像其他普通ARM一样可以直接通过SDK进行编程。
Bank2和Bank3通过EMIO接口将CPU的GPIO连接到PL部分的引脚上,其中每个Bank各有32个引脚。通过EMIO扩展的GPIO连接到Pl上,可以在PL部分进行逻辑设计,进行特定功能的IP核定制。然后在PS部分,想控制普通的MIO一样进行编程。ui那次,使用EMIO引脚必须通过Block Dedign 金总设计,然后再PS部分使用SDK进行编程控制
DATA_R0: DATA_R0 寄存器是读取GPIO引脚值寄存器,不论该GPIO引脚配置为输入还是输出,都能正确的读取该GPIO引脚值。如果该引脚的功能没有配置为GPIO功能,读取的值为随机值,因为该寄存器只能读取GPIO引脚值。
DATA: 当GPIO引脚配置为输出时,DATA寄存器的值是要输出到GPIO引脚上的数值。当读取该寄存器的数值时,结果是前一次写入DATA寄存器里的数值,而不是当前GPIO引脚的数值。
MASK_DATA_LSW/MASK_DATAMSW: MASK_DATA_LSW/MASK_DATAMSW 是传统的数据寄存器和屏蔽寄存器的结合,该寄存器为32为,分成高16位和低16位,其中高16位作为传统的MASK使用,低16位作为传统的DATA使用。因此,MASK_DATA_LSW是对GPIO的低16位引脚进行设置和屏蔽寄存器。当某位在MASK_DATA_LSW寄存器的高16位被屏蔽时,即使修改MASK_DATA_LSW的低16位也不影响该寄存器的值。
DIRM: DIRM寄存器是方向控制寄存器,控制GPIO的输入或者输出,该寄存器值不影响输入,即GPIO输入功能时钟有效。当DIRM[x] = 0 时,输出无效。
OEN: OEN是输出使能寄存器,当GPIO引脚被配置为输出引脚时,该寄存器控制该引脚是否输出;当被配置为输出禁止时,该引脚为三态;当OEN[x] = 0时输出无效。
GPIO slcr: MIO的每个引脚都可以配置乘其他的功能,因此,在对MIO引脚进行编程时,首先要把对赢得MIO引脚设置乘GPIO功能,同时设置对应的电平和是否上拉等,每个引脚对应的寄存器进行设置,这些寄存器是系统控制寄存器(slcr)MIO_PIN_x.
与MIO大部分类似,但是以下几点需要注意。
在米联系列的开发板上有一个MIO是与开发板上的一个LD9相连接的,这个MIO就是MIO7。实验通过操作该MIo来实现LD9的闪烁。
step1: 新建一个名称为Miz_sys的工程,正确配芯片型号,正确配置时钟频率与内存。
step2;:单击 Create Block Design,创建一个BD文件,并命名为System.
step3:加入一个ZYNQ CPU IP,正确配置时钟频率核内存类型。
step4: 由于本小节需要用到MIO接口,因此需要确保MIO接口已经勾选(默认勾选)
step5: 单击OK 后退出,系统整体电路如下。
step6: 右击 system.bd, 单击 Generate Output Products。
Step7:右击 system.bd 选择 Create HDL Wrapper 产生顶层的 HDL 文件。
Step8:File->Export->Export Hardware。
Step9:勾选 Include bitstream 直接单击 OK。
Step10:File->Launch SDK 加载到 SDK,单击 OK。
step1: 在SDK界面中,新建一个名称为MIO_Test的工程
step2: 建立一个空的工程
step3:新建一个main.c文件
step4:输入以下程序
#include "xgpiops.h" //此头文件中包含了关于GPIO操作的相关定义与函数
#include "sleep.h" //延迟或者定时函数头文件
int main()
{
static XGpioPs psGpioInstancePtr;
XGpioPs_Config* GpioConfigPtr;
int iPinNumber = 7; //LD9连接的是MIO7
u32 uPinDirection = 0x01; //设置输入、输出方向,1表示输出,0表示输入
int xStatus;
//MIO的初始化,也就是设置MIO的输出和输出等配置
GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
if(GpioConfigPtr == NULL)
return XST_FAILURE; //查找MIO失败的话,直接返回,否则执行下面的程序。
xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr->BaseAddr);
if (XST_SUCCESS != xStatus)
print("PS GPIO INIT FAILED \n\r "); //初始化失败
XGpioPs_SetDirectionPin(&psGpioInstancePtr,iPinNumber,uPinDirection); //配置MIO7为输出
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr,iPinNumber,1); //因为配置为输出后还需要使能输出,这里就是使能输出
while(1)
{
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,1);//设置MIO7输出1,点亮LD9
sleep(1); //延时1秒
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);//设置MIO7输出0,熄灭LD9
sleep(1); //延时1秒
}
return 0;
}
step5:给开发板上电,下载程序。可以看到开发板上的LD9以1秒的周期在闪烁。