1、ADC参数计算类
/// <summary>
/// ADC参数(SNR、THD、SFDR、ENOB)计算
/// </summary>
/// <param name="source"></param>
/// <param name="snr"></param>
/// <param name="thd"></param>
/// <param name="sfdr"></param>
/// <param name="enob"></param>
public static void AdcParameterCalculate(double[] source,out double snr,out double thd,out double sfdr,out double enob)
{
double P0 = 0;
double P1 = 0;
double PD = 0;
double PN = 0;
double PS = 0;
for(int i=0; i<source.Length; i++)
{
if (i == 0)
{
P0 = source[i];
}else if (i == 1)
{
P1 = source[i];
}else if(i>1 && i<11)
{
PD += source[i];
if (source[i] > PS)
{
PS = source[i];
}
}
else
{
PN += source[i];
if (source[i] > PS)
{
PS = source[i];
}
}
}
snr = 10 * Math.Log10(P1 / PN);
thd = 10 * Math.Log10(PD / P1);
sfdr = 10 * Math.Log10(P1 / PS);
double sinad = 10 * Math.Log10(P1 / (PN + PD));
enob = (sinad - 1.76) / 6.02;
}
/// <summary>
/// ADC参数(DNL、INL)计算
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="bits"></param>
/// <param name="scope"></param>
/// <param name="dnl"></param>
/// <param name="inl"></param>
public static void AdcDnlAndInlCalculate(List<double> x,List<double> y, int bits,double scope,out double dnl,out double inl)
{
List<double> data = LinearRegression(x, y);
double vlsb = GetVlsb(bits, scope);
dnl = AdcDnl(x, y, vlsb);
inl = AdcInl(data, y, vlsb);
}
/// <summary>
/// 求和
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static double Sum(List<double> source)
{
double sum = 0;
foreach(double d in source)
{
sum+= d;
}
return sum;
}
/// <summary>
/// 平方和
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static double SumOfSquare(List<double> source)
{
double sum = 0;
foreach (double d in source)
{
sum+= d*d;
}
return sum;
}
/// <summary>
/// 交叉积和
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static double SumOfCross(List<double> x, List<double> y)
{
double sum = 0;
for(int i=0; i<x.Count; i++)
{
double d = x[i] * y[i];
sum+= d;
}
return sum;
}
/// <summary>
/// 用最小二乘法计算一元一次函数的参数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="a"></param>
/// <param name="b"></param>
public static void LeastSquareMethod(List<double> x, List<double> y,out double a,out double b)
{
a = (SumOfSquare(x) * Sum(y) - Sum(x) * SumOfCross(x, y)) / (x.Count * SumOfSquare(x) - Sum(x) * Sum(x));
b = (x.Count * SumOfCross(x, y) - Sum(x) * Sum(y)) / (x.Count * SumOfSquare(x) - Sum(x) * Sum(x));
}
/// <summary>
/// 线性回归
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static List<double> LinearRegression(List<double> x, List<double> y)
{
LeastSquareMethod(x, y, out double a, out double b);
List<double> data = new List<double>();
foreach (double d in x)
{
double z = a + b * d;
data.Add(z);
}
return data;
}
/// <summary>
/// 计算VLSB
/// </summary>
/// <param name="bits"></param>
/// <param name="scope"></param>
/// <returns></returns>
public static double GetVlsb(int bits, double scope)
{
int count = (int)Math.Pow(2, bits);
double d = (scope - 0) / (count - 1);
//Console.WriteLine($"VLSB:{d}");
return d;
}
/// <summary>
/// 计算INL
/// </summary>
/// <param name="y1"></param>
/// <param name="y"></param>
/// <param name="vlsb"></param>
/// <returns></returns>
public static double AdcInl(List<double> y1, List<double> y, double vlsb)
{
double max = 0;
for (int i = 0; i < y1.Count; i++)
{
double x = Math.Abs(y1[i] - y[i]);
if (x > max) max = x;
}
double inl = max / vlsb;
//Console.WriteLine($"INL:{inl}");
return inl;
}
/// <summary>
/// 计算DNL
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="vlsb"></param>
/// <returns></returns>
public static double AdcDnl(List<double> x, List<double> y, double vlsb)
{
double max = 0;
for (int i = 1; i < x.Count; i++)
{
double d = Math.Abs(y[i] - y[i - 1]) / Math.Abs(x[i] - x[i - 1]);
if (d > max) max = d;
}
double dnl = (max - vlsb) / vlsb;
//Console.WriteLine($"DNL:{dnl}");
return dnl;
}
2、应用
private void AdcInitialize()
{
List<List<double>> idealData = IdealAdcData(4, 100);
AdcDnlAndInlCalculate(idealData[0], idealData[1], 4, 100, out double dnl, out double inl);
Console.WriteLine($"DNL:{dnl}");
Console.WriteLine($"INL:{inl}");
easyChartX2.Plot(idealData[1], 0, 1);
}
double[] res = FFT.ButterflyFFT(data);
FFT.AdcParameterCalculate(res, out SNR, out THD, out SFDR, out ENOB);
其中data为数据