1、背景介绍
国产ZYNQ XADC位于PL部分,和进口的对应关系如下:
外部的AUX只有8个通道,最终支持8路外部监测。
2、fpga设置
XADC不需要在linux内核中添加驱动,也不需要在设备数中添加节点,只需要知道FPGA中的XADC基地址,在应用程序中通过/dev/mem方式进行读写。
FPGA中建议将所有使用到的通道全部打开,AUX通道设置为0-11
然后确认XADC的基地址
3、应用设计
应用中可以使用一套代码,需要改动的部分包括:
- XADC基地址
- 外部AUX通道采集的数据经过电阻分压的转换公式
转换公式一般是将读到的原始数据先除以65536 再进行转换
注意:由于和进口存在区别,程序读到的值为下图右侧XADC的通道值,硬件设计是使用下图左侧XADC的通道值。
硬件只提供左侧的通道采样的信息:
应用程序中换算为右侧对应的通道,获取采样值。
举例 通道9就是应用中读到的XADCPS_CH_AUX[2]
除了8个外部通道AUX外,其他通道不需要转换。
使用XADC采样前,需要对XADC进行初始化部分。
参考代码如下:
#ifndef _XADC_CORE_H
#define _XADC_CORE_H
#include "../global/xil_types.h"
#define XADC_BASE_ADDR 0x83C30000U
#define XADCPS_CH_TEMP 0x200 /**< On Chip Temperature */
#define XADCPS_CH_VCCINT 0x204 /**< VCCINT */
#define XADCPS_CH_VCCAUX 0x208 /**< VCCAUX */
#define XADCPS_CH_VPVN 0x20c /**< VP/VN Dedicated analog inputs */
#define XADCPS_CH_VREFP 0x210 /**< VREFP */
#define XADCPS_CH_VREFN 0x214 /**< VREFN */
#define XADCPS_CH_VBRAM 0x218 /**< On-chip VBRAM Data Reg, 7 series */
#define XADCPS_CH_SUPPLY_CALIB 0x220 /**< Supply Calib Data Reg */
#define XADCPS_CH_ADC_CALIB 0x224 /**< ADC Offset Channel Reg */
#define XADCPS_CH_GAINERR_CALIB 0x228 /**< Gain Error Channel Reg */
#define XADCPS_CH_VCCPINT 0x234 /**< On-chip PS VCCPINT Channel , Zynq */
#define XADCPS_CH_VCCPAUX 0x238 /**< On-chip PS VCCPAUX Channel , Zynq */
#define XADCPS_CH_VCCPMEM 0x23c /**< On-chip PS VCCPMEM Channel , Zynq */
#define XADCPS_CH_AUX_MIN 0x240 /**< Channel number for 1st Aux Channel */
#define XADCPS_CH_AUX_MAX 0x27c /**< Channel number for Last Aux channel */
enum EConvType
{
EConvType_None,
EConvType_Raw_to_Scale,
EConvType_Scale_to_Raw,
EConvType_Max
};
float conv_temperature(float input, enum EConvType conv_direction);
float conv_voltage(float input, enum EConvType conv_direction);
void xadc_initialization();
#endif
/*
* xadc_core.c
*
* Created on: 2017年9月20日
* Author: Administrator
*/
#define __XADC_CORE_C_
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <ctype.h>
#include <pthread.h>
#include <assert.h>
#include "xadc_core.h"
#include "../global/xil_io.h"
void xadc_initialization()
{
Xil_Out32(XADC_BASE_ADDR+0x000, 0xA);
Xil_Out32(XADC_BASE_ADDR+0x010, 0x1);
Xil_Out32(XADC_BASE_ADDR+0x010, 0x0);
}
//utility functions
float conv_voltage(float input, enum EConvType conv_direction)
{
float result=0;
switch(conv_direction)
{
case EConvType_Raw_to_Scale:
result = ((input * 3.0)/65536.0);
break;
default:
break;
}
return result;
}
float conv_temperature(float input, enum EConvType conv_direction)
{
float result=0;
switch(conv_direction)
{
case EConvType_Raw_to_Scale:
result = ((input / 65536.0)/0.00198421639) - 273.15;
break;
default:
break;
}
return result;
}
//transfer float to unsigned char
unsigned char transfer(float temp)
{
unsigned char result;
char buff[100];
int before,end;
memset(buff,0,sizeof(buff));
sprintf(buff,"%.2f",temp);
sscanf(buff,"%d.%d",&before,&end);
result=(before<<4)|end;
return result;
}
void printadc()
{
float raw_data=0;
float true_data=0;
raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_TEMP);
//printf("XADCPS_CH_TEMP is %f\n",raw_data);
true_data=conv_temperature(raw_data,EConvType_Raw_to_Scale);
printf("XADCPS_CH_TEMP TRUE DATA is %.2fCent\n",true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCINT);
//printf("XADCPS_CH_VCCINT is %f\n",raw_data);
true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
printf("XADCPS_CH_VCCINT TRUE DATA is %.2fV\n",true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCAUX);
//printf("XADCPS_CH_VCCAUX is %f\n",raw_data);
true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
printf("XADCPS_CH_VCCAUX TRUE DATA is %.2fV\n",true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VBRAM);
//printf("XADCPS_CH_VBRAM is %f\n",raw_data);
true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
printf("XADCPS_CH_VBRAM TRUE DATA is %.2fV\n",true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCPINT);
//printf("XADCPS_CH_VCCPINT is %f\n",raw_data);
true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
printf("XADCPS_CH_VCCPINT TRUE DATA is %.2fV\n",true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCPAUX);
//printf("XADCPS_CH_VCCPAUX is %f\n",raw_data);
true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
printf("XADCPS_CH_VCCPAUX TRUE DATA is %.2fV\n",true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+XADCPS_CH_VCCPMEM);
//printf("XADCPS_CH_VCCPMEM is %f\n",raw_data);
true_data=conv_voltage(raw_data,EConvType_Raw_to_Scale);
printf("XADCPS_CH_VCCPMEM TRUE DATA is %.2fV\n",true_data);
printf("\n****************AUX DATA****************** \n");
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN));
true_data=(raw_data/65536.0)*2.0; //换算公式
printf("XADCPS_CH_AUX[%d] 1V2 is %.2fV\n",0,true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+1*4));
true_data=(raw_data/65536.0)*2.0; //换算公式
printf("XADCPS_CH_AUX[%d] 1V2 is %.2fV\n",1,true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+2*4));
true_data=raw_data/65536.0; //换算公式
printf("XADCPS_CH_AUX[%d] 1V0 is %.2fV\n",2,true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+3*4));
true_data=raw_data/65536.0; //换算公式
printf("XADCPS_CH_AUX[%d] 1V5 is %.2fV\n",2,true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+4*4));
true_data=(raw_data/65536.0*3.0)/2.0; //换算公式
printf("XADCPS_CH_AUX[%d] 3V3 is %.2fV\n",4,true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+8*4));
true_data=(raw_data/65536.0*3.0)/2.0; //换算公式
printf("XADCPS_CH_AUX[%d] 3V3 is %.2fV\n",8,true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+10*4));
true_data=(raw_data/65536.0*3.0)/2.0; //换算公式
printf("XADCPS_CH_AUX[%d] 1V2 is %.2fV\n",10,true_data);
raw_data = Xil_In32(XADC_BASE_ADDR+(XADCPS_CH_AUX_MIN+11*4));
true_data=(raw_data/65536.0)*2.0; //换算公式
printf("XADCPS_CH_AUX[%d] 2V5 is %.2fV\n",11,true_data);
printf("\n************************************** \n");
printf("\n************************************** \n");
printf("\n************************************** \n");
}
int main()
{
xadc_initialization();
printadc();
return 0;
}