当前位置:   article > 正文

【ZYNQ】ZYNQ7000 XADC 及其驱动示例_zynq xadc 寄存器控制

zynq xadc 寄存器控制

XADC 简介

ZYNQ SoC 的 XADC 模块包括两个 12 位的模数转换器,转换速率可以达到 1MSPS(每秒一百万次采样)。它带有片上温度和电压传感器,可以测量芯片工作时的温度和供电电压。

在 7 系列的 FPGA 中,XADC 提供了 JTAG 和 DRP(dynamic reconfiguration port)接口,用于访问其内部的状态和控制寄存器。在 ZYNQ-7000 SoC 器件中,XADC 增加了一个 PS-XADC 接口,用于 PS 中的软件控制 XADC 模块。

XADC 模块的系统框图如下所示:

在这里插入图片描述

在图中 PL-JTAG 接口可以用于开发工具(Vivado)控制 XADC 模块,包括读取芯片温度信息等。而运行在 PS 中的软件则可以通过两种方式与 XADC 进行通信:

  • 1、 通过 PS-XADC 接口,此时不需要对 PL 进行编程配置;
  • 2、 通过 PS 到 PL 的 AXI Master 接口(M_AXI_GP),此时需要在 PL 中调用 AXI XADC IP 核。

在使用 PS 控制 XADC 时,如果对应用的性能要求较高,则推荐第二种方式,它使用的是一个并行的数据路径(DRP 接口)。而 PS-XADC 接口同 PL-JTAG 接口一样,使用的是串行的数据路径,相对较慢。不过使用 PS-XADC 接口不占用 PL 的资源,也不需要对 PL 进行编程,只需要对 PL 部分供电即可。

需要注意的是,PL-JTAG 接口与 PS-XADC 接口不能同时使用。而 XADC 可以在 PL-JTAG 接口(或PS-XADC 接口)与 DRP 接口之间进行仲裁。

XADC 实验

  • 开发工具:Vivado2017.4
  • 验证平台:黑金ZYNQ7035

硬件设计

XADC 为硬核模块,不需要对 PL 进行配置。PS 端只需完成 UART、DDR 等基础配置就可以。

在这里插入图片描述

软件设计

本实验通过 PS-XADC 接口实现,创建基础 SDK 工程即可,添加源代码:

  • xadc.h
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#ifndef __XADC_H__
#define __XADC_H__

#define USING_XADC

#ifdef USING_XADC
#include "xparameters.h"
#include "xadcps.h"

#define XADC_DEVICE_ID	XPAR_XADCPS_0_DEVICE_ID

struct Xadc_Data
{
    float temp;     // Temperature
    float vccint;   // PL kernel voltage
    float vccaux;   // PL auxiliary voltage
    float vccbram;  // PL BRAM voltage
    float vccpint;  // PS kernel voltage
    float vccpaux;  // PS auxiliary voltage
    float vccpdro;  // PS DDR voltage

    uint16_t raw_temp;
    uint16_t raw_vccint;
    uint16_t raw_vccaux;
    uint16_t raw_vccbram;
    uint16_t raw_vccpint;
    uint16_t raw_vccpaux;
    uint16_t raw_vccpdro;
};

typedef struct Xadc_Data XadcData_t;

int XadcPs_Init(XAdcPs *XadcInstancePtr, uint16_t DeviceId);
void XadcPs_GetData(XAdcPs *XadcInstancePtr, XadcData_t *XadcData);

#endif
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • xadc.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "xadc.h"

#ifdef USING_XADC
int XadcPs_Init(XAdcPs *XadcInstancePtr, uint16_t DeviceId)
{
    int Status;
    XAdcPs_Config *XadcConfigPtr;

    XadcConfigPtr = XAdcPs_LookupConfig(DeviceId);
    if (NULL == XadcConfigPtr) {
        return XST_FAILURE;
    }

    Status = XAdcPs_CfgInitialize(XadcInstancePtr, XadcConfigPtr, 
                        XadcConfigPtr->BaseAddress);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    XAdcPs_SetSequencerMode(XadcInstancePtr, XADCPS_SEQ_MODE_SAFE);

    return Status;
}

void XadcPs_GetData(XAdcPs *XadcInstancePtr, XadcData_t *XadcData)
{
    XadcData->raw_temp = XAdcPs_GetAdcData(XadcInstancePtr, XADCPS_CH_TEMP);
    XadcData->temp = XAdcPs_RawToTemperature(XadcData->raw_temp);

    XadcData->raw_vccint = XAdcPs_GetAdcData(XadcInstancePtr, XADCPS_CH_VCCINT);
    XadcData->vccint = XAdcPs_RawToVoltage(XadcData->raw_vccint);

    XadcData->raw_vccaux = XAdcPs_GetAdcData(XadcInstancePtr, XADCPS_CH_VCCAUX);
    XadcData->vccaux = XAdcPs_RawToVoltage(XadcData->raw_vccaux);

    XadcData->raw_vccbram = XAdcPs_GetAdcData(XadcInstancePtr, XADCPS_CH_VBRAM);
    XadcData->vccbram = XAdcPs_RawToVoltage(XadcData->raw_vccbram);

    XadcData->raw_vccpint = XAdcPs_GetAdcData(XadcInstancePtr, XADCPS_CH_VCCPINT);
    XadcData->vccpint = XAdcPs_RawToVoltage(XadcData->raw_vccpint);

    XadcData->raw_vccpaux = XAdcPs_GetAdcData(XadcInstancePtr, XADCPS_CH_VCCPAUX);
    XadcData->vccpaux = XAdcPs_RawToVoltage(XadcData->raw_vccpaux);

    XadcData->raw_vccpdro = XAdcPs_GetAdcData(XadcInstancePtr, XADCPS_CH_VCCPDRO);
    XadcData->vccpdro = XAdcPs_RawToVoltage(XadcData->raw_vccpdro);
}
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • app_xadc.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "xadc.h"

#ifdef USING_XADC
#include "stdio.h"
#define kprintf printf

/**
 * xil_printf does not support printing floating point numbers
*/

static XAdcPs Xadc;
static XadcData_t xadc_data;

int xadc_read_data(void)
{
    XadcPs_GetData(&Xadc, &xadc_data);

    kprintf("On Chip Temperature:  %f C    \r\n", xadc_data.temp);
    kprintf("PL Kernel Voltage:     %f V    \r\n", xadc_data.vccint);
    kprintf("PL Auxiliary Voltage:  %f V    \r\n", xadc_data.vccaux);
    kprintf("PL BRAM Voltage:       %f V    \r\n", xadc_data.vccbram);
    kprintf("PS Kernel Voltage:     %f V    \r\n", xadc_data.vccpint);
    kprintf("PS Auxiliary Voltage:  %f V    \r\n", xadc_data.vccpaux);
    kprintf("PS DDR Voltage:        %f V    \r\n", xadc_data.vccpdro);

    return 0;
}

int app_xadc_init(void)
{
    int Status = XST_SUCCESS;
    Status = XadcPs_Init(&Xadc, XADC_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    return Status;
}
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

主函数种首先调用 app_xadc_init() 对 XADC 初始化,需要读取时调用 xadc_read_data() 即可。

实验现象

在这里插入图片描述

参考资料

  • UG585
  • 正点原子 ZYNQ 领航者
  • 黑金 ZYNQ7035

更多内容

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/586059
推荐阅读
  

闽ICP备14008679号