赞
踩
软件环境: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;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
接下来对程序中的一些函数做一些解释说明:
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采样。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。