ZYNQ-Vitis(SDK)裸机开发之(四)PS端MIO和EMIO的使用

目录

一、ZYNQ中MIO和EMIO简介

[二、Vivado中搭建block design](#二、Vivado中搭建block design)

1.配置PS端MIO:

2.配置PS端EMIO:

三、Vitis中新建工程进行GPIO控制

[1. GPIO操作头文件gpio_hdl.h:](#1. GPIO操作头文件gpio_hdl.h:)

2.GPIO操作源文件gpio_hdl.c:

3.main函数进行调用


例程开发环境:

SOC芯片:ZYNQ7020

开发环境:Vivado2020.2,Vitis2020.2

一、ZYNQ中MIO和EMIO简介

以ZYNQ7020为例,GPIO总共118个,分为了4个bank(ZU+的GPIO和bank数量有所增加),其中MIO有两个bank,需要注意的是bank1的GPIO数量只有22个,其余三个都有32个。

MIO和EMIO均为PS端的GPIO,由PS控制,其中MIO可直接配置复用成PS外设,而EMIO则可以连接到PL端,复用为PL端搭建的外设资源

二、Vivado中搭建block design

Vivado工程详细搭建方法,可见以下文章:

ZYNQ-Linux开发之(二)Vivado工程搭建、Block Design设计搭建、PS、PL的IP核的使用配置

该工程是在ZYNQ-Vitis(SDK)裸机开发之(一)基础上进行的修改,具体文件见如下连接:

ZYNQ-Vitis(SDK)裸机开发之(一)串口收发使用:PS串口+PL串口、多个串口使用方法

1.配置PS端MIO:

双击IP核进行配置,选择MIO Configuration-----I/O Peripherals-----GPIO MIO,勾选后,默认全部MIO都启用

PS端的MIO是不需要在XDC文件中进行约束的,可直接使用

我的板卡使用的是MIO7和MIO8,分别控制两个LED灯,需要根据自己的原理图进行选择

2.配置PS端EMIO:

双击IP核进行配置,选择MIO Configuration-----I/O Peripherals-----GPIO EMIO,勾选后,选取使用的EMIO个数,我这选择使用4个EMIO,其中两个用来控制PL端的LED,剩余两个用作其他使用,这里不用管。

勾选EMIO后,要将连接LED的PL端引脚与EMIO进行约束,这样才能通过EMIO来控制PL端LED的亮灭,值得注意的是,选取EMIO后,系统默认是从GPIO0开始使用,约束的话也要从GPIO[0]开始约束,在XDC文件中增加管脚约束,具体对应引脚需要根据自己项目的硬件原理图确定,我的PL端两个LED分别连接到了L15和H15,对应XDC文件中约束到GPIO[0]和GPIO[1]上如下:

三、Vitis中新建工程进行GPIO控制

1. GPIO操作头文件gpio_hdl.h:

(1)定义GPIO初始化以及配置使用的实例(多个GPIO其实可以公用同一个实例,这里为了方便分区才每个GPIO都实例化了一个结构体)

(2)使用宏定义重新定义PS GPIO的外设ID号

(3)定义工程中使用到的GPIO号,这里有个需要注意的地方,在第一章节就说明了,GPIO分为4个bank,其中0、1bank是MIO,2、3bank是EMIO,工程中使用了两个MIO和两个EMIO,那么这四个GPIO对应的IO号并不是连续的,参见如下关系可知,本工程中MIO对应的GPIO号是7、8,EMIO对应的GPIO号是54、55(因为在vivado中约束时,将PL端的LED约束到了EMIO的[0]和[1]上,从bank的开头数起,对应bank2上的GPIO号即54、55)

/*

* Max pins in the GPIO device ZYNQ

* 0 - 31, Bank 0

* 32 - 53, Bank 1

* 54 - 85, Bank 2

* 86 - 117, Bank 3

*/

(4)定义一些枚举变量,用来表示GPIO的输入输出方向、电平的高低、以及是否使能状态等

(5)声明一些GPIO操作相关的函数,例如GPIO初始化、GPIO点评输出、GPIO输入等操作函数

cpp 复制代码
/*!
    \file    gpio_hdl.h
    \brief   firmware functions to manage gpio
    \version 2024-04-10, V1.0.0
	\author  tbj
*/

#ifndef GPIO_HDL_H
#define GPIO_HDL_H

#include "xgpiops.h"

#ifdef __cplusplus
 extern "C" {
#endif

//GPIO初始化实例
XGpioPs MIOLed0, MIOLed1, EMIOLed0, EMIOLed1;

//GPIO外设地址ID
#define GPIO_DEVICE_ID		XPAR_XGPIOPS_0_DEVICE_ID

//LED灯对应的PS和PL的IO
#define LED0_GPIO_PS_MIO		7
#define LED1_GPIO_PS_MIO		8
#define LED0_GPIO_PL_EMIO		55
#define LED1_GPIO_PL_EMIO		54

typedef enum{
	GPIO_DIR_INPUT = 0,
	GPIO_DIR_OUTPUT,
}GPIO_DIR;

typedef enum{
	GPIO_VALUE_OFF = 0,
	GPIO_VALUE_ON,
}GPIO_VALUE;

typedef enum{
	GPIO_DISABLE = 0,
	GPIO_ENABLE,
}GPIO_EN_STU;

//初始化GPIO
int gpio_polled_init(XGpioPs * Gpio_Ptr, u32 Gpio_Pin, GPIO_DIR Gpio_dir, GPIO_VALUE Gpio_init_value,
 		GPIO_EN_STU Gpio_en);
//设置GPIO输出
int set_gpio_value(XGpioPs * Gpio_Ptr, u32 Gpio_Pin, GPIO_VALUE Gpio_value);
//读取GPIO输入
int read_gpio_value(XGpioPs * Gpio_Ptr, u32 Gpio_Pin, GPIO_VALUE *Gpio_value);

#ifdef __cplusplus
}
#endif

#endif /* GPIO_HDL_H */

2.GPIO操作源文件gpio_hdl.c:

(1)分别对头文件中声明的三个GPIO相关函数进行了实现

cpp 复制代码
/*!
    \file    gpio_hdl.c
    \brief   firmware functions to manage gpio
    \version 2024-04-10, V1.0.0
	\author  tbj
*/

#include "gpio_hdl.h"

//GPIO初始化实例,因为EMIO也属于PS,所以都使用XGpioPs结构体(多个GPIO也可以只初始化一个实例共用)

/* 功能:gpio初始化函数
 * 参数1:GpioPtr-GPIO对象指针
 * 参数2:Gpio_Pin-GPIO对应pin
 * 参数3:Gpio_dir-GPIO方向,输入还是输出
 * 参数4:Gpio_init_value-GPIO初始化值
 * 参数5:Gpio_en-GPIO是否使能
 * 说明:Gpio_init_value和Gpio_en,只有配置输出时有效,配置为输入模式时,可以随意填写
 */
int gpio_polled_init(XGpioPs * Gpio_Ptr, u32 Gpio_Pin, GPIO_DIR Gpio_dir, GPIO_VALUE Gpio_init_value,
		GPIO_EN_STU Gpio_en){

	int Status;
	XGpioPs_Config *ConfigPtr;

	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	Status = XGpioPs_CfgInitialize(Gpio_Ptr, ConfigPtr,
					ConfigPtr->BaseAddr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	//配置GPIO的输入输出模式
	XGpioPs_SetDirectionPin(Gpio_Ptr, Gpio_Pin, Gpio_dir);

	//如果GPIO配置为输出模式,还要配置使能和默认输出值
	if(Gpio_dir == GPIO_DIR_OUTPUT){
		//使能输出的GPIO
		XGpioPs_SetOutputEnablePin(Gpio_Ptr, Gpio_Pin, Gpio_en);
		//初始化GPIO的值
		XGpioPs_WritePin(Gpio_Ptr, Gpio_Pin, Gpio_init_value);
	}

	/*
	 *	Max pins in the ZynqMP GPIO device	ZU+
	 *	0 - 25,  Bank 0
	 *	26 - 51, Bank 1
	 *	52 - 77, Bank 2
	 *	78 - 109, Bank 3
	 *	110 - 141, Bank 4
	 *	142 - 173, Bank 5
	 */

	/*
	 *	Max pins in the GPIO device	ZYNQ
	 *	0 - 31,  Bank 0
	 *	32 - 53, Bank 1
	 *	54 - 85, Bank 2
	 *	86 - 117, Bank 3
	 */
	return XST_SUCCESS;
}

/* 功能:设置GPIO的值
 * 参数1:GpioPtr-GPIO对象指针
 * 参数2:Gpio_Pin-GPIO对应pin
 * 参数3:Gpio_value-GPIO输出值
 */
int set_gpio_value(XGpioPs * Gpio_Ptr, u32 Gpio_Pin, GPIO_VALUE Gpio_value){

	u32 Data;
	XGpioPs_WritePin(Gpio_Ptr, Gpio_Pin, Gpio_value);

	Data = XGpioPs_ReadPin(Gpio_Ptr, Gpio_Pin);
	if (Data != Gpio_value) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}

/* 功能:读取GPIO的值
 * 参数1:GpioPtr-GPIO对象指针
 * 参数2:Gpio_Pin-GPIO对应pin
 * 参数3:Gpio_value-GPIO读取值
 */
int read_gpio_value(XGpioPs * Gpio_Ptr, u32 Gpio_Pin, GPIO_VALUE *Gpio_value){

	*Gpio_value = (GPIO_VALUE)XGpioPs_ReadPin(Gpio_Ptr, Gpio_Pin);
	return XST_SUCCESS;
}

3.main函数进行调用

(1)初始化GPIO相关状态,进行输入输出、使能等配置

(2)每隔1秒进行LED等的亮灭操作,查看GPIO输出操作是否好用

cpp 复制代码
int main()
{
		//MIO EMIO测试
#ifdef GPIO_Test
	//初始化GPIO,包括输入输出模式、初始值、是否使能等
	gpio_polled_init(&MIOLed0, LED0_GPIO_PS_MIO, GPIO_DIR_OUTPUT, GPIO_VALUE_OFF, GPIO_ENABLE);
	gpio_polled_init(&MIOLed1, LED1_GPIO_PS_MIO, GPIO_DIR_OUTPUT, GPIO_VALUE_OFF, GPIO_ENABLE);
	gpio_polled_init(&EMIOLed0, LED0_GPIO_PL_EMIO, GPIO_DIR_OUTPUT, GPIO_VALUE_OFF, GPIO_ENABLE);
	gpio_polled_init(&EMIOLed1, LED1_GPIO_PL_EMIO, GPIO_DIR_OUTPUT, GPIO_VALUE_OFF, GPIO_ENABLE);
#endif

	while(1){
	//************************************GPIO-Test*********************************//
#ifdef GPIO_Test
		set_gpio_value(&EMIOLed0, LED0_GPIO_PL_EMIO, GPIO_VALUE_ON);
		sleep(1);
		set_gpio_value(&EMIOLed0, LED0_GPIO_PL_EMIO, GPIO_VALUE_OFF);
		set_gpio_value(&EMIOLed1, LED1_GPIO_PL_EMIO, GPIO_VALUE_ON);
		sleep(1);
		set_gpio_value(&EMIOLed1, LED1_GPIO_PL_EMIO, GPIO_VALUE_OFF);

		set_gpio_value(&MIOLed0, LED0_GPIO_PS_MIO, GPIO_VALUE_ON);
		sleep(1);
		set_gpio_value(&MIOLed0, LED0_GPIO_PS_MIO, GPIO_VALUE_OFF);
		set_gpio_value(&MIOLed1, LED1_GPIO_PS_MIO, GPIO_VALUE_ON);
		sleep(1);
		set_gpio_value(&MIOLed1, LED1_GPIO_PS_MIO, GPIO_VALUE_OFF);

#endif

	}
    return 0;
}

创作不易,希望大家点赞、收藏、关注哦!!!ヾ(o◕∀◕)ノ

相关推荐
东胜物联几秒前
探寻5G工业网关市场,5G工业网关品牌解析
人工智能·嵌入式硬件·5g
stm32发烧友3 分钟前
基于STM32的智能家居环境监测系统设计
stm32·嵌入式硬件·智能家居
上理考研周导师4 分钟前
第二章 虚拟仪器及其构成原理
fpga开发
wowocpp9 分钟前
ubuntu 22.04 硬件配置 查看 显卡
linux·运维·ubuntu
山河君21 分钟前
ubuntu使用DeepSpeech进行语音识别(包含交叉编译)
linux·ubuntu·语音识别
鹏大师运维25 分钟前
【功能介绍】信创终端系统上各WPS版本的授权差异
linux·wps·授权·麒麟·国产操作系统·1024程序员节·统信uos
筱源源28 分钟前
Elasticsearch-linux环境部署
linux·elasticsearch
FPGA技术实战1 小时前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
pk_xz1234562 小时前
Shell 脚本中变量和字符串的入门介绍
linux·运维·服务器
小珑也要变强2 小时前
Linux之sed命令详解
linux·运维·服务器