直接数字合成器DDS设计.docx
《直接数字合成器DDS设计.docx》由会员分享,可在线阅读,更多相关《直接数字合成器DDS设计.docx(17页珍藏版)》请在冰点文库上搜索。
直接数字合成器DDS设计
直接数字合成器(DDS)设计
----基于PIC单片机
学院:
班级:
学号:
姓名:
导师:
日期:
电子系统CAD课程设计任务书
一.设计题目
直接数字合成器(DDS)设计
二.总则
1.本课程设计可采用ARM/DSP/FPGA/PIC/51之一来实现题目中所规定的系统设计,完成软硬件设计。
若自行出题目者,必须经过审核。
2.课程设计为1人一组。
3.在19-20周完成并提交设计,通过演示和非抄袭确认后所取得的成绩为有效成绩。
4.设计过程中严禁抄袭,否则将根据情节扣减成绩直至取消成绩。
5.设计调试在分别在各个实验室进行,时间为19-20周周一至周五。
三.设计内容及要求
1.输出波形要求:
1).在输入时钟频率为16KHz时,输出正弦波分辨率达到1Hz;
2).在输入时钟频率为4MHz时,输出正弦波分辨率达到256Hz;
2.通过RS232C通信,实现和PC机之间串行通信,从而实现用PC机改变频率控制字,实现对输出正弦波频率的控制。
四.设计报告要求
1.画出整个系统的原理图
2.编写程序;
3.叙述各功能模块得工作原理;
4.报告中应附上仿真波形图;
5.书写报告时注意结构合理,层次分明,在分析时注意语言的流畅。
目录:
1、设计题目…………………………………………4
2、设计内容及要求…………………………………4
3、DDS电路的工作原理……………………………4
3.1.相位累加器原理…………………………………4
3.2.基于PIC的DDS实现……………………………6
4、软件设计…………………………………………7
5、测试结果…………………………………………13
6、实验心得…………………………………………14
一、设计题目:
直接数字合成器(DDS)设计
2、设计内容及要求:
1.输出波形要求:
1).在输入时钟频率为16KHz时,输出正弦波分辨率达到1Hz;
2).在输入时钟频率为4MHz时,输出正弦波分辨率达到256Hz;
2.通过RS232C通信,实现和PC机之间串行通信,从而实现用PC机改变频率控制字,实现对输出正弦波频率的控制。
三.DDS电路的工作原理
3.1.相位累加器原理
DDS电路的工作原理如图1所示:
其工作过程为:
①将存于数表中的数字波形,经数模转换器D/A,形成模拟量波形。
②两种方法可以改变输出信号的频率:
1)改变查表寻址的时钟CLOCK的频率,可以改变输出波形的频率。
2)改变寻址的步长来改变输出信号的频率,DDS即采用此法。
步长即为对数字波形查表的相位增量,由累加器对相位增量进行累加,累加器的值作为查表地址。
③D/A输出的阶梯形波形,经低通(或带通)滤波,成为质量符合需要的模拟波形。
该DDS系统的核心是相位累加器,它由一个加法器和一个位相位寄存器组成,每来一个时钟,相位寄存器以步长M增加,相位寄存器的输出与相位控制字相加,然后输入到正弦查询表地址上。
正弦查询表包含一个周期正弦波的数字幅度信息,每个地址对应正弦波中0~360o范围的一个相位点。
查询表把输入的地址相位信息映射成正弦波幅度的数字量信号,驱动DAC,输出模拟量。
相位寄存器每经过2N/M个fc时钟后回到初始状态,相应的正弦查询表经过一个循环回到初始位置,整个DDS系统输出一个正弦波。
输出正弦波频率为:
频率控制字与输出信号频率和参考时钟频率之间的关系为:
其中N是相位累加器的字长。
频率控制字与输出信号频率成正比,可见控制M就能得到任意频率的信号。
在图中,相位累加器输出位并不全部加到查询表,而要截断。
相位截断减小了查询表长度,但并不影响频率分辨率,对最终输出仅增加一个很小的相位噪声。
通常用频率增量来表示频率合成器的分辨率,DDS的最小分辨率为:
这个增量也就是最低的合成频率。
由取样定理,所产生的信号频率不能超过时钟频率的一半,因此最高的合成频率为:
在实际运用中,为了保证信号的输出质量,输出频率不要高于时钟频率的1/4,以避免混叠或谐波落入有用输出频带内。
正弦ROM查询表完成输出信号相位到幅度的转换,它的输入是相位寄存器和相位控制字之和,其实也就是ROM的地址值(宽度为P位);ROM查找输出的数据(也为P位)送往D/A转换成模拟信号。
在实际应用中,P不能太大,如果P太大,会导致ROM容量的成倍上升,而输出受D/A精度的限制未有很大改善。
图2为相位累加器工作示意图,从图中可以看出,虽然相位累加器的位数为N位,但是只取高P位进行ROM查表。
3.2.基于PIC的DDS实现
图3DDS系统框图
3.2.1串行通信
通过RS232C的TXD管脚与PIC18F452的RC6/TX/CK管脚连接,实现和PC机之间的串行通信,能够用PC机改变频率控制字达到对输出正弦波频率的控制。
3.2.2、D/A转换
从数字信号到模拟信号的转换称为数-模转换,简称D/A转换。
数/模转换器DAC输入数字量是8位,图中所选电压Vref的工作范围是-2.5~+2.5V。
芯片内有一个8位输入寄存器和一个8位DAC寄存器,形成两级缓冲结构。
这样可使DAC转换输出前一个数据的同时,将下一个数据传送到8位输入寄存器,以提高数/模转换的速度。
DAC与PIC18F452的接口电路如图3所示,18F452的RD0/PSP0~RD7PSP7口直接与DAC的数字输入DI0~DI7相接。
通过该芯片将正弦查询表所得的数字信号转换成模拟信号输出。
3.3.3低通滤波器
在DAC的VOUT输出端接电阻R1和电容C1构成一个简易的低通滤波器。
由于DDS合成信号是正弦波时,D/A输出的信号中有许多不需要的寄生谱分量,只有基波分量才是所需要的,因此在D/A之后需跟一个低通滤波器,将除基波外的谐波过滤掉。
四、软件设计
上电复位后,初始化串行通讯终端;
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharacc=6;
ucharucTable0[120]={
127,134,140,147,154,160,166,173,179,185,
191,196,202,207,212,217,222,226,230,234,
237,241,243,246,248,250,252,253,254,254,
255,254,254,253,252,250,248,246,243,241,
237,234,230,226,222,217,212,207,202,196,
191,185,179,173,166,160,154,147,140,134,
127,120,114,107,100,94,88,81,75,69,
63,58,52,47,42,37,32,28,24,20,
17,13,11,8,6,4,2,1,0,0,
0,0,0,1,2,4,6,8,11,13,
17,20,24,28,32,37,42,47,52,58,
63,69,75,81,88,94,100,107,114,120
};
ucharucDA[120];
floatres;
intfre;
intnum=2;
ucharsize;
uintia,ib;
staticucharrec[4],temp;
staticcharindex;
voiddelayms(unsignedintx);
voidSetucDA(uchardatanum)
{
uchari;
uchark;
k=120/datanum;
for(i=0;iucDA[i]=ucTable0[i*k];
}
voidmain(void)
{
TRISD=0x00;
TRISCbits.TRISC6=0;
//初始化串口
INTCON=0b11000000;
//使能全局中断,使能高优先级外设中断,
PIE1bits.RCIE=1;//使能接收中断
IPR1bits.RCIP=1;//接收中断为高优先级
TXSTA=0b00100100;
//?
?
发送使能;异步;?
高速;?
?
RCSTA=0b10010000;
//使能串口,?
:
允许接收器
SPBRG=103;//9600
fre=1000;
if(fre<=240)size=120;
elseif(fre<=490)size=60;
elseif(fre<=740)size=40;
elseif(fre<=1200)size=24;
elseif(fre<=1500)size=20;
elseif(fre<=2540)size=12;
SetucDA(size);//根据频率不同,设定不同的数据数量,频率高,数量少
res=4.0*(1000000.0/size/fre-34);//float
ia=res/14;//取整
num=res-ia*14;//余数取整
if(res-ia*14-num>0.5)
num++;
while
(1){
while(num==0){
Nop();Nop();
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}
if(acc==120)acc=0;
}
while(num==1){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}Nop();
if(acc==120)acc=0;
}
while(num==2){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}Nop();Nop();
if(acc==120)acc=0;
}
while(num==3){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==4){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==5){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==6){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==7){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--)
{}Nop();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==8){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}
Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==9){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}
Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==10){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}
Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==11){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}
Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==12){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}Nop();Nop();Nop();Nop();Nop();Nop
();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==13){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}
Nop();Nop();Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
while(num==14){
ib=ia;
PORTD=ucDA[acc%size];
acc++;
while(ib--){}
Nop();Nop();Nop();Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();Nop();Nop();Nop();
if(acc==120)acc=0;
}
}
}
voidInterruptHandlerHigh(void);
#pragmacodeInterruptVectorHigh=0x08//
voidInterruptVectorHigh(void)
{
_asm
gotoInterruptHandlerHigh
_endasm
}
#pragmacode
#pragmainterruptInterruptHandlerHigh
voidInterruptHandlerHigh(void)
{
staticucharrec[4],temp;
staticcharindex;
if(PIR1bits.RCIF)
{TRISB=0x00;
PORTB=~PORTB;
temp=RCREG;
rec[index]=RCREG;
index++;
if(temp=='a')
index=0;
if(index==4)
{
index=0;
fre=1000*(rec[0]-'0')+100*(rec[1]-'0')+10*(rec[2]-'0')+
(rec[3]-'0');
if(fre<=1)
fre=1;
if(fre>=2500)
fre=2500;
if(fre<=240)size=120;
elseif(fre<=490)size=60;
elseif(fre<=740)size=40;
elseif(fre<=1200)size=24;
elseif(fre<=1500)size=20;
elseif(fre<=2540)size=12;
SetucDA(size);
//根据频率不同,设定不同的数据数量,频率高,数量少
acc=0;
res=4.0*(1000000.0/size/fre-34.0);//float
ia=res/14;//取整
num=res-ia*14;//余数取整
if(res-ia*14-num>0.5)
num++;
TXREG=fre/1000;
while(TXSTAbits.TRMT);//判断发送移位寄存器是否为空
delayms
(2);
TXREG=(fre/100)%10;
while(TXSTAbits.TRMT);//判断发送移位寄存器是否为空
delayms
(2);
TXREG=fre%100/10;
while(TXSTAbits.TRMT);//判断发送移位寄存器是否为空
delayms
(2);
TXREG=fre%10;
while(TXSTAbits.TRMT);//判断发送移位寄存器是否为空
}
//PIR1bits.RCIF=0;
}
}
voiddelayms(unsignedintx)
{
unsignedinti,j;
for(i=x;i>0;i--)
for(j=150;j>0;j--);
}
五、测试结果
在串口调试器中输入0000~2000间的任意四位数字,然后可以从示波器到正弦波波形的明显变化。
六、实验心得
。