在对模块进行信息监测时,会用到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;