|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
本帖最后由 kongc 于 2020-8-18 11:38 编辑
最近在做一个saradc的fft仿真,在网上找的matlab代码,加上自己的数据,发现得到的频谱图很离谱,有没有大佬有兴趣拿着代码和数据试一下,帮我看看哪里出错了?,谢谢!
- %***********************************************************************%
- % The following program code plots the FFT spectrum of a desired test tone.
- % Test tone based on coherent sampling criteria, and computes SNR, SNDR, THD and SFDR.
- % This program is believed to be accurate and reliable.
- % This program may get altered without prior notification.;
- % Company: xxx analog Mixed-signal Group
- % Author:
- % Date: 2016-01-09
- %***********************************************************************%
- %***********************************************************************%
- % 采样时钟240MHz,输入信号频率86.25MHz,FFT点数64,ADC分辨率10bit,仿真时间400ns。
- % 从cadence输出时间隔是4.16666667ns,共计97个点,从第20个点开始取64点做FFT。
- % cadence输出的是归一化的结果范围是0-1.6V,需除以1.6再乘以1024,转换为数字码。
- %***********************************************************************%
- clear all;
- close all;
- %spectP_file='spec.csv';
- %***********************************************************************%
- % 输入采样时钟、样本点数、分辨率等变量
- %***********************************************************************%
- fs=100e6; %采样时钟
- Data_Num=32768; %样本点数
- numbit=12; %ADC分辨率
- data_start=1; %取点起始位置
- fclk=fs/1e6; %x坐标轴数值显示
- numpt=Data_Num;
- fres=fclk/numpt; %Desired frequency resolution of FFT[MHz], fres=fclk/2^N
- %***********************************************************************%
- % 读取数据
- %***********************************************************************%
- %d_in=dlmread('E:\kongcaho\ADC\MATLAB\adc_data_0715.csv','%s')';
- %d_in=d_in*2^numbit;
- d_in=csvread('E:\kongcaho\ADC\MATLAB\adc_data.csv');%以字符形式打开文件
- d11=1;d10=2;d9=3;d8=4;d7=5;d6=6;d5=7;d4=8;d3=9;d2=10;d1=11;d0=12;%标示样本矩阵的列
- vref=1;
- %adc_data=d_in;
- adc_data=round(d_in);
- for i=1:numpt
- dout(i)=adc_data(i,d11)/2+adc_data(i,d10)/4+adc_data(i,d9)/8 ...
- +adc_data(i,d8)/16+adc_data(i,d7)/32+adc_data(i,d6)/64 ...
- +adc_data(i,d5)/128+adc_data(i,d4)/254+adc_data(i,d3)/512 ...
- +adc_data(i,d2)/1024+adc_data(i,d1)/2048+adc_data(i,d0)/4096;%通过转换器出来的结果,恢复原来的波形
- doute(i)=dout(i)-0.5;%将正弦波的共模电平偏置为0
- %doute(i)=dout(i)-mean(dout(i));
- end
- code=zeros(1,numpt); %创建一个全为0元素的数组
- %for i=1:1:numpt
- %code(1:numpt)=d_in(data_start:data_start+numpt-1);
- %end
- for i=1:numpt
- code(i)=adc_data(i,d11)*2048+adc_data(i,d10)*1024+adc_data(i,d9)*512 ...
- +adc_data(i,d8)*256+adc_data(i,d7)*128+adc_data(i,d6)*64+adc_data(i,d5)*32 ...
- +adc_data(i,d4)*16+adc_data(i,d3)*8+adc_data(i,d2)*4+adc_data(i,d1)*2+adc_data(i,d0)*1;%通过转换器出来的结果,恢复原来的波形
-
- end
- dcadc(code,numpt);
- %***********************************************************************%
- % Plot output code
- %***********************************************************************%
- figure;
- plot(code);
- title(sprintf('ADC Digital Output'));
- figure;
- plot(dout);
- title(sprintf('ADC ANALOG Output'));
- %***********************************************************************%
- % Recenter the digital sine wave, for 2's complement code
- %***********************************************************************%
- %m_ean=mean(code); %求code数组的平均值
- %for hk=1:length(code)
- % code(hk)=code(hk)-m_ean;
- %end
- %***********************************************************************%
- % Display a warning, when the input generates a code greater than
- % full-scale, for 2's complement code
- %***********************************************************************%
- max_code=max(code)
- min_code=min(code)
- if (max(code)==2^numbit-1) | (min(code)==0)
- %if (max(code)==2^numbit -1) | (min(code)==0)
- disp('Warning: ADC may be clipping!');
- end
- %***********************************************************************%
- % Normalize input signal relative to full-scale
- %***********************************************************************%
- fin_dB=20*log10((max_code-min_code)/(2^numbit));
- %***********************************************************************%
- % 对数据样本加窗函数处理
- %***********************************************************************%
- % If no window function is used, the input tone must be chosen to be unique and with
- % regard to the sampling frequency. To achieve this prime numbers are introduced and the
- % input tone is determined by Fin = Fsample * (Prime Number / Data Record Size).
- % To relax this requirement, window functions such as HANNING and HAMING (see below) can
- % be introduced, however the fundamental in the resulting FFT spectrum appears 'sharper'
- %without the use of window functions.
- Dout=doute';
- %Doutw=Dout;
- Doutw=Dout.*hanning(numpt);
- % Doutw=Dout.*hamming(numpt);
- % Doutw=Dout.*blackman(numpt);
- %***********************************************************************%
- % Performing the Fast Fourier Transform [FFT]
- %***********************************************************************%
- %span=5; %Span of the input frequency on each side;
- span=max(round(numpt/200),5);
- spanh=2; %Approximate search span for harmonics on each side
- spandc=12; %Approximate search span for DC on right side
- Dout_spect=fft(Doutw);
- Dout_dB=20*log10(abs(Dout_spect)); %Recalculate to dB abs(Dout_spect)
- spectP=(abs(Dout_spect)).*(abs(Dout_spect)); %Determine power spectrum
- maxdB=max(Dout_dB(1+spandc:numpt/2));
- fin=find(Dout_dB(1:numpt/2)==maxdB); %Find the signal bin number, DC=bin1
- %fin=200;
- %***********************************************************************%
- % Calculate SNR, SNDR, THD and SFDR values.
- %***********************************************************************%
- %fw=fopen(spectP_file,'w'); %write the power soectrum to file
- %fprintf(fw,'%12.9e\n',spectP);
- %fclose('all');
- %Find DC offset power
- Pdc=sum(spectP(1:span));
- %Extract overall signal power
- idx1=fin-span;
- idx2=fin+span;
- if(idx1<=0)
- idx1 = 1;
- end
- Ps=sum(spectP(idx1:idx2)); %信号功率
- %Vector/matrix to store both frequency and power of signal and harmonics
- Fh=[];
- %The 1st element in the vector/matrix represents the signal, the next element represents the 2nd harmonic
- Ph=[];
- %Vector/matrix to store the sampling points responding to the harmonics
- Nh=[];
- %Ah represents signal and harmonic amplitude
- Ah=[];
- %Find harmonic frequencies and power components in the FFT spectrum
- %For this procedure to work, ensure the folded back high order harmonics do not overlap
- %with DC or signal or lower order harmonics , so it should be modified according to the actual condition
- for har_num=1:5
- tone=rem((har_num*(fin-1)+1)/numpt,1); %Input tones greater than fSAMPLE are aliased back into the spectrum
- if tone>0.5
- tone=1-tone; %Input tones greater than 0.5*Fsample (aft er aliasing) are reflected
- end
- Fh=[Fh tone];
- %Check Nh to see the bin of the harmonics
- Nh=[Nh round(tone*numpt)];
- %For this procedure to work, ensure the folded back high order harmonics do not overlap
- %with DC or signal or lower order harmonics
- har_peak=max(spectP(round(tone*numpt)-spanh:round(tone*numpt)+spanh));
- har_bin=find(spectP(round(tone*numpt)-spanh:round(tone*numpt)+spanh)==har_peak);
- har_bin=har_bin+round(tone*numpt)-spanh-1;
- Ph=[Ph sum(spectP(har_bin-spanh:har_bin+spanh))];
- Ah=[Ah Dout_dB(har_bin)];
- end
- %Determine the total distortion power, it should be modified according to the actual condition.
- Pd=sum(Ph(2:5)); %总谐波功率
- %Determine the noise power
- Pn=sum(spectP(1:numpt/2))-Pdc-Ps-Pd; %噪声功率
- %Determine the next largest component
- spur_max=max(max(spectP(spandc+1:fin-span-1)),max(spectP(fin+span+1:numpt/2)));
- spur_bin=find(spectP(1:numpt/2)==spur_max);
- %**********************计算动态特性结果**********************%
- format; %设置输出格式
- SFDR = 10*log10(max(spectP(1:numpt/2))/spur_max); %-fin_dB
- THD = 10*log10(Pd/Ps); %+fin_dB
- SNR = 10*log10(Ps/Pn); %-fin_dB
- SNDR = 10*log10(Ps/(Pn+Pd)); %-fin_dB
- ENOB = (SNDR-1.76)/6.02;
- %disp('Note: THD is calculated from 2nd through 10th order harmonics.');
- %*********************标示信号和谐波位置*********************%
- %hold on;
- %plot((Nh(2:10)-1).*fres,Ah(2:10)-maxdB+fin_dB,'rs');
- % 标示信号
- bins=(Nh(1)-1)*fres;
- Ahs=Ah(1)-maxdB+fin_dB;
- % 标示2次谐波
- bin2=(Nh(2)-1)*fres;
- Ah2=Ah(2)-maxdB+fin_dB;
- % 标示3次谐波
- bin3=(Nh(3)-1)*fres;
- Ah3=Ah(3)-maxdB+fin_dB;
- % 标示4次谐波
- bin4=(Nh(4)-1)*fres;
- Ah4=Ah(4)-maxdB+fin_dB;
- % 标示5次谐波
- bin5=(Nh(5)-1)*fres;
- Ah5=Ah(5)-maxdB+fin_dB;
- % 在FFT频谱图中追加标示
- figure;
- plot(bins,Ahs,'rs',bin2,Ah2,'rd',bin3,Ah3,'r^',bin4,Ah4,'r*',bin5,Ah5,'rx');
- legend('SINGAL','HD2','HD3','HD4','HD5');
- %**********************图表显示**********************%
- ylabel('Full-Scale Normalized Magnitude[dB]')
- xlabel('Frequency [MHz]')
- title(sprintf('ADC FFT Spectrum (%g points)\nFs = %g MSps, Fin = %g MHz (%1.2gdBFS)', Data_Num,fs/1e6,(fin-1)*fres,fin_dB));
- grid on;
- box on;
- ylim([-110 100]);
- set(gca,'xgrid', 'off');
- set(gca, 'GridLineStyle' ,'-');
- set(gca,'yTick',[-110:10:100]);
- %****************************************************%
- %Display the results in the frequency domAIn with an FFT plot.
- for i=0:1:(numpt/2-1)
- hold on;
- line([i*fres,i*fres],[-110,Dout_dB(i+1)-maxdB+fin_dB],'LineWidth',2);
- hold off;
- end
- %***********************在图中打印结果***********************%
- hold on;
- s1=sprintf('SFDR = %4.1fdB\n',SFDR);
- s2=sprintf('THD = %4.1fdB\n',THD);
- s3=sprintf('SNR = %4.1fdB\n',SNR);
- s4=sprintf('SNDR = %4.1fdB\n',SNDR);
- s5=sprintf('ENOB = %4.2fbit\n',ENOB);
- text(25,-10,s1);
- text(25,-20,s2);
- text(25,-30,s3);
- text(25,-40,s4);
- text(25,-50,s5);
- hold off;
复制代码
- function[DNL,INL,vo]=dcdac(vi,num);
- %vi_in=dlmread('E:\kongcaho\ADC\MATLAB\adc_data_0715.csv','%s')';
- %num=4096;
- vi_f=vi;
- format long;
- bit=12;%ADC精度
- n=2^bit;%ADC输出码数目
- N_negetive=0;%高于0的采样总数
- N_positive=0;%低于0的采样总数
- N_tot=0;%总采样数目
- A=0.5;%正弦波幅度
- temp=vi_f ; %读入数
- %-----------------------------------------------%
- %计算每个码的统计次数
- %-----------------------------------------------%
- hh=zeros(n,1);
- for i=1:2^bit
- count=0;%附值
- for j=1:num
- if temp(j)==i-1
- count=count+1;
- else count=count;
- end
- end
- hh(i)=count;
- end
- h=[hh(1:2^bit)];
- LSB=A*2.0/(2^bit);%理想LSB
- %-----------------------------------------------%
- %计算offset:vo
- %-----------------------------------------------%
- N_negetive=sum(hh(1:n/2));
- N_positive=sum(hh(n/2+1:n));
- N_tot=sum(hh(1:n))
- vo=A*pi/2*sin((N_positive-N_negetive)/N_tot)
- %-----------------------------------------------%
- %计算INL、DNL
- %-----------------------------------------------%
- ch=zeros(n,1);
- v=zeros(n,1);%possibility of the ith code occurs
- in=zeros(n,1);%每级台阶的INL
- dn=zeros(n,1);%每级台阶的DNL
- for i=1:n
- for j=1:i
- ch(i)=ch(i)+h(j);
- end
- v(i)=-cos(pi*ch(i)/N_tot);
- end
- LSB=(v(n-1)-v(2))/(n-3);%实际LSB
- for i=1:n-1
- in(i)=v(i)/LSB-i+1024;
- % in(i)=(v(i)-vo)/LSB-i+2048;
- dn(i)=(v(i+1)-v(i))/LSB-1;
- end
- INL=max(abs(in))
- DNL=max(abs(dn))
- %-----------------------------------------------%
- %初始化转移曲线坐标
- %-----------------------------------------------%
- vv(1)=-A;
- vv(2)=v(1);
- xx(1)=0;
- xx(2)=0;
- vv(2*(n-1)+1)=v(n-1);
- xx(2*(n-1)+1)=n-1;
- for i=1:n-2
- vv(2*i+1)=v(i);
- vv(2*i+2)=v(i+1);
- xx(2*i+1)=i;
- xx(2*i+2)=i;
- end
- %-----------------------------------------------%
- figure;
- subplot(2,1,1);%画INL
- plot(2:n-2,in(2:n-2),'-.rd');
- xlabel('DIGITAL OUTPUT CODE');
- ylabel('INL(LSB)');
- title('INL vs.DIGITAL OUTPUT CODE');
- grid on;
- subplot(2,1,2);%画DNL
- plot(1:n-3,dn(1:n-3));
- xlabel('DIGITAL OUTPUT CODE');
- ylabel('DNL(LSB)');
- title('DNL vs.DIGITAL OUTPUT CODE');
- grid on;
- figure;
- subplot(2,1,1);%画码密度柱状图
- bar(1:n,hh,'g');
- xlabel('DIGITAL OUTPUT CODE');
- ylabel('Count of code');
- title('Histogram Graph of Code Density');
- axis([-100 2100 0 1000]);
- grid on;
- subplot(2,1,2);%画转移曲线
- plot(vv(1:2*(n-1)),xx(1:2*(n-1)));
- %plot(vv(1:n),xx(1:n));
- xlabel('Input Voltage(V)');
- ylabel('DIGITAL OUTPUT CODE');
- title('Transfer Function');
- axis([-1,1,0,2^bit-1]);
- grid on;
复制代码
|
-
频谱图
-
-
adc_data.zip
87.68 KB, 下载次数: 12
, 下载积分:
资产 -2 信元, 下载支出 2 信元
数据
|