我正在使用C / C ++中的Arduino Due开发直接数字合成(DDS)波形发生器。但我首先在Matlab中实现一个例子,以确保我理解主要组件,包括:相位或角度累加器(N位),查找表(P位)和数模转换器(12位)。我理解这些基本要素。
查找表大小将与DAC分辨率匹配,因此P = 12。累加器至少为16位(N = 16)。因此必须在此处进行相位截断。这就是我的困惑和我的问题。截断如何工作?取N的P有效位是什么意思?
答案 0 :(得分:1)
一般情况下,如果你有 N位长值,一个可能的值,比如说(二进制,即用2位表示(1' s和0' s),其中每个位,取决于其位置代表2的幂是:
1000 1111 0000 1010
最重要的位是从左到右计数的位,即:示例中的四个最重要的位是:1000。因此,通过取P有效位进行截断意味着从左到右计数直到P并且忽略左边的内容。
在十进制表示中,即使用10个数字(0,1,..,8,9)表示,这类似于:如果你的值是:110124并且你只取P = 3个有效数字,你将保持:110000,即,不考虑3个最低有效数字(124),从而失去一些细节。
答案 1 :(得分:1)
这个二进制数学和按位操作对我来说是新的,但我开始明白了。我在Matlab中实现了直接数字合成(DDS)示例。其他人的代码如下。也可以在Octave上运行。
% INPUT PARAMETERS
%-----------------------
fs = 2^14; % Clock Sample Rate (hz)
NT = 1e4; % Total Samples for example
foutd = 80; % Desired Output Freq. (hz)
N = 16; % Accumulator resolution (bits)
P = 12; % Lookup Table resolution (bits)
% FREQUENCY TUNING WORD
%------------------------------
FTWf = foutd/fs*2^N; % float
FTW = round(foutd/fs*2^N); % actual integer term for accumulator
fout = FTW*fs/2^N; % actual output frequency
% SINE WAVE LOOKUP TABLE
%---------------------------
x = [0:2^P-1]';
y = sin(x*2*pi / (2^P-1) );
% INITIALIZE
%--------------------------
dt = 1/fs; % Time Step (sec)
t = [0:dt:dt*(NT-1)]'; % Time Vector
phase = zeros(NT,1); % Save phase vs. time
wave = zeros(NT,1); % Save wave amplitude vs. time
% SAMPLE THROUGH TIME
%-----------------------
pa = 0; % Phase accumulator
for ii=1:length(t)
% ACCUMULATE PHASE
pa = pa + FTW;
% ROLLOVER PHASE
if pa > 2^N
pa = 1;
end
% PHASE TRUNCATION
indx = ceil(pa * 2^(P-N));
% LOOKUP
phase(ii) = pa;
wave(ii) = y( indx );
end
figure;
subplot(211), plot(t, phase); grid on;
subplot(212), plot(t, wave); grid on; hold on
plot(t,sin(foutd*2*pi*t), 'r-.');
我的下一步是在ArduinoDue上实现这一点。该算法将成为ISR中断功能的基础。我肯定会使用二元运算符来加速除法(即“相位截断”)。
之后,我需要弄清楚如何处理非整数频率输入。