基于CPLD实现的DDS频率计.docx
《基于CPLD实现的DDS频率计.docx》由会员分享,可在线阅读,更多相关《基于CPLD实现的DDS频率计.docx(15页珍藏版)》请在冰豆网上搜索。
基于CPLD实现的DDS频率计
基于STC89C51和CPLD实现的DDS与频率计
键盘输入DDS
STC89C51
LCD1602显示电路频率计
系统框图
功能描述:
以STC89C51为控制核心,实现任意频率值fa(小于10KHz)的输入,经单片机出来后,生成相应的频率字,然后送给DDS模块,DDS模块开始工作,生成以频率值fs;但键盘测频键按下后,单片机控制频率计,让其开始控制,频率计输出值送回单片机处理,得出测量到的频率值fc,最后单片机控制LCD1602显示人为输入的频率值fa和频率计测得的频率值fc,两个值的差异可以直观的显示出系统的误差。
基于CPLD/FPGA的DDS原理图如下:
基于CPLD/FPGA的频率计的原理图如下:
DDS模块代码:
(1)MUX832
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYMUX832IS
PORT(DATAINN:
INSTD_LOGIC_VECTOR(7DOWNTO0);
clk:
instd_logic;
DATAOUTT:
OUTSTD_LOGIC_VECTOR(31DOWNTO0);
SELL:
INSTD_LOGIC_VECTOR(1DOWNTO0));
ENDMUX832;
ARCHITECTUREbehavOFMUX832IS
BEGIN
PROCESS(SELL,DATAINN,clk)
BEGIN
ifclk'eventandclk='1'then
CASESELLIS
WHEN"00"=>DATAOUTT(7DOWNTO0)<=DATAINN;
WHEN"01"=>DATAOUTT(15DOWNTO8)<=DATAINN;
WHEN"10"=>DATAOUTT(23DOWNTO16)<=DATAINN;
WHEN"11"=>DATAOUTT(31DOWNTO24)<=DATAINN;
ENDCASE;
endif;
ENDPROCESS;
ENDbehav;
(2)32位加法器
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYADDER32BIS
PORT(A:
INSTD_LOGIC_VECTOR(31DOWNTO0);
B:
INSTD_LOGIC_VECTOR(31DOWNTO0);
S:
OUTSTD_LOGIC_VECTOR(31DOWNTO0));
ENDADDER32B;
ARCHITECTUREbehavOFADDER32BIS
BEGIN
S<=A+B;
ENDbehav;
(3)32位寄存器
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYREG32BIS
PORT(LOAD:
INSTD_LOGIC;
DIN:
INSTD_LOGIC_VECTOR(31DOWNTO0);
DOUT:
OUTSTD_LOGIC_VECTOR(31DOWNTO0));
ENDREG32B;
ARCHITECTUREbehavOFREG32BIS
BEGIN
PROCESS(LOAD,DIN)
begin
IFLOAD'EVENTANDLOAD='1'THEN
DOUT<=DIN;
ENDIF;
ENDPROCESS;
ENDbehav;
频率计模块代码:
(1)标准频率计数器
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYBZHHIS
PORT(BCLK:
INSTD_LOGIC;--Fs
BENA:
INSTD_LOGIC;
CLR:
INSTD_LOGIC;--清零
BZQ:
inOUTSTD_LOGIC_VECTOR(31DOWNTO0));
ENDBZHH;
ARCHITECTUREbehavOFBZHHIS
BEGIN
PROCESS(BCLK,CLR)--标准频率计数开始
BEGIN
IFCLR='1'THENBZQ<=(OTHERS=>'0');
ELSIFBCLK'EVENTANDBCLK='1'THEN
IFBENA='1'THENBZQ<=BZQ+1;
ENDIF;
ENDIF;
ENDPROCESS;
ENDbehav;
(2)待测频率计数器
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYTTFFIS
PORT(TCLK:
INSTD_LOGIC;--Fs
ENA:
INSTD_LOGIC;
CLR:
INSTD_LOGIC;--清零
TSQ:
inOUTSTD_LOGIC_VECTOR(31DOWNTO0));
ENDTTFF;
ARCHITECTUREbehavOFTTFFIS
BEGIN
PROCESS(TCLK,CLR,ENA)
BEGIN
IFCLR='1'THENTSQ<=(OTHERS=>'0');
ELSIFTCLK'EVENTANDTCLK='1'THEN
IFENA='1'THENTSQ<=TSQ+1;
ENDIF;
ENDIF;
ENDPROCESS;
ENDbehav;
(3)MUX648
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYMUX648IS
PORT(DATAIN1:
INSTD_LOGIC_VECTOR(31DOWNTO0);
DATAIN2:
INSTD_LOGIC_VECTOR(31DOWNTO0);
DATAOUT:
OUTSTD_LOGIC_VECTOR(7DOWNTO0);
SEL:
INSTD_LOGIC_VECTOR(2DOWNTO0));
ENDMUX648;
ARCHITECTUREbehavOFMUX648IS
BEGIN
DATAOUT<=DATAIN1(7DOWNTO0)WHENSEL="000"ELSE--标准频率计低八位输出
DATAIN1(15DOWNTO8)WHENSEL="001"ELSE
DATAIN1(23DOWNTO16)WHENSEL="010"ELSE
DATAIN1(31DOWNTO24)WHENSEL="011"ELSE--标准频率计最高八位输出
DATAIN2(7DOWNTO0)WHENSEL="100"ELSE--待测频率计数值低八位输出
DATAIN2(15DOWNTO8)WHENSEL="101"ELSE
DATAIN2(23DOWNTO16)WHENSEL="110"ELSE
DATAIN2(31DOWNTO24)WHENSEL="111"ELSE--待测频率计数值最高八位输出
DATAIN2(31DOWNTO24);
ENDbehav;
单片机程序如下:
主程序
#include
#include
#include"key.h"//scankey();keyexe();setfre();testfre();
#include"lcd1602.h"//display();
voidmain(void)
{
lcd_init();
bena=0;
clr=1;
load_dds=0;
oe=0;
start=1;
lcd_str(0,2,"dds.and.testfre!
");
while
(1)
{
keyexe();
}
}
键盘程序:
#ifndef__KEY_H__
#define__KEY_H__
#include
#include
#include"lcd1602.h"
#definedinoutP3;
unsignedcharkeybuffer[8],longtochar[4],recieve[8];
unsignedlongfreword,setdispbuf;
unsignedlongtfrecount,bfrecount;//Fs、Fx计数值
unsignedlongtfreword;
//-----------pindefineforddsandtestfre------
sbitsel2=P1^2;
sbitsel1=P1^1;
sbitsel0=P1^0;
sbitoe=P2^3;
//-----------pindefineforddsloading----------
sbitload_dds=P2^4;
//-----------pindefinefortestfre--------------
sbitclr=P2^0;
sbitbena=P2^1;
sbitstart=P2^2;
//-----------delayprogramm----------------------
voiddelay(unsignedintn)
{
while(n--)_nop_();
}
//-----------formatexchange---------------------
voidkeytofreword(void)
{
freword=keybuffer[0]*10000000+keybuffer[1]*1000000+keybuffer[2]*100000+keybuffer[3]*10000+keybuffer[4]*1000+keybuffer[5]*100+keybuffer[6]*10+keybuffer[7];//合成输入频率值
setdispbuf=freword;
freword=(unsignedlong)(freword*214.7493648);//计算相应的频率字
longtochar[0]=(freword>>24)&0xff;//频率字最高八位
longtochar[1]=(freword>>16)&0xff;//频率字次高八位
longtochar[2]=(freword>>8)&0xff;//频率字次低八位
longtochar[3]=(freword)&0xff;//频率字最低八位
}
//-----------selectchannel-----------------------
voidselect(unsignedcharsel)
{
unsignedchari,j;
j=sel;
sel=sel&0x07;
i=P1;
i=i&0xf8;
i=i|sel;
P1=i;
}
//-----------settingfrequency--------------------
voidsetfre(void)
{
unsignedchari;
keytofreword();
display(setdispbuf,1);//显示输入的频率值
lcd_str(0,2,"--setting.fre!
-");
oe=0;
load_dds=0;
for(i=0;i<4;i++)
{
select(i);
P3=longtochar[i];
_nop_();
_nop_();
_nop_();
load_dds=1;
_nop_();
_nop_();
_nop_();
load_dds=0;
}
lcd_str(0,2,"--setting.succ!
-");
}
//----------testfrequency------------------------
voidtestfre(void)
{
unsignedchari;
unsignedintj;
lcd_str(0,2,"--testing.fre---");
bena=0;
clr=0;
_nop_();
_nop_();
_nop_();
_nop_();
clr=1;//-----clearregister--------清零
bena=1;//允许频率计开始工作
delay1ms_x(1000);//门控时间2S
delay1ms_x(1000);
bena=0;//------countuntilstartequals0------------
j=10000;
while((start==1)&&(j--));//----waitforendoftesttingortimeout---
if(j==0)
lcd_str(0,2,"--test.fre.err!
-");
else
lcd_str(0,2,"-test.fre.succ!
-");
oe=1;//双向口
for(i=0;i<8;i++)
{
select(i);
P3=0xff;//P3作为输入口
_nop_();
_nop_();
_nop_();
_nop_();
recieve[i]=P3;//读取频率计计数值
}
oe=0;
bfrecount=0;
tfrecount=0;
for(i=0;i<4;i++)
{
bfrecount=(bfrecount<<8)+recieve[i];//合成标准频率计数值
tfrecount=(tfrecount<<8)+recieve[i+4];//合成待测频率计数值
}
tfrecount=(unsignedlong)tfrecount/3.5200886+1;//?
?
?
?
?
?
display(tfrecount,0);
}
//-------------------scankeyvalue-------------------------
unsignedcharscankey(void)//键盘扫描
{
unsignedchari=0xff,k=0xfe,buf;
unsignedcodetable[4]={0xfe,0xfd,0xfb,0xf7};
for(i=0;i<4;i++)
{
P1=table[i];
buf=P1;
if(buf!
=table[i])
{
delay(1000);
if(buf==P1)
{
while(buf==P1);
break;
}
}
}
switch(buf)
{
case0xee:
return1;
case0xed:
return2;
case0xeb:
return3;
case0xe7:
return10;//4
case0xde:
return4;//5
case0xdd:
return5;//6
case0xdb:
return6;//7
case0xd7:
return11;//8
case0xbe:
return7;//9
case0xbd:
return8;//0
case0xbb:
return9;//11
case0xb7:
return12;//12
case0x7e:
return13;//13
case0x7d:
return0;//14
case0x7b:
return14;//15
case0x77:
return15;//16
default:
return16;//10
}
P1=0xff;
}
//-----------------keyexecution-----------------------
voidkeyexe(void)
{
unsignedchari,buf;
buf=scankey();//调键盘扫描,读取键值
switch(buf)
{
case0:
case1:
case2:
case3:
case4:
case5:
case6:
case7:
case8:
case9:
for(i=0;i<7;i++)
keybuffer[i]=keybuffer[i+1];
keybuffer[7]=buf;
lcd_data1(0,1,'i');
lcd_data1(1,1,'n');
lcd_data1(2,1,'p');
lcd_data1(3,1,'u');
lcd_data1(4,1,'t');
lcd_data1(5,1,':
');
lcd_data1(6,1,keybuffer[0]+'0');
lcd_data1(7,1,keybuffer[1]+'0');
lcd_data1(8,1,keybuffer[2]+'0');
lcd_data1(9,1,keybuffer[3]+'0');
lcd_data1(10,1,keybuffer[4]+'0');
lcd_data1(11,1,keybuffer[5]+'0');
lcd_data1(12,1,keybuffer[6]+'0');
lcd_data1(13,1,keybuffer[7]+'0');
lcd_data1(14,1,'H');
lcd_data1(15,1,'z');
break;
case10:
lcd_cmd(clear);
setfre();
break;
case11:
testfre();
break;
case12:
for(i=0;i<8;i++)
{
keybuffer[i]=0;
lcd_data1(i+6,1,keybuffer[i]+'0');
}
lcd_data1(14,1,'H');
lcd_data1(15,1,'z');
break;
default:
break;
}
}
#endif