zoukankan      html  css  js  c++  java
  • 【转】ZYNQ中三种实现GPIO的方式

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/husipeng86/article/details/52123465
     
    本文介绍在zynq中三种实现GPIO的方式,分别为MIO、EMIO和IP方式。
    MIO和EMIO方式是使用PS部分的GPIO模块来实现GPIO功能的,支持54个MIO(可输出三态)、64个输入和128个输出(64个输出和64个输出使能)EMIO

    而IP方式是在PL部分实现 GPIO功能,PS部分通过M_AXI_GP接口来控制该GPIO IP模块;另外EMIO模块虽然使用PS部分GPIO但也使用了PL部分的管脚资源。

     

    MIO方式实现GPIO

    vivado中zynq设置如下图

    mio_vivado中配置

    由图中可见要选中打开GPIO,其下自动显示可用于GPIO的MIO(当MIO作为其他功能时就不能作为GPIO使用了),其中MIO 7、MIO 8只能作为输出使用,因为它们用于VMODE管脚(参考UG585第14章:14.2.3)

    软件部分如下

     1 #include <stdio.h>
     2 #include "platform.h"
     3 #include "xgpiops.h"
     4 
     5 #define LED1    0
     6 #define LED2    9
     7 
     8 static void delay(int dly)
     9 {
    10     int i, j;
    11     for (i = 0; i < dly; i++) {
    12         for (j = 0; j < 0xffff; j++) {
    13             ;
    14         }
    15     }
    16 }
    17 
    18 int main()
    19 {
    20     int Status;
    21     XGpioPs_Config *ConfigPtr;
    22     XGpioPs Gpio;
    23 
    24     init_platform();
    25 
    26     ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
    27     Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
    28                     ConfigPtr->BaseAddr);
    29     if (Status != XST_SUCCESS){
    30         return XST_FAILURE;
    31     }
    32 
    33     XGpioPs_SetDirectionPin(&Gpio, LED1, 1);
    34     XGpioPs_SetDirectionPin(&Gpio, LED2, 1);
    35     XGpioPs_SetOutputEnablePin(&Gpio, LED1, 1);
    36     XGpioPs_SetOutputEnablePin(&Gpio, LED2, 1);
    37 
    38     while (1) {
    39         XGpioPs_WritePin(&Gpio, LED1, 0);
    40         XGpioPs_WritePin(&Gpio, LED2, 1);
    41         delay(1000);
    42         XGpioPs_WritePin(&Gpio, LED1, 1);
    43         XGpioPs_WritePin(&Gpio, LED2, 0);
    44         delay(1000);
    45     }
    46     cleanup_platform();
    47 }

    EMIO方式实现GPIO

    vivado中zynq设置如下图

    emio_vivado中配置

    图中可知GPIO中选择使用EMIO,并选择位宽(这里例子中选择3);其vivado中连接如下图

    emio_vivado中连接

    上图可知除了FIXED IO和DDR接口外,还多了3个3对(一个输入,一个输出和一个输出使能)GPIO管脚。

    不同于MIO,这里三个IO管脚(一个输入,一个输出和一个输出使能在自动生成的顶层模块中合并为一个IO)要绑定到芯片对应管脚上

    软件部分如下

     1 #include <stdio.h>
     2 #include "platform.h"
     3 #include "xgpiops.h"
     4 
     5 #define LED_R   54
     6 #define LED_G   55
     7 #define LED_B   56
     8 #define LED_ON  0
     9 #define LED_OFF 1
    10 
    11 static void delay(int dly)
    12 {
    13     int i, j;
    14     for (i = 0; i < dly; i++) {
    15         for (j = 0; j < 0xffff; j++) {
    16             ;
    17         }
    18     }
    19 }
    20 
    21 int main()
    22 {
    23     int Status;
    24     XGpioPs_Config *ConfigPtr;
    25     XGpioPs Gpio;
    26 
    27     init_platform();
    28 
    29     ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
    30     Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
    31                     ConfigPtr->BaseAddr);
    32     if (Status != XST_SUCCESS) {
    33         print("cfg init err
    ");
    34         return XST_FAILURE;
    35     }
    36     XGpioPs_SetDirectionPin(&Gpio, LED_R, 1);
    37     XGpioPs_SetOutputEnablePin(&Gpio, LED_R, 1);
    38     XGpioPs_SetDirectionPin(&Gpio, LED_G, 1);
    39     XGpioPs_SetOutputEnablePin(&Gpio, LED_G, 1);
    40     XGpioPs_SetDirectionPin(&Gpio, LED_B, 1);
    41     XGpioPs_SetOutputEnablePin(&Gpio, LED_B, 1);
    42 
    43     while (1) {
    44         XGpioPs_WritePin(&Gpio, LED_R, LED_ON);
    45         delay(1000);
    46         XGpioPs_WritePin(&Gpio, LED_G, LED_ON);
    47         delay(1000);
    48         XGpioPs_WritePin(&Gpio, LED_B, LED_ON);
    49         delay(1000);
    50         XGpioPs_WritePin(&Gpio, LED_R, LED_OFF);
    51         delay(1000);
    52         XGpioPs_WritePin(&Gpio, LED_G, LED_OFF);
    53         delay(1000);
    54         XGpioPs_WritePin(&Gpio, LED_B, LED_OFF);
    55         delay(1000);
    56     }
    57     cleanup_platform();
    58 }

    类似MIO方式(都为PS部分GPIO操作),设置为输出并设置输出使能,但要注意这里的GPIO号是从54开始的3个。

    IP方式实现GPIO

    vivado中zynq设置如下图

    axi_gpio_vivado中配置

    图中可知GPIO中MIO和EMIO都不选择,但要打开M_AXI_GP接口(这里选择M_AXI_GP0)和复位管脚,如下图

    axi_gpio_vivado中配置_GP和复位

    当然用到了PL部分逻辑则至少需要一个时钟输出到PL部分,这里选择FCLK_CLK0输出50MHz,如下图

    axi_gpio_vivado中配置_时钟

    推荐加入zynq后,不要自动连接,再加入gpio并位宽设置为3,具体设置如下图

    axi_gpio_ip设置

    GPIO设置好后,再点击上面的蓝色字体的自动连接,即可得到上面的连接,这样可以减少手动连接量。

    最后vivado中连接如下图

    axi_gpio_vivado中连接

    与EMIO类似需要将顶层三个GPIO管脚要绑定到芯片对应管脚上。

    软件部分如下

     1 #include <stdio.h>
     2 #include "platform.h"
     3 #include "xgpio.h"
     4 
     5 #define AXI_GPIO_DEVICE_ID  XPAR_GPIO_0_DEVICE_ID
     6 #define XGPIO_BANK1         1
     7 #define XGPIO_BANK2         2
     8 
     9 #define LED34_R_PIN         0x01
    10 #define LED34_G_PIN         0x02
    11 #define LED34_B_PIN         0x04
    12 
    13 static void delay(int dly)
    14 {
    15     int i, j;
    16     for (i = 0; i < dly; i++) {
    17         for (j = 0; j < 0xffff; j++) {
    18             ;
    19         }
    20     }
    21 }
    22 
    23 int main()
    24 {
    25     XGpio_Config *XGpioCfg;
    26     XGpio XGpio;
    27     int Status;
    28 
    29     init_platform();
    30 
    31     XGpioCfg = XGpio_LookupConfig(AXI_GPIO_DEVICE_ID);
    32     Status = XGpio_CfgInitialize(&XGpio, XGpioCfg, XGpioCfg->BaseAddress);
    33     if (Status != XST_SUCCESS) {
    34         return XST_FAILURE;
    35     }
    36 
    37     XGpio_SetDataDirection(&XGpio, XGPIO_BANK1, ~(LED34_R_PIN | LED34_G_PIN | LED34_B_PIN));
    38     XGpio_DiscreteWrite(&XGpio, XGPIO_BANK1, LED34_R_PIN | LED34_G_PIN | LED34_B_PIN);
    39     while (1) {
    40         XGpio_DiscreteWrite(&XGpio, XGPIO_BANK1, ~LED34_R_PIN);
    41         delay(1000);
    42         XGpio_DiscreteWrite(&XGpio, XGPIO_BANK1, ~(LED34_R_PIN | LED34_G_PIN));
    43         delay(1000);
    44         XGpio_DiscreteWrite(&XGpio, XGPIO_BANK1, ~(LED34_R_PIN | LED34_G_PIN | LED34_B_PIN));
    45         delay(1000);
    46         XGpio_DiscreteWrite(&XGpio, XGPIO_BANK1, ~(LED34_G_PIN | LED34_B_PIN));
    47         delay(1000);
    48         XGpio_DiscreteWrite(&XGpio, XGPIO_BANK1, ~(LED34_B_PIN));
    49         delay(1000);
    50         XGpio_DiscreteWrite(&XGpio, XGPIO_BANK1, LED34_R_PIN | LED34_G_PIN | LED34_B_PIN);
    51         delay(1000);
    52     }
    53     cleanup_platform();
    54     return 0;
    55 }

    这里实现的功能与EMIO方式中功能相同,当时IP方式中为PL部分实现的GPIO,所以调用的函数与前面两种GPIO实现函数不同,注意包含的GPIO头文件,前两种是#include "xgpiops.h"而这最后一种为#include "xgpio.h"

     

    总结

    MIO和EMIO方式使用PS部分的GPIO模块,其中MIO方式不占用PL部分资源,其输出管脚只能为固定的54个(而且要在未被其它外设使用的情况下),EMIO方式会占用PL的管脚资源,其管脚可在PL部分任意选择(除特殊功能管脚),IP方式除了占用PL部分管脚资源外还会占用PL部分逻辑资源,所以其GPIO功能在PL部分实现其调用函数也和前两种不同,最后EMIO和IP方式在vivado都需要绑定管脚。

  • 相关阅读:
    越狱第三季开播了
    永远成长的苹果树
    最强最短的武侠小说
    买房和租房15年后的巨大差别[好文转载]
    秋凉了,大家别加班了,早回吧:)
    dedecms dede_archives表中arcrank和ismake两个字段的理解
    asp.net c#读取word 文档的方法
    css实现不固定长度圆角按钮,兼容所有浏览器
    js keyup、keypress和keydown事件 详解
    android中使用webview缓存网页
  • 原文地址:https://www.cnblogs.com/xianyufpga/p/11431142.html
Copyright © 2011-2022 走看看