一、目的:
在multisim环境下,参考图5-3-1,设计一种基于DDFS的正弦信号源,给出原理图和仿真实验结果。
二、DDFS原理:
DDFS-Direct Digital Frequency Synthesizer 直接数字频率合成。在时钟脉冲的控制下,相位累加器输出线性递增的相位吗,相位吗作为地址信息来寻址波形寄存器,讲波形寄存器中存放的正弦波形样点数据输出,然后经过模数变换器得到对应的阶梯波形,最后经过低通滤波器对解题波进行平滑,得到正弦波形。波形储存器中也可以存放其他波形,实现任意波形产生的功能。频率控制字K在时钟的控制下控制每次相位累加器累计的相位增量,从而实现对输出信号频率的控制。由于相位累加器是Nbit的模2加法器,正弦查找表中存储0~2Π区间内一个周期的正弦波幅度量化数控,所以频率控制字是K时,每2的N次幂个时钟周期输出一个周期的正弦波, ,这是DDFS系统最基本的公式之一。
三、题目分析及方案确定:
由于不知道multisim是否有可记忆的芯片,所以采用51单片机来进行仿真,每次中断单片机p0口输出一个正弦表的数值,经过数模转换后变成模拟电压,一个周期内输出126个电平组成正弦波,低通滤波后使之平滑,再外接一个运放来调节偏置电压使之成为标准正弦波,用外部按键控制中断的时间大小间隔就可以达到输出不同频率的正弦波的目的
C语言的正弦查找表用一数组表示
sin1[126]={ 126,133,139,145,151,158,164,170,175,181,187,192,197,203,207,212,217,221,225,229,232,236,239,241,244,246,248,249,251,251,252,252,252,252,251,251,249,248,246,244,241,239,236,232,229,225,221,217,212,207,203,197,192,187,181,175,170,164,158,151,145,139,133,127,120,114,108,102,95,89,83,78,72,66,61,56,50,46,41,36,32,28,24,21,17,14,12,9,7,5,4,2,2,1,1,1,1,2,2,4,5,7,9,12,14,17,21,24,28,32,36,41,46,50,56,61,66,72,78,83,89,95,102,108,114,120 };
四、单片机算法流程分析:
keil调试运行
五、仿真分析
1、总体电路仿真图:
频率调节电路+单片机数字量输出电路+数模转换电路+滤波电路+偏置电压调节电路
2、单片机输出数字量及数模转换电路:
单片机输出数字量经过数模转换后的波形,可见每一个输出电平都有阶跃现象产生,电平的切换时输出电压不稳定
3、滤波电路
500pF电容加1k欧姆电阻:
低通滤波后的波形,可见,电平之间的切换已经没有了阶跃现象,而且波形更加平滑了,但是还是有直流偏置电压存在。
4、运放调节偏置电压电路:
R8为偏压调节电阻
可见,经过LM324运放调节偏压后,输出波形为标准正弦波
5、频率调节电路:
频率调节输出波形:
输出频率为1/906.516us=1103Hz
输出频率为:1/191.238us=5229.1Hz
六、附:单片机c语言程序
#include "reg51.h"
#define uchar unsigned char
#define uint unsigned int
sbit key1 = P2^0;
sbit key2 = P2^1;
uchar TIMER_H;//给计数器的值
uchar TIMER_L;
int i = 0;
int Fre = 1000;
uchar CurStal = 1;
uchar code sin1[126] = { 126,133,139,145,151,158,164,170,175,181,187,192,197,203,207,212,217,221,225,229,
232,236,239,241,244,246,248,249,251,251,252,252,252,252,251,251,249,248,246,244,
241,239,236,232,229,225,221,217,212,207,203,197,192,187,181,175,170,164,158,151,
145,139,133,127,120,114,108,102,95,89,83,78,72,66,61,56,50,46,41,36,32,28,24,21,
17,14,12,9,7,5,4,2,2,1,1,1,1,2,2,4,5,7,9,12,14,17,21,24,28,32,36,41,46,50,56,61,
66,72,78,83,89,95,102,108,114,120 };
void keyscanf() //按键扫描
{
uint temp;
if(key1 == 0)
{
if((Fre + 100) <= 10000)
{
Fre = Fre +100;
temp = (unsigned long)504000000 / 126/ Fre;
TIMER_H = (65535 - temp) / 256;
TIMER_L = (65535 - temp) % 256;
}
while(!key1);
}
if(key2 == 0)
{
if((Fre - 100) >= 0)
{
Fre = Fre - 100;
temp = (unsigned long)504000000/126/ Fre;
TIMER_H = (65535 - temp) / 256;
TIMER_L = (65535 - temp) % 256;
}
while(!key2);
}
}
void init_time()
{
EA = 1; //开中断
ET0 = 1;
TMOD = 0X01; //初始化
TR0 = 1; //开定时器
}
void time0() interrupt 1
{
TH0 = TIMER_H;
TL0 = TIMER_L;
P0=sin1[i];
i++;
if(i==125)
{
i=0;
}
}
void main()
{
uint temp;
init_time(); //定时器初始化调用
temp = (unsigned long)504000000 /126/Fre;
TIMER_H = (65535 - temp) / 256;
TIMER_L = (65535 - temp) % 256;
while(1)
{
keyscanf(); //按键一直扫描
}
}