1. 程式人生 > 其它 >Xilinx ZYNQ 7000+Vivado2015.2系列(四)之GPIO的三種方式:MIO、EMIO、AXI_GPIO

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

作者:柒月 出處:https://www.cnblogs.com/Ph-one/ 開源:https://github.com/iqiy/ 站點:https://qiy.net/ Q群 :2122210(嵌入式/機器學習)