我刚刚在使用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/

10-11 18:37