Zynq7020 SDK 初学篇(4)- PL 端 GPIO

1.开发背景

       基于 PS 端 GPIO 的基础上,如何调用 PL 端 GPIO 的输入输出

2.开发需求

        PL 端按键控制 PL 端 LED

3.开发环境

        Zynq7020 + Vivado2017.4

4.实现步骤

4.1 设计配置

        这里设置 PIO 数量 3 个

        由于 PL 端不像 PS 端一样绑定 GPIO,所以需要对上面的 3 个 GPIO 绑定引脚 RTL IO 

4.2 代码编辑

        事实上通过 EMIO 复用和 MIO 使用方法一样,唯一需要注意的是 GPIO 的映射关系,所以GPIO从54 - 56

#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP	(u32)174 /**< Max pins in the
						  *	Zynq Ultrascale+ MP GPIO device
					      * 0 - 25,  Bank 0
					      * 26 - 51, Bank 1
					      *	52 - 77, Bank 2
					      *	78 - 109, Bank 3
					      *	110 - 141, Bank 4
					      *	142 - 173, Bank 5
					      */
#define XGPIOPS_DEVICE_MAX_PIN_NUM	(u32)118 /**< Max pins in the Zynq GPIO device
					      * 0 - 31,  Bank 0
					      * 32 - 53, Bank 1
					      *	54 - 85, Bank 2
					      *	86 - 117, Bank 3
					      */
#include <xil_printf.h>        	// 包含 xil_printf()函数

#include "xparameters.h"     	// 器件参数信息 系统生成
#include "xstatus.h"         	// 包含 库的故障码 的宏定义
#include "xgpiops.h"        	// 包含 PS、PL GPIO 的函数声明
#include "xplatform_info.h"    	// 获取当前的平台信息
#include "sleep.h"            	// 睡眠延时接口
#include "xtime_l.h"

/* 重新定义 */
#define printf     xil_printf

/* gpio 设备,不知为何为 0 */
#define GPIO_DEVICE_ID      XPAR_XGPIOPS_0_DEVICE_ID    // 0

/* GPIO 映射 */
#define BOARD_LED0    	(7)
#define BOARD_KEY0    	(12)
#define CORE_LED    	(0)
#define EMIO_LED0 		(54)
#define EMIO_LED1 		(55)
#define EMIO_KEY0 		(56)

static XGpioPs s_psGpio = {0};

/* 毫秒延时 */
void msleep(int ms)
{
    /* 64 bit 记录时间 */
    XTime tEnd;
    XTime tCur;

    /* 获取当前时间 */
    XTime_GetTime(&tCur);

    /* 计算理论结束时间 */
    tEnd  = tCur + ((((XTime) ms) * COUNTS_PER_SECOND) / 1000);

    /* 阻塞一直查询当前时间是否超时,一直占用 CPU */
    do
    {
        XTime_GetTime(&tCur);
    }while (tCur < tEnd);
}

/* main 入口 */
int main()
{
	printf("%s XGetPlatform_Info = %d\r\n", __func__, XGetPlatform_Info());

	/* 通过设备 ID 找到对应的配置指针 */
	XGpioPs_Config *ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);

	/* 通过配置指针初始化GPIO */
	int Status = XGpioPs_CfgInitialize(&s_psGpio, ConfigPtr,
					ConfigPtr->BaseAddr);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}

	/* 设置  GPIO 方向输出,这里为什么会共用一个 GPIO 结构体?参数一致?  */
	XGpioPs_SetDirectionPin(&s_psGpio, BOARD_LED0, 1);
	XGpioPs_SetDirectionPin(&s_psGpio, CORE_LED, 1);
	XGpioPs_SetDirectionPin(&s_psGpio, EMIO_LED0, 1);
	XGpioPs_SetDirectionPin(&s_psGpio, EMIO_LED1, 1);

	XGpioPs_SetDirectionPin(&s_psGpio, BOARD_KEY0, 0);
	XGpioPs_SetDirectionPin(&s_psGpio, EMIO_KEY0, 0);

	/* 使能 GPIO */
	XGpioPs_SetOutputEnablePin(&s_psGpio, BOARD_LED0, 1);
	XGpioPs_SetOutputEnablePin(&s_psGpio, CORE_LED, 1);
	XGpioPs_SetOutputEnablePin(&s_psGpio, EMIO_LED0, 1);
	XGpioPs_SetOutputEnablePin(&s_psGpio, EMIO_LED1, 1);

	/* 点灯 1s改变一次电平 */
	for (int i = 0; i < 3; i++)
	{
		 XGpioPs_WritePin(&s_psGpio, BOARD_LED0, 0);
		 msleep(500);

		 XGpioPs_WritePin(&s_psGpio, BOARD_LED0, 1);
		 msleep(500);
	}

	/* 点灯 0.2s改变一次电平 */
	for (int i = 0; i < 3; i++)
	{
		 XGpioPs_WritePin(&s_psGpio, CORE_LED, 0);
		 XGpioPs_WritePin(&s_psGpio, EMIO_LED1, 0);
		 msleep(200);

		 XGpioPs_WritePin(&s_psGpio, CORE_LED, 1);
		 XGpioPs_WritePin(&s_psGpio, EMIO_LED1, 1);
		 msleep(200);
	}

	/* 定时读取电平控制对应灯的亮灭 */
	unsigned int status = 0;
	while (1)
	{
		msleep(10);
		status = XGpioPs_ReadPin(&s_psGpio, BOARD_KEY0);
		XGpioPs_WritePin(&s_psGpio, BOARD_LED0, status);

		status = XGpioPs_ReadPin(&s_psGpio, EMIO_KEY0);
		XGpioPs_WritePin(&s_psGpio, EMIO_LED0, status);
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值