【JokerのZYNQ7020】XADC。

软件环境:vivado 2017.4        硬件平台:XC7Z020 


 

手册ug480_7Series_XADC,由上图可见,右边红框圈的,ZYNQ的XADC模块包括2个12bit 1MSPS的模数转换器;左边红框圈的,共十七组信号,都分P端N端,也就是差分信号的两端,单端当然也可接受;最上边红框,意味着XADC模块也可采集片上传感器测量到的片上包括芯片温度、供电电压等信息;最终这些测量转换数据存储在状态寄存器的专用寄存器内,可由FPGA内部动态配置端口(DRP ----Dynamic Reconfiguration Port)的16位同步读/写端口访问。ADC的转换数据也可以由JTAG访问,当使用这种方式时,并不需要直接去例化XADC模块,因为这是一个已经存在与FPGA JTAG结构的专用接口,此时因为没有在设计中直接例化XADC模块,故XADC模块工作在一种预先定义好的模式即缺省模式,此模式下XADC模块专用于监视芯片上的供电电压和芯片温度。

其片上可采集的参数主要如下,这次例程就是针对这些片上数据进行XADC采集实验。

 


Vivado 2017.4 Create Block Design后,添加ZYNQ7 Processing system和XADC Wizard。

打开XADC Wizard模块设置,Basic选项卡下,选Channel Sequencer。

Channel Swquencer选项卡下,勾选要测试的数据量。

然后自动连线, Generate the output products,Create a HDL wrapper,Generate Bitstream,Export Hardware(注意勾选include biestream),最后launch SDK进行测试。

SDK中new application然后添加如下测试代码。

#include <stdio.h>
#include "xadcps.h"
#include "xil_types.h"
#define XPAR_AXI_XADC_0_DEVICE_ID 0

static XAdcPs XADCMonInst;

int main()
{

  XAdcPs_Config *ConfigPtr;
  XAdcPs *XADCInstPtr = &XADCMonInst;

  //status of initialisation
  int Status_ADC;

  /********************芯片温度********************/
  u32 TempRawData;
  float TempData;

  /********************内部PL核心电压********************/
  u32 VccIntRawData;
  float VccIntData;

  /********************辅助PL电压********************/
  u32 VccAuxRawData;
  float VccAuxData;

  /********************PL BRAM电压********************/
  u32 VBramRawData;
  float VBramData;

  /********************PS内部核心电压********************/
  u32 VccPIntRawData;
  float VccPIntData;

  /********************PS辅助电压********************/
  u32 VccPAuxRawData;
  float VccPAuxData;

  /********************DDR RAM的工作电压********************/
  u32 VDDRRawData;
  float VDDRData;

  printf("XADC_TEST BEGIN!!! \n\r");
  
    //XADC initilization
     ConfigPtr = XAdcPs_LookupConfig(XPAR_AXI_XADC_0_DEVICE_ID);
     if (ConfigPtr == NULL) {
           return XST_FAILURE;
         }

     Status_ADC = XAdcPs_CfgInitialize(XADCInstPtr,ConfigPtr,ConfigPtr->BaseAddress);
     if(XST_SUCCESS != Status_ADC){
           print("ADC INIT FAILED\n\r");
           return XST_FAILURE;
        }

     //self test
     Status_ADC = XAdcPs_SelfTest(XADCInstPtr);
     if (Status_ADC != XST_SUCCESS) {
       return XST_FAILURE;
     }

		//stop sequencer
		XAdcPs_SetSequencerMode(XADCInstPtr,XADCPS_SEQ_MODE_SINGCHAN);

		//disable alarms
		XAdcPs_SetAlarmEnables(XADCInstPtr, 0x0);

		//configure sequencer to just sample internal on chip parameters
		XAdcPs_SetSeqInputMode(XADCInstPtr, XADCPS_SEQ_MODE_SAFE);


		//configure the channel enables we want to monitor

		XAdcPs_SetSeqChEnables(XADCInstPtr,XADCPS_CH_TEMP|XADCPS_CH_VCCINT|XADCPS_CH_VCCAUX|XADCPS_CH_VBRAM|XADCPS_CH_VCCPINT| XADCPS_CH_VCCPAUX|XADCPS_CH_VCCPDRO);

		while(1)
		{
			TempRawData = XAdcPs_GetAdcData(XADCInstPtr, XADCPS_CH_TEMP);
			TempData = XAdcPs_RawToTemperature(TempRawData);
			printf("Raw Temp %lu Real Temp %f \n\r", TempRawData, TempData);

			VccIntRawData= XAdcPs_GetAdcData(XADCInstPtr, XADCPS_CH_VCCINT);
			VccIntData = XAdcPs_RawToVoltage(VccIntRawData);
			printf("Raw VccInt %lu Real VccInt %f \n\r", VccIntRawData,VccIntData);

			VccAuxRawData = XAdcPs_GetAdcData(XADCInstPtr, XADCPS_CH_VCCAUX);
			VccAuxData = XAdcPs_RawToVoltage(VccAuxRawData);
			printf("Raw VccAux %lu Real VccAux %f \n\r", VccAuxRawData,VccAuxData);


			VBramRawData = XAdcPs_GetAdcData(XADCInstPtr, XADCPS_CH_VBRAM);
			VBramData = XAdcPs_RawToVoltage(VBramRawData);
			printf("Raw VccBram %lu Real VccBram %f \n\r", VBramRawData, VBramData);

			VccPIntRawData = XAdcPs_GetAdcData(XADCInstPtr, XADCPS_CH_VCCPINT);
			VccPIntData = XAdcPs_RawToVoltage(VccPIntRawData);
			printf("Raw VccPInt %lu Real VccPInt %f \n\r", VccPIntRawData, VccPIntData);

			VccPAuxRawData = XAdcPs_GetAdcData(XADCInstPtr, XADCPS_CH_VCCPAUX);
			VccPAuxData = XAdcPs_RawToVoltage(VccPAuxRawData);
			printf("Raw VccPAux %lu Real VccPAux %f \n\r", VccPAuxRawData, VccPAuxData);

			VDDRRawData = XAdcPs_GetAdcData(XADCInstPtr, XADCPS_CH_VCCPDRO);
			VDDRData = XAdcPs_RawToVoltage(VDDRRawData);
			printf("Raw VccDDR %lu Real VccDDR %f \n\r", VDDRRawData, VDDRData);
		 }

		return 0;
}

接下来对程序中的一些函数做一些解释说明:

XAdcPs_LookupConfig()和XAdcPs_CfgInitialize()就不多说了,跟IO部分一样,这两个函数一个是查找设备ID,看设备是否存在,另一个是设备存在的前提下,获取设备的配置表的基址。

XAdcPs_SelfTest()作用是这样的,先把设备复位,然后往警报门限寄存器中写入警报门限的值,再读出来,看写进去的和读出来的值是否相等,相等就说明test成功然后再次复位清除设置的值,否则test失败。

XAdcPs_SetSequencerMode()设置采样序列模式,可设置安全模式、单次、循环、单通道、同步、独立。这里将定序器设置的是单通道,从而停止定序器当前操作。至于这些模式之间的详细区别,因为现在还用不到,所以还没细看,只是感觉,除了单次或者单通道模式外,其他的肯定还要配置通道序列(几通道是序列一、几通道是序列二等等),应该是采集外部信号的时候才会用到,相对复杂一些,等用的时候在看把= =。

#define XADCPS_SEQ_MODE_SAFE		0  /**< Default Safe Mode */
#define XADCPS_SEQ_MODE_ONEPASS		1  /**< Onepass through Sequencer */
#define XADCPS_SEQ_MODE_CONTINPASS	2  /**< Continuous Cycling Sequencer */
#define XADCPS_SEQ_MODE_SINGCHAN	3  /**< Single channel -No Sequencing */
#define XADCPS_SEQ_MODE_SIMUL_SAMPLING	4  /**< Simultaneous sampling */
#define XADCPS_SEQ_MODE_INDEPENDENT	8  /**< Independent mode */

XAdcPs_SetAlarmEnables()设置采样值报警,1使能,0失能。就是采集值大于模块配置时候设置的门限值时报警。

XAdcPs_SetSeqInputMode()设置输入模式,相当于是复位定序器,并按照当前设置的模式进行工作。安全模式下仅采样内部的片上传感器参数。

XAdcPs_SetSeqChEnables()使能采样通道,需要采哪些通道,就将通道与进第二个参数里。

XAdcPs_GetAdcData()获取采集到的ADC的量,传参哪个通道,就采哪个通道。

XAdcPs_RawToTemperature()将采集到的温度数字量,转化成实际的温度值,转换关系如下。

#define XAdcPs_RawToTemperature(AdcData)				\
	((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f)

XAdcPs_RawToVoltage()将采集到的电压数字量,转化成实际的电压值,转换关系如下。

#define XAdcPs_RawToVoltage(AdcData) 					\
	((((float)(AdcData))* (3.0f))/65536.0f)

所以在最后总结一下XADC在SDK中大致的流程:

通过XGpioPs_LookupConfig函数,找到所设备的基址------------>

通过XGpioPs_CfgInitialize函数,初始化设备配置------------>

通过XAdcPs_SelfTest函数,进行采样前自检------------>

通过XAdcPs_SetSequencerMode函数,停止定序器------------>

通过XAdcPs_SetAlarmEnables函数,关闭报警------------>

通过XAdcPs_SetSeqInputMode函数,复位定序器,设置输入模式------------>

通过XAdcPs_SetSeqChEnables函数,使能需要采样的通道------------>

通过XAdcPs_GetAdcData函数,进行ADC采样。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值