首页 > 代码库 > ZYNQ学习之——MIO

ZYNQ学习之——MIO

1、GPIO基础知识

  Zynq7000 系列芯片有 54 个 MIO(multiuse I/O) ,它们分配在 GPIO 的 Bank0 和Bank1 隶属于 PS 部分, 这些 IO 与 PS 直接相连。 不需要添加引脚约束, MIO 信号对 PL部分是不可见,即PL不能对这部分IO信号进行任何操作。 所以对 MIO 的操作可以看作是纯 PS 的操作。 参考芯片手册看到技术分享

  Bank0:MI0[31:0]
  Bank1:MI0[52:53]
  Bank2:EMI0[31:0]
  Bank3:EMI0[63:32]

GPIO 的控制寄存器地址空间

技术分享

技术分享

技术分享

很多寄存器,但是一般的操作关注部分寄存器就可以了。

DATA_RO: 此寄存器使能软件观察 PIN 脚, 当 GPIO 被配置成输出的时候, 这个寄存器的值会反应输出的 PIN 脚情况。
DATA:此寄存器控制输出到 GPIO 的值, 读这个寄存器的值可以读到最后一次写入该寄存器的值。
MASK_DATA_LSW:位操作寄存器, 写入 GPIO 16bit 其他没有改变的位置保存原先的状态
MASK_DATA_MSW:位操作寄存器, 写入 GPIO 16bit 其他没有改变的位置保存原先的状态
DIRM:此寄存器控制输出的开关, 当 DIRM[x]=0 时候, 禁止输出
OEN: 输出使能, 当 OEN[x]=0 的时候输出关闭, PIN 脚处于三态
因此, 如果要读 IO 状态就得读 DATA_RO 的值, 如果是对某一位进行操作就是写
MASK_DATA_LSW/MASK_DATA_MSW
具体的相关参数请参考技术手册 ug585-Zynq-7000-TRM.pdf

2、FPGA硬件创建。

  MIO的操作硬件创建比较简单,外置只需添加MIO外置就可以了。

技术分享

 

 然后编译导出硬件到SDK软件中。

3、SDK软件

  首先就是要创建一个APP工程,这里就不做讲解了。看一下软件设计,就是纯C开发了。

    

           

 #include "xgpiops.h"
 #include "sleep.h"
 int main()
 {
    static XGpioPs psGpioInstancePtr;
    XGpioPs_Config* GpioConfigPtr;
    int iPinNumber= 7; //板子的LED连接的是MIO7,这个根据板子的硬件设计做对应修改
    u32 uPinDirection = 0x1; //设置IO方向。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
      usleep(500000); //us延时
      XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭MIO的第7位输出0
      usleep(500000); //us延时
    }*/

 

    //以下是寄存器的操作方式。

    while(1)

    {
      XGpioPs_WriteReg(0xE000A000,0x00000000, 0xFF7FFFFF&0xFFFF0080);
      usleep(500000); //us延时
      XGpioPs_WriteReg(0xE000A000,0x00000000, 0xFF7FFFFF&0xFFFF0000);
      usleep(500000); //us延时
    }
  return 0;
}

 

 分析以下一些Xilinx的函数:

GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);  查找对应ID设备是否存在,如果不存在出错,如果存在就可以做下一步的初始化。

可以查到

/* Definitions for peripheral PS7_GPIO_0 */
#define XPAR_PS7_GPIO_0_DEVICE_ID 0
#define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000  //这个就是MIO的基地址
#define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF  //这个结束地址不需要管

 

ZYNQ学习之——MIO