论坛风格切换切换到宽版
  • 18206阅读
  • 212回复

方波的采样定理和DDS的问题 [复制链接]

上一主题 下一主题
离线小比尔/5
发帖
2582
只看该作者 40楼 发表于: 2008-07-31
还有一个比较:
输出频率变为1001hz时的情况
黄-6位地址线,64样点正弦表
红-7位
绿-8位
蓝-9位,512样点正弦表
可以看到输出质量的变化(采样频率:8khz,1024点fft,矩形窗)
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线一异
发帖
868
只看该作者 41楼 发表于: 2008-08-01
dds累加器的最高位直接作方波输出纯粹是一个馊主意。
除非采样频率是输出频率的整倍数,否则相位抖动是不可避免的——如果是整倍数,直接用分频器分频就可以了,还要什么dds?
这不需要什么频谱分析,直接手工计算一下就清楚了。特别是当输出频率比较接近采样频率的时候,输出绝对是一塌糊涂。

如果一定要用dds输出方波,用经过良好滤波的正弦波做过零比较是唯一可行的方案。
离线mainstreet
发帖
44
只看该作者 42楼 发表于: 2008-08-01
'
我猜测是因为
1.频率低0.1hz
2.波表细1024位
把频率调高到一定程度谐波就会大了
'
0.1这个频率是归一化的。如果采样时钟是10 mhz或归一化的1,这个频率是1 mhz或0.1,奈奎斯特频率是5 mhz或0.5。
离线mainstreet
发帖
44
只看该作者 43楼 发表于: 2008-08-01
'
发现您波表有点儿小问题,2^n应该是2^n-1,否则会出现128这个值,就不是8位了。但这基本上不影响输出啊,不明白为什么信噪比如此高。
我是为了避免matlab的双精度计算而改用c写dds的,这样dds核心是整数运算,相位舍入与实际硬件是一样的,而且我不会用matlab写整数运算,:) :)。
个人感觉8位输出的dds不该有如此高的信噪比,所以估计问题出在相位累加的双精度运算问题上。猜测而已。
'


n=8-1; wave=round(wave*2^n)/2^n;
把正负1之间的浮点数四舍五入成正负128之间的整数,正好8位(?)。

phase3=round(phase2*(2^m-1)+1);
把0-1之间的浮点数四舍五入成1-1024之间的整数,正好10位。

matlab有fixed-point toolbox定点数工具,用来模拟硬件,但是速度会受影响。round四舍五入差不多。
离线mainstreet
发帖
44
只看该作者 44楼 发表于: 2008-08-01
稍微改了一下。我的1024x8波表附上了。
close all;
clear all;

m=10; wave=sin(2*pi*(1:2^m)'/2^m); % 1024-entry wave table
n=8-1; wave=round(wave*2^n); % truncated to 8-b

f0=0.1*exp(1)/2.7; % normalized frequency is 0.1
phase0=rand; % initial phase
k=20; phase1(1:2^k)=phase0+2*pi*f0*(0:2^k-1); % phase
phase2=mod(phase1,2*pi)/2/pi; % phase between 0 and 2*pi
phase3=round(phase2*(2^m-1)+1); % phase as wave table indices

x=wave(phase3); % wave table output
x=x.*hanning(2^k); % windowed
y=fft(x);
y2=abs(y(1:2^k/2)).^2;
y2=y2/max(y2); % normalized
plot((1:2^k/2)/2^k,20*log10(y2));
axis([0 0.5 -150 0]);
title(['fft of dds based on ',num2str(2^m),'x',num2str(n+1),' wave table'])
fhandle=fopen('wave','w');
for i=1:length(wave)
  fprintf(fhandle,'%3i\n',wave(i));
end
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线mainstreet
发帖
44
只看该作者 45楼 发表于: 2008-08-01
几个fft。
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线alchemier
发帖
69
只看该作者 46楼 发表于: 2008-08-01
样表的影响很明显。试试1024×16位的样表呢
离线bd1es
发帖
2096
只看该作者 47楼 发表于: 2008-08-01
[quote=小比尔/5]这是我今天做的:
截断误差比dac的精度误差影响更大
当地址线位数增大后,截断误差引起的杂散频谱f轴上变稀,幅值变小
采样频率与精度也是一对矛盾,需要权衡
若要高频、高速、高质量,只有同时增加采样频率和累加器位数
如果频率不是采样频率的公因子,杂散也会急剧变多
[/quote]

对!这应该是本贴的最高总结了, 。仿真确实是个好东西,可以让我们避开那些繁琐的解析而看到近似的结论,至少在选择dds芯片时心里有些底数了。

也可以武断地下个结论,累加器较差时,比如小于32位,主要的杂散是相位抖动带来的边带扩展。当累加器较精密时,比如48比特,那么波表的质量也必须跟上去了,否则量化噪声影响就很明显了, :d 。

自制dds前也最好先仿真,几年前我从网上抄过一个avr单片机的24位dds,总感觉信号乱糟糟的,现在明白这与累加器的精度有关。在回复楼主的最先几帖中我也没搞懂dds到底有啥问题,现在总算踏实些了。

以后有时间尝试仿真1位dds的“方波”输出经窄带跟踪锁相环倍频后会是啥样,看看到底糟到什么程度。
离线bd1es
发帖
2096
只看该作者 48楼 发表于: 2008-08-01
'
n=8-1; wave=round(wave*2^n)/2^n;
把正负1之间的浮点数四舍五入成正负128之间的整数,正好8位(?)。
phase3=round(phase2*(2^m-1)+1);
把0-1之间的浮点数四舍五入成1-1024之间的整数,正好10位。
matlab有fixed-point toolbox定点数工具,用来模拟硬件,但是速度会受影响。round四舍五入差不多。
'

乘128就不是8位了。128='b01111111+'b00000001='b10000000,冒了,变负数了 。8位2进制的值空间是-128到127,我们在本例中能用的是-127到127。当然做仿真实验没大问题,matlab不会对128另眼看待,而且我们不在乎这点儿误差。可要是写rom的话就不行了,这会发生正弦波的波峰处陡然凹陷,问题就大了,

我还没有仔细看过您程序中的累加器逻辑,今晚如有空我实际转一下试试...
离线小比尔/5
发帖
2582
只看该作者 49楼 发表于: 2008-08-01
BD1ES
关于在160mhz采样频率上出10.7mhz,我的仿真结果与你的大致一样:
图1:采样频率160mhz,输出10.7mhz,累加器32bit,1bit(方波“dds”)
图2:采样频率160mhz,输出10.7mhz,累加器32bit,8bit(1024正弦样点表)

这样的仿真很好玩儿,颇有指点江山的味道,呵呵~
学习了!!!
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线mainstreet
发帖
44
只看该作者 50楼 发表于: 2008-08-02
'
对!这应该是本贴的最高总结了, [表情] 。仿真确实是个好东西,可以让我们避开那些繁琐的解析而看到近似的结论,至少在选择dds芯片时心里有些底数了。
也可以武断地下个结论,累加器较差时,比如小于32位,主要的杂散是相位抖动带来的边带扩展。当累加器较精密时,比如48比特,那么波表的质量也必须跟上去了,否则量化噪声影响就很明显了, :d 。
自制dds前也最好先仿真,几年前我从网上抄过一个avr单片机的24位dds,总感觉信号乱糟糟的,现在明白这与累加器的精度有关。在回复楼主的最先几帖中我也没搞懂dds到底有啥问题,现在总算踏实些了。
以后有时间尝试仿真1位dds的“方波”输出经窄带跟踪锁相环倍频后会是啥样,看看到底糟到什么程度。 [表情]
'

可以这么估计。

x=sin(phase)

phase的“量化噪声”的最大值是2*pi/2^m/2,大约是1/2^(m-4)。在零点附近,它的影响最大,一比一出现在x里。x的量化噪声受dac限制,最大值是2/2^(n-1)/2=1/2^(n-1)。

如果想让dac不成为瓶颈,m-3>n。

1024x16的波表浪费dac的性能,1024x7/8就是极限了。
离线mainstreet
发帖
44
只看该作者 51楼 发表于: 2008-08-02
fdsgdhhjy uytuytutyuytu
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线alchemier
发帖
69
只看该作者 52楼 发表于: 2008-08-02
'
fdsgdhhjy uytuytutyuytu
'

谢谢!看来我也得再学学matlab了,对于设想的验证真方便。
离线alchemier
发帖
69
只看该作者 53楼 发表于: 2008-08-02
'
对!这应该是本贴的最高总结了, [表情] 。仿真确实是个好东西,可以让我们避开那些繁琐的解析而看到近似的结论,至少在选择dds芯片时心里有些底数了。
也可以武断地下个结论,累加器较差时,比如小于32位,主要的杂散是相位抖动带来的边带扩展。当累加器较精密时,比如48比特,那么波表的质量也必须跟上去了,否则量化噪声影响就很明显了, :d 。
自制dds前也最好先仿真,几年前我从网上抄过一个avr单片机的24位dds,总感觉信号乱糟糟的,现在明白这与累加器的精度有关。在回复楼主的最先几帖中我也没搞懂dds到底有啥问题,现在总算踏实些了。
'

这也是我在小比尔的帖子里说的对于24位累加器要用16.8m样表的初衷,因为不论累加器有多精密,最终都会被样表截断,产生相位抖动。
当然这是理论上的设想,对于业余条件可能会觉得没有必要,但是可以仿真看一下结果,matlab是个好东西啊。
离线小比尔/5
发帖
2582
只看该作者 54楼 发表于: 2008-08-02
'
这也是我在小比尔的帖子里说的对于24位累加器要用16.8m样表的初衷,因为不论累加器有多精密,最终都会被样表截断,产生相位抖动。
当然这是理论上的设想,对于业余条件可能会觉得没有必要,但是可以仿真看一下结果,matlab是个好东西啊。
'

但问题是,样表精确到一定程度,dac就无法表达了。
16.8m的样表终究太大了,无论从成本还是复杂程度都是没必要的。
如果能实现16.8m的样表,还不如直接用级数进行实时的近似运算。

在这个系统里,幅度和相位是可以相互转换的。

请看上面同学的推论。
离线mainstreet
发帖
44
只看该作者 55楼 发表于: 2008-08-02
16.8m=2^27

这要配合大概30位的dac。
离线小比尔/5
发帖
2582
只看该作者 56楼 发表于: 2008-08-02
'
16.8m=2^27
这要配合大概30位的dac。
'

24位的dac就已经很难做了~不是说做不到,而是外围元件的误差已经比分辨率大了。
音频一般才用到16位,视频只有10位(hdtv),8位(sdtv)。
而且16位和24位很多是通过1bit sigma-delta来实现的,速度上不去。

30位的dac一般是没有必要的,16位的s/n就已经可以做到90db以上了。

我曾经试图用12位的dac出dds,结果12位的dac非常贵,新品能工作在1mhz的至少得35元,索性后来买了片二手的ad7541,还不错,7块钱。所以,如果没有特别要求,这个时候dds专用芯片的性价比就比分立的高了。

仿真的结果是:12位dac配合2^12=4096正弦表与配合2^16=65536正弦表,在1/4fs内的频谱未见明显的改善效果,但存储量却增大了60kb。

比较实用的方法是:过采样(但要注意权衡过采样与精度的关系),并且可以在dac的幅度上进行一定的抖动(噪声整形),在输出的时候用低通滤波器把不要的频带滤掉。
离线mainstreet
发帖
44
只看该作者 57楼 发表于: 2008-08-02
[quote=小比尔/5]
并且可以在dac的幅度上进行一定的抖动(噪声整形)[/quote]

这是从电压轴来看。还可以从时间轴来看。如果输出16 khz的正弦波,时钟的抖动要在ns级,否则16m长的波表也浪费了。

那天我就想到了用dither抖动的办法把谐波转化成噪声改善频谱,但是我觉得在波表的时间轴和电压轴上在外部做不到。在dac内部是可能的。

你是用什么办法实现的?
离线一异
发帖
868
只看该作者 58楼 发表于: 2008-08-02
'
对!这应该是本贴的最高总结了, [表情] 。仿真确实是个好东西,可以让我们避开那些繁琐的解析而看到近似的结论,至少在选择dds芯片时心里有些底数了。
也可以武断地下个结论,累加器较差时,比如小于32位,主要的杂散是相位抖动带来的边带扩展。当累加器较精密时,比如48比特,那么波表的质量也必须跟上去了,否则量化噪声影响就很明显了, :d 。
自制dds前也最好先仿真,几年前我从网上抄过一个avr单片机的24位dds,总感觉信号乱糟糟的,现在明白这与累加器的精度有关。在回复楼主的最先几帖中我也没搞懂dds到底有啥问题,现在总算踏实些了。
以后有时间尝试仿真1位dds的“方波”输出经窄带跟踪锁相环倍频后会是啥样,看看到底糟到什么程度。 [表情]
'

这个结论不正确!
相位累加器的字长与相位抖动无关,相位累加器的字长只决定相位的步长,换句话说之决定频率分辨率。
用单片机实现dds相位抖动大的主要原因应当是单片机的响应时间造成的。
如果外接dac,可以在dac与单片机之间增加一个多位d触发器来保证相位抖动指标。这样做的话,就不能用单片机的定时中断了,必须用驱动d触发器的时钟移相向后用来做外部中断……
如果不用外部dac,也可以考虑用采样保持电路或者脉冲成型电路。总之要保证采样时钟的稳定。
离线bd1es
发帖
2096
只看该作者 59楼 发表于: 2008-08-02
'
fdsgdhhjy uytuytutyuytu
'

hi mainstreet,俺试着运行了您的程序,发现如下问题
1、波表的位宽超限,已改成2^n-1;
2、fft的功率计算有误。既然前面已对电压平方了,后面就db计算应该是10*log10(),也改了;
3、相位累加部分没看懂,请问如何表示一个16位累加器,又如何表示一个32位累加器呢?否则相位的舍入就不能评估了。是否可介绍一下您程序的设计原理。

下面是俺修改的程序,运行效果与小比尔/5和我的c程序类似了。但还是不知道这个dds是多少位累加器的,我感觉这里还有错误。 ,运行结果见附图:

function mainstreet_case_modis
close all;
clear all;

m=10; wave=sin(2*pi*(1:2^m)'/2^m); % 1024-entry wave table
n=8-1; wave=round(wave*(2^n-1)); % truncated to 8-b

f0=0.1*exp(1)/2.7; % normalized frequency is 0.1
phase0=rand; % initial phase
k=16; phase1(1:2^k)=phase0+2*pi*f0*(0:2^k-1); % phase
phase2=mod(phase1,2*pi)/2/pi; % phase between 0 and 2*pi
phase3=round(phase2*(2^m-1)+1); % phase as wave table indices

x=wave(phase3); % wave table output
x=x.*hanning(2^k); % windowed
y=fft(x);
y2=abs(y(1:2^k/2)).^2;
y2=y2/max(y2); % normalized
plot((1:2^k/2)/2^k,10*log10(y2));
axis([0 0.5 -100 0]);
title(['fft of dds based on ',num2str(2^m),'x',num2str(n+1),' wave table'])
fhandle=fopen('wave','w');
for i=1:length(wave)
fprintf(fhandle,'%3i\n',wave(i));
end
本主题包含附件,请 登录 后查看, 或者 注册 成为会员