c - DDS 插值 - 8 位 Atmel AVR ASM 到 12 位 DAC

标签 c assembly embedded microcontroller avr

我刚刚在采用 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)作为两个连续样本之间的比例因子。

输出 = (LUT[r30] * (256 - r29) + LUT[r30+1] * r29) >> 8;

Also this thread讨论了正弦波生成的许多实用替代方案。

EDIT 公式实现课本线性插值

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 中的量化误差。

enter image description here

插值总是相对于 LUT 中的整数索引发生,无论是否有许多样本落在同一范围内,例如。查找表2和查找表 [3]。数学上 Lut[R]、LUT[R+1] 比 [R-1]、[R] 更正确,但在现实生活中没有区别,因为人类的听觉系统没有绝对的引用相位。

关于c - DDS 插值 - 8 位 Atmel AVR ASM 到 12 位 DAC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13558090/

相关文章:

c - 为指向 C 中记录的指针中的键赋值

c - win api - 如何为 TreeView 实现单独的事件过程

php - 如何将汇编代码嵌入到php中?

assembly - GAS 是否像 NASM 那样支持字符串文字作为数字常量?

linux - Linux 内核 3.4.103 上的 iptables --to-port

c - 嵌入式系统 Linux 中 RAM 使用率最低的情况

C 编程打开和读取文件

c - 为什么stm32上的程序只能调试才能运行?

ubuntu - 汇编通过堆栈传递变量

c++ - 几次访问后,mmap 因无法打开/dev/mem 而死