在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 9431|回复: 13

[求助] 用matlab做adc的动态参数仿真

[复制链接]
发表于 2020-7-23 14:37:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 kongc 于 2020-7-23 15:02 编辑

本人最近在研究ADC,现在是用matlab做fft分析,用网上找的代码加上自己的数据,运行后频谱图结果是出来了,但是那些动态参数一个都没有计算出来,而且都提示“下标索引必须为正整数类型或逻辑类型。”,求大佬指点迷津。
 楼主| 发表于 2020-7-23 15:03:34 | 显示全部楼层
代码如下:




  1. %***********************************************************************%
  2. % The following program code plots the FFT spectrum of a desired test tone.
  3. % Test tone based on coherent sampling criteria, and computes SNR, SNDR, THD and SFDR.
  4. % This program is believed to be accurate and reliable.
  5. % This program may get altered without prior notification.;
  6. % Company: xxx analog Mixed-signal Group
  7. % Author:
  8. % Date: 2016-01-09
  9. %***********************************************************************%




  10. %***********************************************************************%
  11. % 采样时钟240MHz,输入信号频率86.25MHz,FFT点数64,ADC分辨率10bit,仿真时间400ns。
  12. % 从cadence输出时间隔是4.16666667ns,共计97个点,从第20个点开始取64点做FFT。
  13. % cadence输出的是归一化的结果范围是0-1.6V,需除以1.6再乘以1024,转换为数字码。
  14. %***********************************************************************%




  15. clear all;
  16. clc;
  17. datafile='ADC_result8.csv'
  18. spectP_file='spec.csv';




  19. %***********************************************************************%
  20. % 输入采样时钟、样本点数、分辨率等变量
  21. %***********************************************************************%
  22. fs=240e6;        %采样时钟
  23. Data_Num=64;   %样本点数
  24. numbit=10;       %ADC分辨率
  25. data_start=20; %取点起始位置
  26. fclk=fs/1e6;     %x坐标轴数值显示
  27. numpt=Data_Num;
  28. fres=fclk/numpt; %Desired frequency resolution of FFT[MHz], fres=fclk/2^N


  29. %***********************************************************************%
  30. % 读取数据
  31. %***********************************************************************%
  32. d_in=csvread('ADC_result8.csv',1,1);
  33. d_in=d_in/1.6*1024;
  34. code=zeros(1,numpt);
  35. code(1:numpt)=d_in(data_start:data_start+numpt-1);


  36. %***********************************************************************%
  37. % Plot output code
  38. %***********************************************************************%
  39. figure;
  40. plot(code);
  41. title(sprintf('ADC Digital Output'));


  42. %***********************************************************************%
  43. % Recenter the digital sine wave, for 2's complement code
  44. %***********************************************************************%
  45. m_ean=mean(code);
  46. for hk=1:length(code)
  47.     code(hk)=code(hk)-m_ean;
  48. end


  49. %***********************************************************************%
  50. % Display a warning, when the input generates a code greater than
  51. % full-scale, for 2's complement code
  52. %***********************************************************************%
  53. max_code=max(code)
  54. min_code=min(code)
  55. if (max(code)>2^(numbit-1)) | (min(code)<(0-2^(numbit-1)))
  56. %if (max(code)==2numbit -1) | (min(code)==0)
  57.     disp('Warning: ADC may be clipping!');
  58. end


  59. %***********************************************************************%
  60. % Normalize input signal relative to full-scale
  61. %***********************************************************************%
  62. fin_dB=20*log10((max_code-min_code)/(2^numbit));


  63. %***********************************************************************%
  64. % 对数据样本加窗函数处理
  65. %***********************************************************************%
  66. % If no window function is used, the input tone must be chosen to be unique and with
  67. % regard to the sampling frequency. To achieve this prime numbers are introduced and the
  68. % input tone is determined by Fin = Fsample * (Prime Number / Data Record Size).
  69. % To relax this requirement, window functions such as HANNING and HAMING (see below) can
  70. % be introduced, however the fundamental in the resulting FFT spectrum appears 'sharper'
  71. %without the use of window functions.
  72. Dout=code';
  73. Doutw=Dout;
  74. % Doutw=Dout.*hanning(numpt);
  75. % Doutw=Dout.*hamming(numpt);
  76. % Doutw=Dout.*blackman(numpt);


  77. %***********************************************************************%
  78. % Performing the Fast Fourier Transform [FFT]
  79. %***********************************************************************%
  80. span=0; %Span of the input frequency on each side; span=max(round(numpt/200),5);
  81. spanh=0; %Approximate search span for harmonics on each side
  82. spandc=0; %Approximate search span for DC on right side
  83. Dout_spect=fft(Doutw);
  84. Dout_dB=20*log10(abs(Dout_spect)); %Recalculate to dB abs(Dout_spect)
  85. spectP=(abs(Dout_spect)).*(abs(Dout_spect)); %Determine power spectrum
  86. maxdB=max(Dout_dB(1+spandc:numpt/2));
  87. fin=find(Dout_dB(1:numpt/2)==maxdB); %Find the signal bin number, DC=bin1


  88. %***********************************************************************%
  89. % Calculate SNR, SNDR, THD and SFDR values.
  90. %***********************************************************************%
  91. fw=fopen(spectP_file,'w'); %write the power soectrum to file
  92. fprintf(fw,'%12.9e\n',spectP);
  93. fclose('all');
  94. %Find DC offset power
  95. Pdc=sum(spectP(1:span));
  96. %Extract overall signal power
  97. idx1=fin-span;
  98. idx2=fin+span;
  99. if(idx1<=0)
  100.     idx1 = 1;
  101. end
  102. Ps=sum(spectP(idx1:idx2));
  103. %Vector/matrix to store both frequency and power of signal and harmonics
  104. Fh=[];
  105. %The 1st element in the vector/matrix represents the signal, the next element represents the 2nd harmonic
  106. Ph=[];
  107. %Vector/matrix to store the sampling points responding to the harmonics
  108. Nh=[];
  109. %Ah represents signal and harmonic amplitude
  110. Ah=[];
  111. %Find harmonic frequencies and power components in the FFT spectrum
  112. %For this procedure to work, ensure the folded back high order harmonics do not overlap
  113. %with DC or signal or lower order harmonics , so it should be modified according to the actual condition
  114. for har_num=1:5
  115.     tone=rem((har_num*(fin-1)+1)/numpt,1); %Input tones greater than fSAMPLE are aliased back into the spectrum
  116.     if tone>0.5
  117.         tone=1-tone; %Input tones greater than 0.5*Fsample (after aliasing) are reflected
  118.     end
  119.     Fh=[Fh tone];
  120.     %Check Nh to see the bin of the harmonics
  121.     Nh=[Nh round(tone*numpt)];
  122.     %For this procedure to work, ensure the folded back high order harmonics do not overlap
  123.     %with DC or signal or lower order harmonics
  124.     har_peak=max(spectP(round(tone*numpt)-spanh:round(tone*numpt)+spanh));
  125.     har_bin=find(spectP(round(tone*numpt)-spanh:round(tone*numpt)+spanh)==har_peak);
  126.     har_bin=har_bin+round(tone*numpt)-spanh-1;
  127.     Ph=[Ph sum(spectP(har_bin-spanh:har_bin+spanh))];
  128.     Ah=[Ah Dout_dB(har_bin)];
  129. end
  130. %Determine the total distortion power, it should be modified according to the actual condition.
  131. Pd=sum(Ph(2:5));
  132. %Determine the noise power
  133. Pn=sum(spectP(1:numpt/2))-Pdc-Ps-Pd;
  134. %Determine the next largest component
  135. spur_max=max(max(spectP(spandc+1:fin-span-1)),max(spectP(fin+span+1:numpt/2)));
  136. spur_bin=find(spectP(1:numpt/2)==spur_max)
  137. %**********************计算动态特性结果**********************%
  138. format; %设置输出格式
  139. SFDR = 10*log10(max(spectP(1:numpt/2))/spur_max); %-fin_dB
  140. THD = 10*log10(Pd/Ps); %+fin_dB
  141. SNR = 10*log10(Ps/Pn); %-fin_dB
  142. SNDR = 10*log10(Ps/(Pn+Pd)); %-fin_dB
  143. ENOB = (SNDR-1.76)/6.02;
  144. %disp('Note: THD is calculated from 2nd through 10th order harmonics.');
  145. %*********************标示信号和谐波位置*********************%
  146. %hold on;
  147. %plot((Nh(2:10)-1).*fres,Ah(2:10)-maxdB+fin_dB,'rs');
  148. % 标示信号
  149. bins=(Nh(1)-1)*fres;
  150. Ahs=Ah(1)-maxdB+fin_dB;
  151. % 标示2次谐波
  152. bin2=(Nh(2)-1)*fres;
  153. Ah2=Ah(2)-maxdB+fin_dB;
  154. % 标示3次谐波
  155. bin3=(Nh(3)-1)*fres;
  156. Ah3=Ah(3)-maxdB+fin_dB;
  157. % 标示4次谐波
  158. bin4=(Nh(4)-1)*fres;
  159. Ah4=Ah(4)-maxdB+fin_dB;
  160. % 标示5次谐波
  161. bin5=(Nh(5)-1)*fres;
  162. Ah5=Ah(5)-maxdB+fin_dB;
  163. % 在FFT频谱图中追加标示
  164. figure;
  165. plot(bins,Ahs,'rs',bin2,Ah2,'rd',bin3,Ah3,'r^',bin4,Ah4,'r*',bin5,Ah5,'rx');
  166. legend('SINGAL','HD2','HD3','HD4','HD5');
  167. %**********************图表显示**********************%
  168. ylabel('Full-Scale Normalized Magnitude[dB]')
  169. xlabel('Frequency [MHz]')
  170. title(sprintf('ADC FFT Spectrum (%g points)\nFs = %g MSps, Fin = %g MHz (%1.2gdBFS)', Data_Num,fs/1e6,(fin-1)*fres,fin_dB));
  171. grid on;
  172. box on;
  173. ylim([-110 10]);
  174. set(gca,'xgrid', 'off');
  175. set(gca, 'GridLineStyle' ,'-');
  176. set(gca,'yTick',[-110:10:10]);
  177. %****************************************************%
  178. %Display the results in the frequency domAIn with an FFT plot.
  179. for i=0:1:numpt/2-1)
  180.     hold on;
  181.     line([i*fres,i*fres],[-110,Dout_dB(i+1)-maxdB+fin_dB],'LineWidth',2);
  182.     hold off;
  183. end
  184. %***********************在图中打印结果***********************%
  185. hold on;
  186. s1=sprintf('SFDR = %4.1fdB\n',SFDR);
  187. s2=sprintf('THD = %4.1fdB\n',THD);
  188. s3=sprintf('SNR   = %4.1fdB\n',SNR);
  189. s4=sprintf('SNDR = %4.1fdB\n',SNDR);
  190. s5=sprintf('ENOB = %4.2fbit\n',ENOB);
  191. text(25,-10,s1);
  192. text(25,-20,s2);
  193. text(25,-30,s3);
  194. text(25,-40,s4);
  195. text(25,-50,s5);
  196. hold off;


复制代码
发表于 2020-7-24 14:47:47 | 显示全部楼层
没有必要用网上找的matlab代码,直接用波形窗口的频谱分析工具不香吗?
 楼主| 发表于 2020-7-24 17:29:31 | 显示全部楼层
那个频谱分析工具可以算ADC的动态参数吗?我之前也研究过,但好像就是因为只有频谱图没有参数的计算才考虑代码的
 楼主| 发表于 2020-7-26 15:21:44 | 显示全部楼层
原因找到了,下列代码中的fin值过小。fft后的dout_dB的值前两个都很大,导致fin值很小,后面的矩阵下标都是负值了,所以改了spandc的值把前两个dout_dB忽略掉就正常了。但是这样我有两个问题:一是这样忽略会不会有问题?二是为什么fft后前两个点的幅度怎么这么大,明显比后面的值大很多。



  1. Dout_spect=fft(Doutw);
  2. Dout_dB=20*log10(abs(Dout_spect)); %Recalculate to dB abs(Dout_spect)
  3. spectP=(abs(Dout_spect)).*(abs(Dout_spect)); %Determine power spectrum
  4. maxdB=max(Dout_dB(1+spandc:numpt/2));
  5. fin=find(Dout_dB(1:numpt/2)==maxdB);


复制代码
发表于 2021-4-7 10:37:43 | 显示全部楼层
顶一个,遇到过同样的问题,增大输入信号频率之后解决了
发表于 2021-11-24 19:57:25 | 显示全部楼层
楼主你好赞。现在刚刚做到这里
发表于 2021-11-24 20:26:33 | 显示全部楼层
楼主,你好,请问一下代码第26行的文件是什么文件啊,我只有一个数据文件
发表于 2022-8-22 10:45:16 | 显示全部楼层


jade_ysz 发表于 2021-11-24 20:26
楼主,你好,请问一下代码第26行的文件是什么文件啊,我只有一个数据文件 ...


你好,请问一下,你问的这个文件是什么文件
发表于 2022-11-18 21:49:48 | 显示全部楼层
楼主你好,请问spectP_file='spec.csv';这行代码中的文件是从哪来的?是什么文件呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-20 07:42 , Processed in 0.023749 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表