Zynq7020 SDK 初学篇(2)- PS 端 GPIO LED

发布时间 2023-08-09 20:28:42作者: 掌控命运

一、开发环境  Zynq7020 + Vivado2017.4

二、开发背景:会使用 Vivado 开发工具,不熟悉的可以参考正点原子开发文档

三、功能实现,LED 定时闪烁

四、实现步骤:

  1、配置 PS 端 Block Design MIO 功能, 根据配置表编写代码

   

    

  2、导出到 SDK,编写代码,编译运行

#include <xil_printf.h>        // 包含 xil_printf()函数

#include "xparameters.h"     // 器件参数信息 系统生成
#include "xstatus.h"         // 包含 库的故障码 的宏定义
#include "xgpiops.h"        // 包含 PS 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_LED1    (8)
#define CORE_LED    (0)

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);
}

int main(int argc, char* argv[])
{
    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, BOARD_LED1, 1);
    XGpioPs_SetDirectionPin(&s_psGpio, CORE_LED, 1);

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

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

         XGpioPs_WritePin(&s_psGpio, BOARD_LED0, 1);
         XGpioPs_WritePin(&s_psGpio, BOARD_LED1, 1);
         sleep(1);
    }

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

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

    return 0;
}

   3、代码解释:

    (1)void msleep(int ms) 接口,暂时只找到 sleep 秒级延时API,如果需要更小的延时,进入 sleep 接口内部,发现实现的方式是获取了CPU当前的计数时钟节拍,

       这样就简单了,参考 sleep 的的实现方式,把需要等待的计数值 除以 1000 即可求出,毫秒级的延时时间。关键函数:XTime_GetTime

    (2)GPIO MIO 驱动流程:

      1)XGpioPs_LookupConfig:通过设备 ID 找到对应的配置指针

      2)XGpioPs_CfgInitialize:初始化 GPIO 

      3)XGpioPs_SetDirectionPin:设置 GPIO 控制方向,可以是输出,也可以是输入,上述代码是输出部分

      4)XGpioPs_SetOutputEnablePin:使能 GPIO 输出

      5)XGpioPs_WritePin:控制电平高低,这样就可以自由控制输出啦