基于DDS芯片AD9833的音源发生器设计
在 2008年浙江省大学生电子设计竞赛中,有一个题目是“音乐演奏器设计”,要求用12个键盘演奏音乐,其中有一个关于音阶的技术指标要求频率误差小于±0.1%。本题目的关键在于产生一个高精度的音源。一般采用的单片机定时器中断产生信号的方法勉强能达到这个要求。本题目有一个音阶对应频率的附表,描述了各音阶对应频率的精确值,如音阶6频率为739.99 Hz,采用51系列单片机定时器中断方法无法达到该表数据所描述频率精度要求。而采用DDS技术,则能达到这一频率精度的要求。与采用51单片机定时器产生的信号相比,通过DDS产生的音阶信号除了频率精度高的优点外,产生的是正弦波,具有“纯”音的特点,听觉效果较好。基于上述原因,采用DDS+MCU 是实现音乐演奏器的一种较好设计方案。其技术核心为可控的音阶的发生,构成一个音源发生器。本文介绍的音源发生器可用于钢琴的校音,具有一定实用价值。
1 音源产生原理
TIerney J和Tader C M等人于1971年首次提出了DDS或DDFS(Direct Digital Frequency Synthesis)的概念,通常将DDS视为第三代频率合成技术。DDS突破了以往频率合成法的原理,从“相位”的概念出发进行频率合成。这种方法不仅可以产生不同频率的正弦波,而且可以控制波形的初始相位。另外,可以采用DDS方法产生任意波形(AWG)。
DDS的基本结构如图1所示,包括主频、同步加法器、频率字寄存器、ROM、D/A、LPF等。主频产生主时钟,同步加法器按照主时钟进行同步加法运算。同步加法器的一个加数是存储于频率字寄存器中的频率字,另一个加数是同步加法器的上次加法运算结果(和)。同步加法器的加法运算结果(和)作为ROM的地址,ROM内存储有波形数据,ROM的数据输出由D/A转换成模拟量,经过LPF滤波,输出ROM内存储的波形。
基本的DDS芯片,主频fMCLK=1 MHz,频率字FREQREG=1,同步加法器的位数为8,则同步加法器相当于进行0~255(0x00~0xFF)的计数过程,该过程循环重复,其循环频率为fMCLK/256。若ROM存储有正弦波数据,则经过D/A转换和LPF滤波后,输出频率为fMCLK/256的正弦波信号;当频率字FREQREG=2,则同步加法器相当于进行步长为2的0~255(0x00~0xFF)的累加过程,该过程的频率为2×fMCLK/256,也就是输出频率为2×fMCLK/256的正弦波信号。
由此类推,基本型DDS芯片的输出频率为:
f0=fMCLK/28×FREQREG
对于基本型DDS芯片,一般,主频fMCLK通过晶体振荡电路产生,相对固定,因此DDS的输出频率取决于频率字,频率字一般通过串行或并行接口进行设置。
DDS芯片的输出频率的变化间隔(分辨率)为fMCLK/28(当同步加法器的位数是8时)。输出频率的稳定度主要取决于晶体振荡的稳定度,输出波形则取决于ROM中的波形数据,根据奈奎斯特定理,最高输出频率小于fMCLK/2。
由于同步加法器结果是改变输出波形的相位,在有关DDS芯片的资料中[1],该同步加法器通常称为相位累加器。
实际应用时,DDS的结构会复杂得多,同步加法器的位数远大于8,加入相位加法器,ROM、D/A数据宽度在10位以上,主频也会较高。因此通常采用专用芯片,也有少量采用FPGA来实现的(特别当需要实现AWG时)。
Qualcomm公司、ADI公司等推出一系列DDS专用芯片。比较典型的有AD9850、AD9851、AD9852、AD9853、AD9833等。当前的信号发生器广泛使用DDS专用芯片作为电路核心[1]。历年的大学生电子竞赛均有涉及DDS芯片应用的题目。
AD9833是ADI公司生产的一款低功耗、可编程波形发生器,能够产生正弦波、三角波、方波输出,输出频率和相位都可通过软件编程,调节比较方便。采用 28位的频率寄存器,当主频时钟为25 MHz时,频率分辨率为0.1 Hz;主频时钟为1 MHz时,频率分辨率可以达到0.004 Hz[2]。
AD9833采用10个引脚的MSOP封装形式,采用SPI接口进行控制寄存器和频率寄存器的设置,功能简洁,使用方便,故选用AD9833芯片作为音阶频率发生器。AD9833芯片的引脚图如图2所示。
在主频合适的条件下,通过SPI接口设置频率寄存器和控制寄存器,即能得到理想的信号输出。其输出频率为:
2 硬件设计
AD9833芯片有3根串行接口线,与SPI、QSPI、MI-CROWIRE和DSP接口标准兼容,在串口时钟SCLK的作用下,数据以16位的方式加载到设备上,其时序图如图3所示,FSYNC引脚是使能引脚,电平触发方式,低电平有效。进行串行数据传输时,FSYNC引脚必须置低。
本设计中,MCU采用51系列芯片,图4是音源器部分的电路原理图。P1.5、P1.6、P1.7分别与AD9833芯片的FSYN、SCLK、SDA相连,MCU通过模拟SPI的时序,对AD9833芯片的各寄存器进行设置。Y2是一个有源晶振,其第3脚输出频率为4.194 304 MHz的信号,提供给AD9833芯片的主频输入端,AD9833芯片产生的信号通过JP3输出,与音频功放电路相连,通过音频功放驱动扬声器发声。
3 软件实现
本设计中,主频时钟采用4.194 304 MHz。输出频率计算如下:
式中,f0为输出频率,fMCLK为主频(4.194 304 MHz),FREQREG为频率寄存器设置的频率字。频率分辨率为1/64=0.015 625 Hz。
根据上述公式,计算出各音阶对应的频率字参数如表1所示。
控制程序在Keil uv2环境下开发,程序采用汇编语言和C语言混合编程形式实现。实现时序控制部分采用汇编语言,主体部分则采用C语言进行编程。程序主体部分调用时序控制部分时,通过全局字节变量light_o和light_o1传递数据。
时序控制部分程序通过模拟SPI接口时序,完成对DDS芯片内部寄存器的设置,具体程序如下(定义部分略):
to_9833:
setb SCK
clr CS
mov a,light_o
mov r1,#08h
call out_SPI
mov a,light_o1
mov r1,#08h
call out_SPI
setb CS
clr SCK
ret
out_SPI:
RLC A
mov SO,c
clrSCK
setb SCK
djnz r1,out_SPI
ret
程序主体部分中,根据表1将音阶数据定义成一个一维数组:
code unsigned int music_table[ ]={0x5268,0x5c80,
0x67d3,0x6e00,0x7b78,0x8a97,0x92d5,0xa4d5,0xb8ff,0xcfa7,0xdc00,0xf6f0,};
主程序的编程框图如图5所示。对AD9833芯片通过写入控制字的方式进行初始化。程序在主循环中运行。主循环对有效按键进行处理,对于有效琴键,调用音阶函数即可。音阶函数如下:
void play_music(unsigned char nn)
{
light_o = 0x20;
light_o1 = 0x00; //设控制字
to_9833();
v_3.cm_int =music_table[nn]; //查音阶表
light_o = 0x40 | (v_3.cm.cm_0 & 0x3f);
light_o1 = v_3.cm.cm_1;
to_9833(); //设频率字
light_o = 0x40;
light_o1 = v_3.cm.cm_0 / 0x40;
to_9833();
}
如有音阶2的琴键被按下有效,C语言对调用函数描述为:
play_music(2);
程序中还包含按键处理、显示、存储控制等部分,限于篇幅,不再赘述。经实测,本音源发生器产生的各音阶频率与表1设计值一致,频率误差<0.02%,波形则是“纯净”的正弦波。通过功率放大,驱动扬声器发声。
通常不同乐器发音时,均有不同特征的谐波。常规乐器难以实现只有主音、无谐波成分的音阶,而通过本文DDS芯片设计的音源器,实现了精准的无谐波成分的音阶,有独特的听觉效果。可作为基准音阶,用于各类乐器的校音。