我刚刚在使用ASM的Atmel AVR上完成了一个DDS项目,得出的结论是8位查找表和8位DAC在低频时会产生过多的量化失真;由于缺乏更好的措辞,我在示波器上遇到了带有梯形效果的正弦波。
显然,如果我用较大的LPF平滑波形,则在较高频率下会有振幅问题。
从理论上讲,从8位DAC升级到12位DAC,并使用4个最低有效位进行插值,应使我能够将滤波器的截止点提高到足够高的水平,以缓解较高频率下的波形幅度问题。我的问题是我不知道如何执行此操作,或者是否有更简单的方法来消除 zipper 效果。也许是12位查找表?
到目前为止,我已经创建了一个无限循环,每次循环完成一个循环时,都会根据与查找表相关的指针的位置将一个值发送到DAC。这就是我感到困惑的地方。我已经阅读了大量有关此方面的信息,但仍然没有找到一个可行的示例。如果我有一个无限循环,应该如何在表查找值之间填充内插值?我能想到的最好的事情是(a + b)/2;我可能可以实现这一点,并获得额外的收入或等同于512点的查询表,但是我想认为有一种更简单的方法或可能带来更好结果的方法。我不知道C或如何使用它,但是如果谨慎的话我会尝试一下。
目前,我的时钟为1MHZ,如有必要,我可能会达到16MHZ。
这是我的代码示例:
;将正弦波输出设置为默认值
ldi ZH, High(sine*2); setup Z pointer hi
ldi ZL, Low(sine*2) ; setup Z pointer lo
;清除累加器
clr r29 ; clear accumulator
;设置加法器寄存器
ldi r24,0x50 ; Fine adder value change register
ldi r25,0x08 ; Middle adder value change register
ldi r26,0x00 ; Coarse adder value change register
循环1:
add r28,r24 ; 1 Adder values carry over to higher registers. Higher registers raise freq. in larger steps
adc r29,r25 ; 1
adc r30,r26 ; 1 r30 is database address pointer for Z register
lpm r0, Z ; 3 (Load Program Memory) Reads byte from database into the destination register based on Z pointer
out PORTD,r0
rjmp LOOP1 ; 2 => 9 cycles
最佳答案
如果您的LUT有256个条目,则可以首先使用寄存器r29(显然从0到255)作为两个连续采样之间的比例因子。Output = (LUT[r30] * (256 - r29) + LUT[r30+1] * r29) >> 8;
Also this thread讨论了正弦波生成的许多实用替代方法。
编辑该公式实现教科书线性插值
y = a*(1-t) + b*t, with 0<=t<1
因此,当t = 0时y = a,而当t = 1时y = b。移位8表示在相乘后将内插项t除以256。在表达式LUT [r30 + 1]中,我假设一个隐式256模运算,因为r30是8位(不是吗?)。
LUT扩展到12位必须单独完成,因为除以4只会增加LUT中的量化误差。
插值总是相对于LUT中的整数索引发生,而不管是否许多样本落在相同范围内,例如。 LUT 2和LUT [3]。从数学上讲,Lut [R],LUT [R + 1]比[R-1],[R]更正确,但在现实生活中没有区别,因为人类听觉系统没有绝对的引用相位。
关于c - DDS插值-8位Atmel AVR ASM至12位DAC,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13558090/