• Xilinx ZYNQ 7000+Vivado2015.2系列(四)之GPIO的三种方式:MIO、EMIO、AXI_GPIO


    前言:

    ZYNQ 7000有三种GPIO:MIO,EMIO,AXI_GPIO

    MIO是固定管脚的,属于PS,使用时不消耗PL资源;EMIO通过PL扩展,使用时需要分配管脚,使用时消耗PL管脚资源;AXI_GPIO是封装好的IP核,PS通过M_AXI_GPIO接口控制PL部分实现IO,使用时消耗管脚资源和逻辑资源。

    使用的板子是zc702。

    1.MIO方式

    Zynq7000 系列芯片有 54 个 MIO(multiuse I/O), 它们分配在 GPIO 的 Bank0 和Bank1 隶属于 PS 部分, 这些 IO 与 PS 直接相连。 不需要添加引脚约束, MIO 信号对 PL部分是透明的, 不可见。 所以对 MIO 的操作可以看作是纯 PS 的操作。

     新建Vivado工程,添加ZYNQ CPU核,双击,配置好时钟和内存类型,确认勾选MIO:

     如系列(三)文章所述,生成bit stream,然后Launch SDK。

    在SDK中新建工程,源文件如下:

    #include "xgpiops.h"
    #include "sleep.h"
    int main()
    {
    static XGpioPs psGpioInstancePtr;
    XGpioPs_Config* GpioConfigPtr;
    int iPinNumber= 8; //DS12连接的是MIO8
    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的第8位输出
    while(1)
    {
    XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1);//点亮MIO的第8位输出1
    usleep(500000); //延时
    XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 0);//熄灭MIO的第8位输出0
    usleep(500000); //延时
    }
    /****************************************************************
    while(1)
    {
    XGpioPs_WriteReg(0xE000A000,0x00000000, 0xFF7FFFFF&0xFFFF0080);
    usleep(500000); //延时
    XGpioPs_WriteReg(0xE000A000,0x00000000, 0xFF7FFFFF&0xFFFF0000);
    usleep(500000); //延时
    } *
    *****************************************************************/
    return 0;
    }


    下载到板子上,DS12就开始闪烁了。

    2.EMIO方式

    EMIO 分配在 bank2 和 bank3 和 PL部分相连。EMIO 有 64 个引脚可供我们使用 。当 MIO 不够用时, PS 可以通过驱动 EMIO 控制 PL 部分的引脚 。

     Vivado工程里ZYNQ CPU核配置,确保EMIO勾选,这里我设置了位宽为4,后面为其分配了四个管脚:

     在Diagram里面将GPIO_0的引脚引出来,生成顶层文件后查看这个引脚的名字,因为我修改了名字,这里叫emio_0_tri_io
    管脚约束文件:

    #GPIO PMOD1
    set_property PACKAGE_PIN E15 [get_ports {emio_0_tri_io[0]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[0]}]
    set_property PACKAGE_PIN D15 [get_ports {emio_0_tri_io[1]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[1]}]
    set_property PACKAGE_PIN W17 [get_ports {emio_0_tri_io[2]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[2]}]
    set_property PACKAGE_PIN W5 [get_ports {emio_0_tri_io[3]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {emio_0_tri_io[3]}]

    SDK部分:MIO号是0~53,EMIO从54开始

    #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;
    }

    下载到板子里,PMOD1的4个led灯交替闪烁。


    3.AXI_GPIO方式

    VIvado工程里,ZYNQ CPU核配置:
    勾选M_AXI_GPIO 接口:

     勾选复位信号:

     给PL的时钟信号:

     加入AXI_GPIO IP,这里设置位宽为4,后面将控制4个led灯:

     自动连接后如下图:

     管脚约束如下:

    #GPIO PMOD1
    set_property PACKAGE_PIN E15 [get_ports {gpio_sw_tri_o[0]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[0]}]
    set_property PACKAGE_PIN D15 [get_ports {gpio_sw_tri_o[1]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[1]}]
    set_property PACKAGE_PIN W17 [get_ports {gpio_sw_tri_o[2]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[2]}]
    set_property PACKAGE_PIN W5 [get_ports {gpio_sw_tri_o[3]}]
    set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_o[3]}]

    SDk部分如下:

    #include <stdio.h>
    #include "platform.h"
    #include "xparameters.h"
    #include "xgpio.h"
    int main() {
        XGpio gpio_led;
        int status;
        int i,x,y;
     
        init_platform();
        status = XGpio_Initialize(&gpio_led, 0);
        if(status == 0){
            printf("success \r\n");
        }
     
        XGpio_SetDataDirection(&gpio_led,1,0);//设置通道1为输出
        while (1){
            for (i = 0; i<=3; i++){
            XGpio_DiscreteWrite(&gpio_led, 1, 0x01<<i);
            for(x =1000; x > 0; x-- ){
                    for (y = 100000; y > 0; y--);
                }
            }
        }
        cleanup_platform();
        return 0;
    }


    可以看到,与EMIO一样需要分配管脚,但是AXI_GPIO使用的头文件是#include "xgpio.h",而EMIO是#include "xgpiops.h"。

    下载完成后,PMOD1 的四个LED灯依次闪烁。


    总结:

    MIO和EMIO使用PS的GPIO,,MIO固定管脚,EMIO手动分配管脚;IP方式手动分配管脚,综合后需要消耗PL的逻辑资源。



    原文链接:https://blog.csdn.net/u014485485/article/details/78141594

    作者:柒月
    Q群 :2122210(嵌入式/机器学习)
  • 相关阅读:
    Algs4-1.1.17找出以下递归函数的问题
    Algs4-1.1.16给出exR1(6)的返回值
    Algs4-1.1.15编写一个静态方法histogram()
    Algs4-1.1.14实现以2为底的对数
    Algs4-1.1.13编写一段代码,打印出一个M行N列的二维数组的转置(交换行和列)
    Algs4-1.1.12以下代码段会打印出什么结果?
    python将一个列表的元素随机打乱
    python 类似java的三目运算符
    java的三元运算符
    java 的Colections类(Java也有python类似列表的反转、排序等方法)
  • 原文地址:https://www.cnblogs.com/Ph-one/p/15571131.html
Copyright © 2020-2023  润新知