基于数字频率合成技术的正弦波发生器设计

        数字频率合成算法又称为DDS算法,实际上就是信号采样过程的一个逆用。当我们进行信号采样时,会使用一个大于信号频率2倍以上的采样频率去采点,把这个点存储在存储器中,称为波形ROM表。而DDS恰好相反,它是先把波形ROM表制作好,然后以等于采样频率的输出频率输出电压。由于在采样时,原始信号是经过了一个零阶保持器,然后被量化存储到存储器的;所以在输出电压时,也相应的加一个滤波器,把阶梯波滤除,来恢复原信号。

        在这样的思想指导下,只要平台具有定时输出不同电压的功能,都能设计波形发生器。我们本次主要采用最简单的STC89C52和一片DAC芯片实现该设计。使用Keil5来编写代码,proteus 8来进行仿真。效果如下图所示,系统输出了100Hz的正弦信号。

  

         硬件设计:

        首先要选择一个DAC芯片。我们可以选用PCF8591,因为它是使用IIC协议通信,所以只占据2个引脚。但我们将在原理图中使用两片DAC芯片。一片DAC芯片用来发出正弦波,另一片DAC用来改变波形输出的幅度。由于DAC能输出的电压范围在AGND~Vref之间,我们可以把一个DAC的输出Vdac1_out,接到另一片DAC的Vref,然后改变Vdac1_out来实现幅度控制。其中AGND接地,为0V。

        有些同学此刻会问了,不是说输送到DAC的数字量能改变输出电压的大小吗?我们把整个波形ROM表的数据乘以一个系数,就能控制输出幅度了,何必用两片DAC呢?这里要注意,虽然数字量乘以一个系数可以改变电压大小,但输出波形的分辨率就降低了。也就是说,原本0~255可以将输出电压分割成256个等级。但如果将数字量乘以0.5,则只能以0~127来分割电压,这个衡量不同电压的“尺子”变得更粗糙以后,输出的波形失真度会加大。极端的,如果把数字量乘以1/255,那么在输出端只能看到输出0V和0.02V两种电压,根本无法表示一个正弦信号。

        软件设计:

        测得PCF8591输出一个电压的时间是1ms。这意味着输出电压最大的频率是Fdac_max = 1000Hz。为了预留一些余量,就设置输出频率为Fdac=512Hz好了。此时这个Fdac相当于信号采样过程的采样频率。根据采样定理,采样频率必须大于或等于信号频率的2倍。所以理论上,这个系统可以输出256Hz的正弦波。但是为了减小设计难度,取最高输出频率100Hz。相当于在正弦波的一个周期内,至少有5个点。

        由于PCF8591是8bit的DAC,所以最大有256个电压等级。我们可定义一个长度为256点的波形ROM表,如下定义的数组。这个表存储的是一个周期正弦波的电压数字量。

//ROM点数:256 虚拟表长:512 中断频率:512Hz 中断时间:1.95ms 最高正弦输出频率:512/5 = 102.4
code unsigned char Wave_ROM_Sine[WAVE_ROM_SIZE] = 
{
        128,131,134,137,140,143,146,149,152,155,
        158,162,165,167,170,173,176,179,182,185,
        188,190,193,196,198,201,203,206,208,211,
        213,215,218,220,222,224,226,228,230,232,
        234,235,237,238,240,241,243,244,245,246,
        248,249,250,250,251,252,253,253,254,254,
        254,255,255,255,255,255,255,255,254,254,
        254,253,253,252,251,250,250,249,248,246,
        245,244,243,241,240,238,237,235,234,232,
        230,228,226,224,222,220,218,215,213,211,
        208,206,203,201,198,196,193,190,188,185,
        182,179,176,173,170,167,165,162,158,155,
        152,149,146,143,140,137,134,131,128,124,
        121,118,115,112,109,106,103,100,97,93,
        90,88,85,82,79,76,73,70,67,65,
        62,59,57,54,52,49,47,44,42,40,
        37,35,33,31,29,27,25,23,21,20,
        18,17,15,14,12,11,10,9, 7, 6,
        5, 5, 4, 3, 2, 2, 1, 1, 1, 0,
        0, 0, 0, 0, 0, 0, 1, 1, 1, 2,
        2, 3, 4, 5, 5, 6, 7, 9, 10,11,
        12,14,15,17,18,20,21,23,25,27,
        29,31,33,35,37,40,42,44,47,49,
        52,54,57,59,62,65,67,70,73,76,
        79,82,85,88,90,93,97,100,103,106,
        109,112,115,118,121,124

};

        中断频率是512Hz,表的长度只有256,如果要输出1Hz的正弦波怎么办?只能做一个虚拟表长度RomLen = 512。实际上,对ROM寻址时是把数组索引先除以二再进行寻址的。所以当输出1Hz正弦波时,包含的阶梯波实际上是256Hz的阶梯信号。

        ROM表只存储了一个周期的波形,那如何实现持续输出多个周期?这个其实就是循环寻址,不必赘述。中断服务函数的关键代码如下:

  ......

    wave_dds.data_index += wave_dds.freq;
    if(wave_dds.data_index >= wave_dds.rom_len)
    {
        wave_dds.data_index-= wave_dds.rom_len;
    }
    
    if(wave_dds.wave == sin)
    {
        wave_dds.Rom_data = Wave_ROM_Sine[wave_dds.data_index>>1];
    }

    pcf8591_set_dac_value(PCF8591_SLAVE_ADDRESS_0,wave_dds.Rom_data);        

......

        根据以上设计,输出正弦波最高频率为100Hz,夹杂的阶梯波最低频率为256Hz。那么可以设计一个截止频率为100Hz的低通滤波器,恢复原信号。

        该波形发生器可以输出正弦,那如何输出三角波、锯齿波?其实只需要再多定义几个ROM表即可。但是注意,通过正弦ROM输出的信号经过低通滤波器,可以得到较好的波形;但是如果是三角波,却不适合经过低通滤波器。三角波本身就存在很多高频分量,故它不太适合使用低通滤波器。

        所有的源代码和仿真文件:

        

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值