Ted*_*LED 5 c embedded microcontroller assembly avr
我刚刚在采用ASM的Atmel AVR上完成了一个DDS项目,并得出结论,8位查找表和8位DAC在低频时会产生太多的量化失真; 由于缺乏更好的措辞,我在示波器上得到一个带有梯形效果的正弦波.
显然,如果我用大LPF平滑波形,我在高频时会出现振幅问题.
理论上,从8位升级到12位DAC并采用4个最低有效位的插值应该可以让我将滤波器的截止点提高到足够大的数量,以缓解更高频率下波形振幅的问题.我的问题是,我不知道如何做到这一点,或者是否有一种更简单的方法来删除拉链效果..也许12位查找表?
到目前为止,我已经创建了一个无限循环,每次循环完成一个循环时,就会根据与查找表相关的指针位置向DAC发送一个值.这是我感到困惑的地方.我已经阅读了大量关于此的信息,但仍然没有找到一个有效的例子.如果我有一个无限循环,我应该如何在表查找值之间填充插值?关于我能想到的最好的事情是(a + b)/ 2; 我可以实现这个并获得一个额外的位或相当于512点的查找表,但我想认为有一种更简单的方法可以提供更好的结果.我不知道C或如何使用它,但如果它是谨慎的我会试一试.
目前,我的时钟是1MHZ,如果有必要,我可能会达到16MHZ.
以下是我的代码示例:
; 将sinewave输出设置为默认值
ldi ZH, High(sine*2); setup Z pointer hi
ldi ZL, Low(sine*2) ; setup Z pointer lo
Run Code Online (Sandbox Code Playgroud)
; 清除累加器
clr r29 ; clear accumulator
Run Code Online (Sandbox Code Playgroud)
; 设置加法器寄存器
ldi r24,0x50 ; Fine adder value change register
ldi r25,0x08 ; Middle adder value change register
ldi r26,0x00 ; Coarse adder value change register
Run Code Online (Sandbox Code Playgroud)
LOOP1:
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
Run Code Online (Sandbox Code Playgroud)
如果您的 LUT 有 256 个条目,您可以首先使用寄存器 r29(显然从 0 到 255)作为两个连续样本之间的缩放因子。
Output = (LUT[r30] * (256 - r29) + LUT[r30+1] * r29) >> 8;
还有这个线程讨论了许多正弦波生成的实用替代方案。
编辑公式实现教科书线性插值
y = a*(1-t) + b*t, with 0<=t<1
Run Code Online (Sandbox Code Playgroud)
因此当 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]更正确,但在现实生活中没有区别,因为人类听觉系统没有绝对的参考相位。