Zynq 7020笔记之 GPIO MIO 和EMIO的学习

1 参考

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

2 理论指示

在PS侧,有PS自己的IO pin,称为MIO,共有54个(编号0-53)。如果PS侧IO不够使用,则可以通过扩展的方式来使用PL侧的IO。扩展方式有两中:EMIO和GPIO。 EMIO 方式可以将PL侧IO直接看作PS侧IO使用,只是编号从54-117. 而GPIO则没有数量限制。直接挂到AXI总线上就可以。
在这里插入图片描述
在这里插入图片描述
上图是EMIO和MIO的IO映射关系示意图。
对于MIO的使用。
MIO的例化在ZYNQ的Perpheral IO和IO Configuration中体现。
Perpheral IO中的0-43就是MIO的pin Number.这个Pin Number在SDK(C编程中)可以体现到。

3 实验目的

练习使用MIO,EMIO,GPIO等接口。

4 实验过程

建立工程,并初始化GPIO,EMIO等。然后:
当按下GPIO LED对应的KEY时,GPIO LED会进行亮灭转换;
当按下EMIO LED对应的KEY时,EMIO LED会进行亮灭转换;
当按下MIO LED对应的KEY时,MIO LED会进行亮灭转换;

5 实验平台

Microphase ZUS zynq7020 开发板。 串口使用 uart1[48,49]. DDR选择 MT41J256M16 RE-125,32bit. BANK1 = 1.8v.
同时对GPIO EMIO进行下图的设置。

EMIO,EMIO也是在Zynq的设置中进行设置的。

在这里插入图片描述
在这里插入图片描述
上图中的3代表EMIO的宽度,不管是input还是output都算在一起。然后对应的pin number会从54开始映射,到54+emio_width(eg.3)-1。假如在block design中 EMIO端名为ps_emio_port,则pin assignment 会从最低位开始映射,即ps_emio_port[0] = EMIO number 54. ps_emio_port[width-1] = EMIO Number 54+emio_width-1。

GPIO 是挂在PS_to_PL AXI 总线上的外设,比较简单。

6 Vivado 建立工程

block design 如下:
在这里插入图片描述

7、SDK的工程程序

#本例程是将GPIO,EMIO和MIO融合在一起的程序。
#include <stdio.h>
#include "platform.h"
#include "xgpio.h"
#include "xgpiops.h"
#include "xparameters.h"
#include <unistd.h>  //sleep()  usleep()


////// parameter define ,根据xparameters.h中的参数来定义每个AXI_GPIO外设的ID
#define 	KEY_GPIO_DEVICE_ID		XPAR_AXI_GPIO_1_DEVICE_ID
#define 	LED_Auto_GPIO_DEVICE_ID	XPAR_AXI_GPIO_0_DEVICE_ID
#define 	LED_key_GPIO_DEVICE_ID	XPAR_AXI_GPIO_2_DEVICE_ID

//定义EMIO的pin number,根据PL程序中port的高地位来映射。54对应最低位,依次累加。【重要】
#define 	KEY_iPinNumberEMIO			56
#define 	LED_Auto_iPinNumberEMIO		55
#define 	LED_Key_iPinNumberEMIO		54  //PL侧EMIO例化的端口的最低位,为端口54,然后依次向上排列

//定义MIO的pin number,根据zynq设定,是多少就定于多少。
#define 	KEY_iPinNumberMIO			47
#define 	LED_Auto_iPinNumberMIO		50
#define 	LED_Key_iPinNumberMIO		51


int main()
{

	//定义 gpiO 所用参数
	XGpio KEY_GpioInst;
	XGpio LED_Auto_GpioInst;
	XGpio LED_Key_GpioInst;
	u32   led_Auto_gpio	;
	u32   Key_gpio_value	;


	int	  key_gpio_status;
	int	  led_auto_gpio_status;
	int	  led_key_gpio_status;
	int   i;

	//定义EMIO所用参数,和MIO所用参数。
	//使用EMIO 和MIO都需要对PS侧GPIO进行初始化,当两个都使用时只需要初始化一次就可以了,所以有些参数共同使用

	static XGpioPs psGpioInstancePtr;  //共用
	XGpioPs_Config* GpioConfigPtr;   //共用
	u32   emio_Led;
	int	  emio_status;  //共用
	u32   Key_EMIO_value	;
	int   j ;


	u32   mio_led ;
	u32	  Key_MIO_value ;
	int   k;

 //固定初始化。
	init_platform();

	// init gpio,并检测初始化之后的状态
	key_gpio_status 		= XGpio_Initialize(&KEY_GpioInst		,KEY_GPIO_DEVICE_ID 		);
	led_auto_gpio_status 	= XGpio_Initialize(&LED_Auto_GpioInst	,LED_Auto_GPIO_DEVICE_ID 	);
	led_key_gpio_status 	= XGpio_Initialize(&LED_Key_GpioInst	,LED_key_GPIO_DEVICE_ID 	);

	if(key_gpio_status == 0)
	{
		printf(" KEY GPIO  init successful ! 
");

	} else {

		printf(" KEY GPIO  init Failed ! 
");
	}

	if(led_auto_gpio_status == 0)
		{
			printf(" LED Auto GPIO  init successful ! 
");

		} else {

			printf(" LED Auto GPIO  init Failed ! 
");
		}

	if(led_key_gpio_status == 0)
		{
			printf(" LED KEY GPIO  init successful ! 
");

		} else {

			printf(" LED KEY GPIO  init Failed ! 
");
		}

	// 设置GPIO的方向,
	XGpio_SetDataDirection(&KEY_GpioInst		,	1,	1);  // set as input
	XGpio_SetDataDirection(&LED_Auto_GpioInst	,	1,	0);  // set as output
	XGpio_SetDataDirection(&LED_Key_GpioInst	,	1,	0);  // set as output

   //并对output信号进行消隐(这里output接LED灯),最后的1为data.这里LED 为0时点亮。初始化之后设置为1,熄灭led.
	XGpio_DiscreteWrite(&LED_Auto_GpioInst	,	1, 	1);  ////消隐,初始化,关闭LED
	XGpio_DiscreteWrite(&LED_Key_GpioInst	,	1, 	1);  ////消隐,初始化,关闭LED


	// init ps侧GPIO (emio and mio ),并检测初始化状态。

	GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
	if(GpioConfigPtr == NULL)  return XST_FAILURE ;
	emio_status = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr->BaseAddr);
	if(emio_status == XST_SUCCESS)
		printf(" PS EMIO and MIO init successful ! 
");
	else
		printf(" PS EMIO and MIO init Failed ! 
");

	// 设置EMIO的方向,
	XGpioPs_SetDirectionPin(&psGpioInstancePtr,KEY_iPinNumberEMIO,0);
	XGpioPs_SetDirectionPin(&psGpioInstancePtr,LED_Auto_iPinNumberEMIO,1);
	XGpioPs_SetDirectionPin(&psGpioInstancePtr,LED_Key_iPinNumberEMIO,1);
   //并对output信号进行消隐(这里output接LED灯),
	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr,	LED_Auto_iPinNumberEMIO	,	1);
	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr,	LED_Key_iPinNumberEMIO	,	1);

	//// 设置EMIO的方向,并对output信号进行消隐(这里output接LED灯)
	XGpioPs_SetDirectionPin(&psGpioInstancePtr,	KEY_iPinNumberMIO		,	0);
	XGpioPs_SetDirectionPin(&psGpioInstancePtr,	LED_Auto_iPinNumberMIO	,	1);
	XGpioPs_SetDirectionPin(&psGpioInstancePtr,	LED_Key_iPinNumberMIO	,	1);

	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr,	LED_Auto_iPinNumberMIO	,	1);
	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr,	LED_Key_iPinNumberMIO	,	1);

//对EMIO和MIO输出端口进行消隐。
	XGpioPs_WritePin(&psGpioInstancePtr,LED_Auto_iPinNumberEMIO	,	1);   //消隐
	XGpioPs_WritePin(&psGpioInstancePtr,LED_Key_iPinNumberEMIO	,	1);   //消隐
	XGpioPs_WritePin(&psGpioInstancePtr,LED_Auto_iPinNumberMIO	,	1);   //消隐
	XGpioPs_WritePin(&psGpioInstancePtr,LED_Key_iPinNumberMIO	,	1);   //消隐

    printf("LED test Start ----> 
")  ;
    while(1)
    {

    	printf("EMIO LED test Start ----> 
")  ;
    	//EMIO所接的 LED1自动闪烁
    	printf(".......EMIO LED Auto test Start ........... 
")  ;
		for(j = 0; j < 5; j++)
		{
			for(emio_Led = 0; emio_Led < 2; emio_Led ++)
			{
				XGpioPs_WritePin(&psGpioInstancePtr,LED_Auto_iPinNumberEMIO,emio_Led);   //取 最后一位
				sleep(1);
			}
		}
		XGpioPs_WritePin(&psGpioInstancePtr,LED_Auto_iPinNumberEMIO,1);  //消隐

		//当EMIO所接的开关被按下(低有效)之后,EMIO所接的LED2亮一会之后熄灭。
		printf(".......wait EMIO KEY test Start ........... 
")  ;
		while(1)
		{
			Key_EMIO_value = XGpioPs_ReadPin(&psGpioInstancePtr ,KEY_iPinNumberEMIO)& 0x01;
			if(Key_EMIO_value == 0x00)
			{
				printf(".......KEY EMIO have Pressed, LED KEY EMIO Turn on ....... 
")  ;
				XGpioPs_WritePin(&psGpioInstancePtr ,LED_Key_iPinNumberEMIO,0);
				sleep(5);
				break ;
			}
		}
		XGpioPs_WritePin(&psGpioInstancePtr ,LED_Key_iPinNumberEMIO,1);  //消隐



    	printf("GPIO LED test Start ----> 
")  ;

    	printf(".......LED Auto test Start ........... 
")  ;

    	for(i = 0; i < 5; i++)
    	{
    		for(led_Auto_gpio = 0; led_Auto_gpio < 2; led_Auto_gpio ++)
			{
    			XGpio_DiscreteWrite(&LED_Auto_GpioInst,1, 1<<led_Auto_gpio);
    			sleep(1);
    		 }
    	}
    	XGpio_DiscreteWrite(&LED_Auto_GpioInst	,	1, 	1);   ////消隐


    	printf(".......Wait KEY GPIO Pressed ........... 
")  ;

    	while(1)
    	{
    		Key_gpio_value = XGpio_DiscreteRead(&KEY_GpioInst,1)& 0x01;
    		if(Key_gpio_value == 0x00)
    		{
    			printf(".......KEY GPIO have Pressed, LED KEY Turn on ....... 
")  ;
    			XGpio_DiscreteWrite(&LED_Key_GpioInst,1,0);
    			sleep(5);
    			break ;
    		}
    	}
    	XGpio_DiscreteWrite(&LED_Key_GpioInst,1,1);  //消隐



		printf("MIO LED test Start ----> 
")  ;
		printf(".......LED MIO test Start ........... 
")  ;
		for(k = 0; k < 5; k++)
		{
			for(mio_led = 0; mio_led < 2; mio_led ++)
			{
				XGpioPs_WritePin(&psGpioInstancePtr,LED_Auto_iPinNumberMIO,mio_led);   //取 最后一位
				sleep(5);

			}

		}
		XGpioPs_WritePin(&psGpioInstancePtr,LED_Auto_iPinNumberMIO,1);   //消隐

		printf(".......wait MIO KEY test Start ........... 
")  ;
		while(1)
		{
			Key_MIO_value = XGpioPs_ReadPin(&psGpioInstancePtr ,KEY_iPinNumberMIO)& 0x01;
			if(Key_MIO_value == 0x00)
			{
				printf(".......KEY EMIO have Pressed, LED KEY EMIO Turn on ....... 
")  ;
				XGpioPs_WritePin(&psGpioInstancePtr ,LED_Key_iPinNumberMIO,0);
				sleep(5);
				break ;
			}
		}
		XGpioPs_WritePin(&psGpioInstancePtr ,LED_Key_iPinNumberMIO,1);  //消隐


    }

 //结束时需要添加的。
    cleanup_platform();
    return 0 ;

}

8 调试步骤

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注