在对模块进行信息监测时,会用到ZYNQ内部的VPVN通道,默认情况下该通道是不开启的,需要手动在内核驱动代码中设置
修改为
重新编译内核,加载镜像就能够系统/sys/bus/iio/devices/iio:device0/中看到VPVN了
将VPVN电压转换为温度可以参考下面代码TEMP1848_1
#ifndef _XADC_CORE_H
#define _XADC_CORE_H
#define MAX_PATH_SIZE 200
#define MAX_NAME_SIZE 50
#define MAX_VALUE_SIZE 100
#define MAX_CMD_NAME_SIZE 100
#define MAX_UNIT_NAME_SIZE 50
#define SYS_PATH_IIO "/sys/bus/iio/devices/iio:device0"
#define VCC_INT_CMD "xadc_get_value_vccint"
#define VCC_AUX_CMD "xadc_get_value_vccaux"
#define VCC_BRAM_CMD "xadc_get_value_vccbram"
#define VCC_TEMP_CMD "xadc_get_value_temp"
#define VCC_EXT_CH_CMD "xadc_get_value_ext_ch"
#define FPGA_TEMP "/sys/bus/iio/devices/iio:device0/in_temp0_raw"
#define TEMP1848_1 "/sys/bus/iio/devices/iio:device0/in_voltage8_vpvn_raw"
#define VCC_1 "/sys/bus/iio/devices/iio:device0/in_voltage0_vccint_raw"
#define VCC_1V8 "/sys/bus/iio/devices/iio:device0/in_voltage4_vccpaux_raw"
#define VCC_PINT "/sys/bus/iio/devices/iio:device0/in_voltage3_vccpint_raw"
#define VCC_PAUX "/sys/bus/iio/devices/iio:device0/in_voltage4_vccpaux_raw"
#define VCC_PDDR "/sys/bus/iio/devices/iio:device0/in_voltage5_vccoddr_raw"
static const int mV_mul = 1000;
static const int multiplier = 1 << 12;
enum EConvType
{
EConvType_None,
EConvType_Raw_to_Scale,
EConvType_Scale_to_Raw,
EConvType_Max
};
enum XADC_Param
{
EParamVccInt,
EParamVccAux,
EParamVccBRam,
EParamTemp,
EParamVAux0,
EParamMax
};
struct command
{
const enum XADC_Param parameter_id;
const char cmd_name[MAX_CMD_NAME_SIZE];
const char unit[MAX_UNIT_NAME_SIZE];
};
struct command command_list[EParamMax] = {
{EParamVccInt, VCC_INT_CMD, "mV"},
{EParamVccAux, VCC_AUX_CMD, "mV"},
{EParamVccBRam, VCC_BRAM_CMD, "mV"},
{EParamTemp, VCC_TEMP_CMD, "Degree Celsius"},
{EParamVAux0, VCC_EXT_CH_CMD, "mV"}
};
struct XadcParameter
{
const char name[MAX_NAME_SIZE];
float value;
float (* const conv_fn)(float,enum EConvType);
};
#endif
/*
* xadc_core.c
*
* Created on: 2017年9月20日
* Author: Administrator
*/
#include "xadc_core.h"
#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>
//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 * mV_mul)/multiplier);
break;
case EConvType_Scale_to_Raw:
result = (input/(3.0 * mV_mul))*multiplier;
break;
default:
printf("Convertion type incorrect... Doing no conversion\n");
// intentional no break;
case EConvType_None:
result = input;
break;
}
return result;
}
#if 0
float conv_voltage_ext_ch(float input, enum EConvType conv_direction)
{
float result=0;
switch(conv_direction)
{
case EConvType_Raw_to_Scale:
result = ((input * mV_mul)/multiplier);
break;
case EConvType_Scale_to_Raw:
result = (input/mV_mul)*multiplier;
break;
default:
printf("Convertion type incorrect... Doing no conversion\n");
// intentional no break;
case EConvType_None:
result = input;
break;
}
return result;
}
#endif
float conv_temperature(float input, enum EConvType conv_direction)
{
float result=0;
switch(conv_direction)
{
case EConvType_Raw_to_Scale:
result = ((input * 503.975)/multiplier) - 273.15;
break;
case EConvType_Scale_to_Raw:
result = (input + 273.15)*multiplier/503.975;
break;
default:
printf("Conversion type incorrect... Doing no conversion\n");
// intentional no break;
case EConvType_None:
result = input;
break;
}
return result;
}
float get_temp(int num)
{
int number;
int fd = -1;
char upset[20];
float raw_data=0;
float true_data=0;
int offset=0;
char value=0;
float max_temp=0;
number=num;
if(number==0)
{
fd = open(FPGA_TEMP, O_RDWR );
offset=0;
while(offset<5)
{
lseek(fd,offset,SEEK_SET);
read(fd,&value,sizeof(char));
upset[offset]=value;
offset++;
}
upset[offset]='\0';
raw_data=atoi(upset);
true_data=conv_temperature(raw_data, EConvType_Raw_to_Scale);
// true_data=(conv_voltage(raw_data, EConvType_Raw_to_Scale)*1000/(3*2.2)-273.15)/10000;
//printf("FPGA temp is %f cent\n",true_data);
close(fd);
return true_data;
}
else
{
fd = open(TEMP1848_1, O_RDWR );
offset=0;
while(offset<5)
{
lseek(fd,offset,SEEK_SET);
read(fd,&value,sizeof(char));
upset[offset]=value;
offset++;
}
upset[offset]='\0';
raw_data=atoi(upset);
true_data=(conv_voltage(raw_data, EConvType_Raw_to_Scale)*1000/(3*2.2)-273.15)/10000;
max_temp=true_data;
//printf("1848-1 temp is %f cent\n",true_data);
close(fd);
return max_temp;
}
}
float get_vcc(int num)
{
int number;
int fd = -1;
char upset[20];
float raw_data=0;
float true_data=0;
int offset=0;
char value=0;
number=num;
if(number==0)
{
fd = open(VCC_1, O_RDWR );
offset=0;
while(offset<5)
{
lseek(fd,offset,SEEK_SET);
read(fd,&value,sizeof(char));
upset[offset]=value;
offset++;
}
upset[offset]='\0';
raw_data=atoi(upset);
true_data=conv_voltage(raw_data, EConvType_Raw_to_Scale);
//printf("vcc 1 is %f mv\n",true_data);
close(fd);
}
else if(number==1)
{
fd = open(VCC_1V8, O_RDWR );
offset=0;
while(offset<5)
{
lseek(fd,offset,SEEK_SET);
read(fd,&value,sizeof(char));
upset[offset]=value;
offset++;
}
upset[offset]='\0';
raw_data=atoi(upset);
true_data=conv_voltage(raw_data, EConvType_Raw_to_Scale);
//printf("vcc 1v8 is %f mv\n",true_data);
close(fd);
}
else if(number==2)
{
fd = open(VCC_PINT, O_RDWR );
offset=0;
while(offset<5)
{
lseek(fd,offset,SEEK_SET);
read(fd,&value,sizeof(char));
upset[offset]=value;
offset++;
}
upset[offset]='\0';
raw_data=atoi(upset);
true_data=conv_voltage(raw_data, EConvType_Raw_to_Scale);
//printf("vcc pint is %f mv\n",true_data);
close(fd);
}
else if(number==3)
{
fd = open(VCC_PAUX, O_RDWR );
offset=0;
while(offset<5)
{
lseek(fd,offset,SEEK_SET);
read(fd,&value,sizeof(char));
upset[offset]=value;
offset++;
}
upset[offset]='\0';
raw_data=atoi(upset);
true_data=conv_voltage(raw_data, EConvType_Raw_to_Scale);
//printf("vcc paux is %f mv\n",true_data);
close(fd);
}
else if(number==4)
{
fd = open(VCC_PDDR, O_RDWR );
offset=0;
while(offset<5)
{
lseek(fd,offset,SEEK_SET);
read(fd,&value,sizeof(char));
upset[offset]=value;
offset++;
}
upset[offset]='\0';
raw_data=atoi(upset);
true_data=conv_voltage(raw_data, EConvType_Raw_to_Scale);
//printf("vcc pddr is %f mv\n",true_data);
close(fd);
}
return true_data/1000;
}
重点是下面这个公式
true_data=(conv_voltage(raw_data, EConvType_Raw_to_Scale)*1000/(3*2.2)-273.15)/10000;