一个LSB大概为0.123度。
片内电压测量时ADC数值就是按3V为最大12比特的线性表示,一个LSB大概为0.732mV,如VCCINT= 1V, 读出的ADC数值应该是 1/3 x 4096 =1365 = 555 h。
总结下XADC模块的访问方式,如下图示XADC模块的系统框图:
主要有PL-JTAG接口,PS-XADC接口,DRP(dynamic reconfiguration port)并行接口, PL-JTAG接口和PS-XADC接口都是串行接口,并且由上图也可以看到二者通过选择器二选一连到XADC模块,不能同时使用,这两种接口都不需要编程PL部分,只需要对PL部分供电。DRP并行接口主要由PL访问,PS也可以通过AXI总线访问PL逻辑来间接地访问XADC模块,设计时需要在PL逻辑中例化XADCIP核。
XADC模块提供了多达128个16比特的寄存器供用户读写控制,寄存器接口如下图示:
详细寄存器比特含义的描述请参考ug480的第3章,这里特别摘出XADC模块有6种工作模式,按下图由第1个控制寄存器的SEQ0~SEQ3决定:
这里Single pass sequence模式是指按顺序采样一次后就停止的模式,如果连续按预定序列采样不停止的话就是Continuous sequence mode模式。上电后或者没有例化XADC IP核时一般是工作在Default Mode缺省模式来执行片内温度和电压的监控功能。
以上对ZYNQ-7000系列的XADC模块有个基本的了解后我们开始实验,首先解压2_Embedded_System.rar压缩包内的10_ps_xadc文件压到一个工作目录,注意路径不要有中文名字,然后用vavido2018.3打开ps_xadc.xpr工程,在工程主界面运行File—Launch SDK后按OK打开SDK的工作区,如下图示:
这里我们将修改工程软件实现片内温度和电压监控功能基础上采集开发板外部XADC接口输入的模拟电压,需要把工作模式从Default Mode修改为Continuous sequence mode模式,并对应配置使能位,修改后的代码如下:
//****************************************************************************************//
#include "xparameters.h"
#include "xadcps.h"
#include "stdio.h"
#include "xil_printf.h"
#include "sleep.h"
#define XADC_DEVICE_ID XPAR_XADCPS_0_DEVICE_ID //PS XADC 器件ID
static XAdcPs xadc_inst; //XADC驱动实例
int main(void)
{
int Op_status;
XAdcPs_Config*ConfigPtr; //XADC 配置指针
u32 temp_rawdata; //温度 原始数据
u32vcc_pint_rawdata; //PS 内核电压 原始数据
u32 vcc_paux_rawdata; //PS 辅助电压 原始数据
u32vcc_pddr_rawData; //PS DDR电压 原始数据
u32 vcc_int_rawdata; //PL 内核电压 原始数据
u32 vcc_aux_rawdata; //PL 辅助电压 原始数据
u32vcc_bram_rawData; //PL BRAM电压 原始数据
u32vcc_vpvn_rawData; //VP_VN电压 原始数据
float temp; //温度
float vcc_pint; //PS内核电压
float vcc_paux; //PS 辅助电压
float vcc_pddr; //PS DDR电压
float vcc_int; //PL 内核电压
float vcc_aux; //PL 辅助电压
float vcc_bram; //PL BRAM电压
float vcc_vpvn; //VP_VN电压
//初始化XADC驱动
ConfigPtr =XAdcPs_LookupConfig(XADC_DEVICE_ID);
XAdcPs_CfgInitialize(&xadc_inst,ConfigPtr, ConfigPtr->BaseAddress);
//设置XADC操作模式为“默认安全模式”
XAdcPs_SetSequencerMode(&xadc_inst,XADCPS_SEQ_MODE_SAFE);
//修改模式为连续采样并使能通道
Op_status =XAdcPs_SetSeqChEnables (&xadc_inst,XADCPS_SEQ_CH_TEMP |XADCPS_SEQ_CH_VCCPINT
| XADCPS_SEQ_CH_VCCPAUX |XADCPS_SEQ_CH_VCCPDRO | XADCPS_SEQ_CH_VCCINT
| XADCPS_SEQ_CH_VCCAUX | XADCPS_SEQ_CH_VBRAM| XADCPS_SEQ_CH_VPVN);
if(Op_status !=XST_SUCCESS)
{
printf("XAdcPs_SetSeqChEnableserror!\n\r");
}
XAdcPs_SetSequencerMode(&xadc_inst,XADCPS_SEQ_MODE_CONTINPASS);
while(1){
//获取原始温度传感器数据
temp_rawdata= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_TEMP);
//转换成温度信息
temp =XAdcPs_RawToTemperature(temp_rawdata);
//获取VCCPINT传感器数据,并转换成电压信息
vcc_pint_rawdata= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCPINT);
vcc_pint =XAdcPs_RawToVoltage(vcc_pint_rawdata);
//获取VCCPAUX传感器数据,并转换成电压信息
vcc_paux_rawdata= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCPAUX);
vcc_paux =XAdcPs_RawToVoltage(vcc_paux_rawdata);
//获取VCCPDRO传感器数据,并转换成电压信息
vcc_pddr_rawData= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCPDRO);
vcc_pddr =XAdcPs_RawToVoltage(vcc_pddr_rawData);
//获取VCCINT传感器数据,并转换成电压信息
vcc_int_rawdata= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCINT);
vcc_int =XAdcPs_RawToVoltage(vcc_int_rawdata);
//获取VCCAUX传感器数据,并转换成电压信息
vcc_aux_rawdata= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCAUX);
vcc_aux =XAdcPs_RawToVoltage(vcc_aux_rawdata);
//获取VBRAM传感器数据,并转换成电压信息
vcc_bram_rawData= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VBRAM);
vcc_bram =XAdcPs_RawToVoltage(vcc_bram_rawData);
//获取VPVN传感器数据,并转换成电压信息
vcc_vpvn_rawData= XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VPVN);
vcc_vpvn =XAdcPs_RawToVoltage(vcc_vpvn_rawData)/3;
//打印温度、电压信息
printf("RawTemp %lu, Real Temp %fC \n", temp_rawdata, temp);
printf("RawVccPInt %lu, Real VccPInt %fV \n", vcc_pint_rawdata, vcc_pint);
printf("RawVccPAux %lu, Real VccPAux %fV \n", vcc_paux_rawdata, vcc_paux);
printf("RawVccPDDR %lu, Real VccPDDR %fV \n", vcc_pddr_rawData, vcc_pddr);
printf("RawVccInt %lu, Real VccInt %fV \n", vcc_int_rawdata, vcc_int);
printf("RawVccAux %lu, Real VccAux %fV \n", vcc_aux_rawdata, vcc_aux);
printf("RawVccBram %lu, Real VccBram %fV \n", vcc_bram_rawData, vcc_bram);
printf("RawVccVPVN %lu, Real VccVPVN %fV \n", vcc_vpvn_rawData, vcc_vpvn);
printf("\n\r");
//延时5s
sleep(5);
}
return 0;
}
注意这里并没有设置控制寄存器0的输入极性比特,所以VP_VN输入极性是默认的单极性输入,我们可以在它们之间用一个直流电源输入0~1V的电源来进行测试,VN接电源地,VP接电源正极,测试过程和结果可以参看下面视频:
最后祝大家新年快乐!