zynq中常用几种gpio小结

本文详细介绍了ZYNQ平台上的三种GPIO实现方式:MIO、EMIO和AXI_GPIO。MIO和EMIO直接挂在PS上,分别固定分布于BANK0、BANK1和BANK2、BANK3,而AXI_GPIO通过AXI总线连接。文章对比了三种方式的特性,包括管脚分配、资源占用及软件调用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载链接:https://blog.youkuaiyun.com/husipeng86/article/details/52123465

三种GPIO的介绍

学了zynq一段时间,一上来的时候就被zynq的GPIO唬住了,实在没搞清楚zynq的GPIO怎么回事,一会这样,一会那样,最后才慢慢发现zynq至少有3种GPIO可以调用。难怪我觉得每篇介绍GPIO的博客说的有一些不一样呢。

我们先看有哪三种GPIO:MIO、EMIO、AXI_GPIO。其中MIO和EMIO是直接挂在PS上的GPIO。而AXI_GPIO是通过AXI总线挂在PS上的GPIO上。

我们先看一下MIO和EMIO:下图EMIO和MIO的结构。其中MIO分布在BANK0,BANK1,而EMIO则分布在BANK2、BANK3。注意一下几项:

首先、MIO在zynq上的管脚是固定的,而EMIO,是通过PL部分扩展的,所以使用EMIO时候需要在约束文件中分配管脚,所以设计EMIO的程序时,

需要生成PL部分的bit文件,烧写到FPGA中。

其次、由下图可以看出MIO共占54bit,而EMIO占64bit。其中MIO占用IO号为0-53。而EMIO占用IO号为54-117。

再者、无论是EMIO还是MIO都属于PS上的IO,直接由PS操作。在调用头文件,只调用#include "xgpiops.h"即可,而在调用AXI_GPIO时,则需要#include "xgpio.h"。

最后、在设计好bd文件后、系统会自动在路径:..\standalone_bsp_0\ps7_cortexa9_0\include生成 xparameters.h文件.我们可以在

xparameters.h文件中查看我们在bd设计时添加的外设ID。例如我们添加了EMIO,可以查到到该IO的地址和ID号。
  1. #define XPAR_PS7_GPIO_0_DEVICE_ID 0  
  2. #define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000  
  3. #define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF  
再举例添加了两个AXI_GPIO,例化为BTNS_4BIT和SW_4BIT
  1. /* Definitions for driver GPIO */  
  2. #define XPAR_XGPIO_NUM_INSTANCES 2  
  3.   
  4. /* Definitions for peripheral BTNS_4BIT */  
  5. #define XPAR_BTNS_4BIT_BASEADDR 0x41210000  
  6. #define XPAR_BTNS_4BIT_HIGHADDR 0x4121FFFF  
  7. #define XPAR_BTNS_4BIT_DEVICE_ID 0  
  8. #define XPAR_BTNS_4BIT_INTERRUPT_PRESENT 0  
  9. #define XPAR_BTNS_4BIT_IS_DUAL 0  
  10.   
  11.   
  12. /* Definitions for peripheral SW_4BIT */  
  13. #define XPAR_SW_4BIT_BASEADDR 0x41200000  
  14. #define XPAR_SW_4BIT_HIGHADDR 0x4120FFFF  
  15. #define XPAR_SW_4BIT_DEVICE_ID 1  
  16. #define XPAR_SW_4BIT_INTERRUPT_PRESENT 0  
  17. #define XPAR_SW_4BIT_IS_DUAL 0  


再来看一下,AXI_GPIO相当于GPIO的IP核,我们调用时是占用相应AXI总线地址空间,如下图,占用地址为0x41200000和0x41210000



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

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

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

这里实现的功能与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都需要绑定管脚。

<think>好的,我现在需要回答用户关于Zynq中AXI GPIO和普通GPIO区别的问题。首先,我需要回忆自己之前学过的Zynq架构知识,并确保信息的准确性。 用户可能是一位刚开始学习Zynq的工程师或学生,对PS和PL部分的GPIO使用不太清楚。他们可能在使用开发板时遇到了配置问题,或者在设计时需要选择合适的GPIO模块,因此需要明确两者的区别和应用场景。 首先,我应该明确Zynq的结构,它分为处理系统(PS)和可编程逻辑(PL)。PS部分有自带的GPIO控制器,而AXI GPIO是位于PL部分的IP核,通过AXI总线连接到PS。接下来,我需要比较两者的不同点,比如物理位置、访问方式、功能灵活性等。 需要注意的是,AXI GPIO是通过内存映射的寄存器来控制的,而PS的GPIO可能更直接。还要考虑性能差异,比如PS GPIO的访问速度可能更快,因为直接集成在处理器内部,而AXI GPIO需要经过总线,可能存在延迟。此外,AXI GPIO可以扩展更多的IO口,这在PS GPIO数量不足时非常有用。 可能还需要提到应用场景,比如当需要连接PL外设时,使用AXI GPIO更合适;而简单的控制信号可以用PS自带的GPIO。同时,配置方式的不同,AXI GPIO需要配置PL部分,而PS GPIO直接在软件中设置。 要确保解释清晰,避免术语混淆,可能需要用例子说明。例如,当用户需要驱动一个PL中的LED时,使用AXI GPIO,而控制PS端的引脚如MIO时,使用PS GPIO。 最后,总结两者的区别,帮助用户做出选择。检查是否有遗漏的关键点,比如中断支持、电源域差异或者时钟管理等方面是否需要提及。不过根据常见问题,可能主要关注访问方式、位置和用途即可。</think>在Zynq-7000 SoC中,**AXI GPIO** 和 **PS端GPIO(MIO/EMIO)** 是两种不同类型的GPIO控制器,它们的区别主要体现在硬件架构、访问方式和应用场景上: --- ### 一、物理位置与硬件架构 | **特性** | **PS GPIO (MIO/EMIO)** | **AXI GPIO** | |----------------|-------------------------------------------|------------------------------------------| | **物理位置** | 集成在PS(Processing System)内部 | 位于PL(Programmable Logic)中的IP核 | | **硬件资源** | 直接由PS的GPIO控制器管理 | PL逻辑实现的GPIO扩展模块,通过AXI总线连接PS | | **引脚类型** | MIO(直接连接PS引脚)或EMIO(通过PL扩展) | 完全通过PL的IO引脚(需绑定到FPGA引脚) | --- ### 二、访问方式与性能 | **特性** | **PS GPIO** | **AXI GPIO** | |----------------|-------------------------------------------|------------------------------------------| | **访问路径** | 直接通过CPU寄存器操作(内存映射到PS地址空间) | 通过AXI总线访问PL中的寄存器(需要AXI接口协议) | | **延迟** | 低延迟(直接访问) | 较高延迟(需跨PS-PL通信) | | **带宽** | 高带宽(PS内部总线) | 受AXI总线带宽限制 | --- ### 三、功能与灵活性 | **特性** | **PS GPIO** | **AXI GPIO** | |----------------|-------------------------------------------|------------------------------------------| | **扩展能力** | 固定数量(Zynq-7000通常最多64个MIO + 64个EMIO) | 可自由扩展(通过PL逻辑实现多组GPIO) | | **功能定制** | 固定功能(输入/输出/中断) | 可定制逻辑(例如添加PWM、编码器等) | | **中断支持** | 原生支持中断 | 需手动配置中断逻辑(通过AXI Interrupt Controller) | --- ### 四、典型应用场景 | **场景** | **PS GPIO** | **AXI GPIO** | |------------------------|-------------------------------------------|------------------------------------------| | **简单控制** | 控制PS端外设(如LED、按键) | 控制PL端外设(如自定义IP模块) | | **高速响应需求** | 实时性要求高的任务(如中断触发) | 对实时性要求较低的任务 | | **资源不足时** | 当MIO/EMIO引脚用完时 | 作为补充扩展更多GPIO | --- ### 五、软件配置差异 1. **PS GPIO** - 通过`xparameters.h`和`xgpiops.h`库直接操作。 - 示例代码: ```c #include "xgpiops.h" XGpioPs_Config *Config = XGpioPs_LookupConfig(XPAR_XGPIOPS_0_DEVICE_ID); XGpioPs_CfgInitialize(&Gpio, Config, Config->BaseAddr); XGpioPs_SetDirectionPin(&Gpio, PIN_NUM, 1); // 设置为输出 XGpioPs_SetOutputEnablePin(&Gpio, PIN_NUM, 1); ``` 2. **AXI GPIO** - 需要初始化AXI总线并访问PL寄存器。 - 示例代码: ```c #include "xgpio.h" XGpio_Initialize(&Gpio, XPAR_AXI_GPIO_0_DEVICE_ID); XGpio_SetDataDirection(&Gpio, CHANNEL, 0x00); // 设置通道为输出 XGpio_DiscreteWrite(&Gpio, CHANNEL, 0x01); // 写入数据 ``` --- ### 六、总结对比表 | **维度** | **PS GPIO** | **AXI GPIO** | |----------------|-----------------------------|----------------------------| | **定位** | PS原生资源 | PL扩展资源 | | **延迟** | 低 | 较高 | | **灵活性** | 固定功能 | 可定制逻辑 | | **适用场景** | 实时控制、简单外设 | 扩展IO、复杂逻辑集成 | --- **选择建议**: - 若需要**低延迟控制PS引脚**(如MIO连接的LED),优先使用PS GPIO。 - 若需要**扩展更多IO**或与PL逻辑协同工作(如驱动自定义外设),选择AXI GPIO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值