AD9850采用先进的DDS技术,在内部集成了32 b相位累加器、14 b正/余弦查询表和高性能的10 bD/A转换器以及一个高速比较器。他通过并口或串口写入的频率控制字来设定相位累加器的步长大小,相位累加器输出的数字相位通过查找正/余弦查询表得到 所需频率信号的采样值,然后通过D/A变换,输出所需频率的正弦波信号。还可以通过高速比较器将该正弦波信号转换成方波,作为时钟信号输出。
1 系统总体设计
AD9850有40 b寄存器:32 b用于频率控制,5 b相位控制,1 b电源休眠功能,2 b厂家保留测试控制。这40 b控制字可通过并行方式或串行方式装入到AD9850。在并行装入方式中,通过8 b总线D7~D0重复5次装入寄存器,在FQ-VD上升沿把40 b数据从输入寄存器装入到频率和相位及控制数据寄存器,从而更新DDS输入频率和相位,同时把地址指针复位到第1个输入寄存器。在串行装入方式中,W- CLK上 升沿把25脚(D7)的1 b数据串行移入,移动40 b后,
用一个FR-VD就可以更新输出频率和相位。设计中选用并行装入方式。
频率调谐和相位调制字通过一个并行装载格式装入到AD9850中,并行装载的格式由连续的8 b控制字组成。第1个8 b字节中的5 b用来控制相位调制,1 b用来低功耗,2 b用于装载格式。第2个字节到第5个字节组成32 b频率调谐字,最大的控制寄存器的更新频率为23 MHz。其输出信号的频率fDDS由式(1)确定:
fDDS=Δf.fCLK/232(1)
其中:Δf为32 b频率控制字的值;fCLK为工作时钟。
AD9850控制简单,可用8 b并行口直接输入频率、相位等控制数据,其功能原理如图1所示。
2 AD9850与单片机接口设计
单片机用来实现对整个系统的控制。单片机控制部分包括键盘显示电路以及频率合成部分的接口电路。产生的正弦波或者方波的频率以及需要实现的功能信息从键盘键入,同时由显示器显示。频率合成以及各功能实现部分由DDS芯片AD9850及其外围电方波的产生输出。
AT89C51单片机是低功耗、高性能CMOS8 b单片机,有4 kb可编程闪存以及可擦写只读存储器(EPROM),该产品与MSC-51系列指令系统和管脚输出的工艺标准完全兼容,可进行电擦写 *** 作并具有超强的加密 功能。AT89C51单片机主要实施逻辑控制功能:根据用户选择产生波形,形成频率字,与上位机通信等。波形、幅值的控制主要由数字电位器构成,即由 89C51的2根口线对其进行控制。AD9850的输出波形接到数字电位器的固定端,单片机通过P1口线改变数字电位器的滑动端计数寄存器的内容,从而控 制滑动端在电阻阵列中的位置,改变输出波形幅值。
电路设计时,对时钟信号的质量要求比较高,即时钟信号的上升沿和下降沿应无大的尖峰和凹坑, 时钟信号必须用地线屏蔽。另外,给AD9850的时钟信号不能低于1 MHz,低于这个数值时,芯片将自动进入休眠状态;当高于此频率时,系统则恢复正常。最后还要考虑设计良好的去耦电路,去耦电容尽可能靠近器件,并注意良 好接地,模拟地和数字地一定要分开等。
3 D/A转换电路设计
由于AD9850是由10 b D/A转换器来输出正弦波信号,因此其输出频率最大值不能超过参考输入频率的1/2。当作为时钟源时,考虑到衰减问题,其输出频率的最佳值限制在参考输入 频率的33%以下。器件内部设有最小时钟门限,当输入频率低于1 MHz时,芯片将自动实现电源判断。
AD9850的直接数字合成技术是基于 数字分频原理实现频率合成的。该器件内部有一个增量可调的累 加器,每接收到一个输入脉冲,累加器就增加所设定的增量(由写入的32 b频率控制字决定),当累加器溢出时,就输出一临界值,AD9850用一种算法逻辑把累加器输出值转换为接近正弦的量化值,这种算法逻辑实际上就是由高度 集成化的存储器查表技术和数字信号处理(DSP)技术来完成的。随后AD9850将量化值送内部的D/A转换器输出正弦波形,若再辅以外部电路(低通滤 波)送内部比较器,即可输出标准的方波信号。
主机借助于程序可以启动D/A转换器中任一通道进行转换工作。当有一条通道被启动时,开始将采样 输入的数字量转换为模拟量,转换完成后,向单片机请求中断。D/A转换器选用TLC7528,按照用户的要求来改变正弦信号的幅值,最终输出用户要求的波 形,提供给下位机。其D/A电路设计框图如图2所示。
4 软件设计
主程序用于完成键盘功能的识别,输出频率的显示以及对AD9850实现各种功能的控制。其设计流程图如图3所示。
对AD9850进行初始化控制时,主复位脚必须置高电平在10个系统周期以 上,主复位的作用是初始化系统总线,置控制寄存器以缺省值。程序设计中要注意AD9850的时序要求,正确送出逻辑控制字,注意其刷新时钟。通过写端口写 入AD9850的控制字暂时寄存在I/O缓冲寄存器中,需要一个从低到高的时钟信号从外部输入,或者由内部32 b的刷新时钟把I/O缓冲寄存器中的控制字传送到DDS的内核。
经调试正确的主程序如下:
5 结 语
应用AT89C51与可编程逻辑控制器件相结合控制AD9850产生频率、幅值均可变化的正弦波信号。该正弦标校信号源稳定方便,可用于许多实时控制系统中,还可以通过高速比较器将该正弦波信号转换成方波,作为时钟信号输出。
将干簧管脉冲信号通过单片机实现到数码管显示:
/********************************************************************
* 文件名 : TLC549.c
* 描述 : 该程序实现了对TLC549的控制。通过TLC549把电压转换为数字信号并通过数码管显示出来。实际工作中进行AD采样时,一般都要把AD信号处理后再用。在这里,采集了30次,去掉最大和最小的5个,中间20个取平均值,最大限度的保证了所要采集AD的准确性。
***********************************************************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit AD_Out = P3^2 //TLC549输出端
sbit CS = P1^0 //TLC549片选信号
sbit AD_In = P1^1 //TLC549输入端
uchar code table[10] = {0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09}
uchar code table_d[10] = {0x02, 0x9e, 0x24, 0x0c, 0x98, 0x48, 0x40, 0x1e, 0x00, 0x08} //带点数码管显示
/********************************************************************
* 名称 : AD_Change(void)
* 功能 : TLC549驱动程序,在“视频及教程”中有讲解。
* 输入 : 无
* 输出 : temp (电压值)
***********************************************************************/
uchar AD_Change(void)
{
uchar i,temp = 0
CS = 0
_nop_()
_nop_()
_nop_()
_nop_()
for(i=0 i<8 i++)
{
AD_In = 1
_nop_()
_nop_()
temp = temp << 1
if(AD_Out == 1) temp += 1
AD_In = 0
_nop_()
_nop_()
}
CS = 1
return temp
}
/********************************************************************
* 名称 : Delay()
* 功能 : 延时,延时时间为 1ms * del
* 输入 : del
* 输出 : 无
***********************************************************************/
void Delay(uint del)
{
uchar i, j
for(i=0 i
for(j=0 j<=148 j++)
}
/***********************************************************************
* 名 称: Average()
* 功 能: 中位值平均滤波法,取一共三十个数据,最大和最小的五个数据不要
对中间的二十个数据求平均值
* 输 入: 三十个待处理的值
* 输 出:得到一个中位的平均值
***********************************************************************/
uint Average(uint buffer[30])
{
uchar i,j
uint temp
for(i=1 i<30 i++) ////先对整个数组的三十个值进行从小到大的排列
for(j=29 j>=i --j)
{
if(buffer[j-1] > buffer[j])
{
temp = buffer[j-1]
buffer[j-1] = buffer[j]
buffer[j] = temp
}
}
////对数组进行处理,去掉一个最大值和一个最小值,中间的二十个值再来求平均值
temp = 0
for(i=5 i<25 i++)
{
temp += buffer[i]
}
temp = (uint)(((float)temp) / 20 + 0.5)
return(temp)
}
/***********************************************************************
* 名 称: AD_Filter()
* 功 能: 进行AD采集30次,并进行滤波处理
* 输 入: 三十次AD采集值
* 输 出:经过处理后的AD值
***********************************************************************/
uint AD_Filter()
{
uint Date_Buffer[30] = {0}, temp
uchar i
for(i=0 i<30 i++)
{
Date_Buffer[i] = AD_Change()
Delay(1) //延时1毫秒采集一次。这里可以根据工作需要调整时间。
}
temp = Average(Date_Buffer)
return(temp)
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main()
{
uint i = 0,temp
uint j
P2 = 0x00
P1 = 0xff
while(1)
{
temp = AD_Filter()
j = temp * 2
for(i=0 i<40 i++)
{
P0 = table_d[j / 100]
P2 = 0x04
Delay(10)
P0 = table[j/ 10 % 10]
P2 = 0x02
Delay(10)
P0 = table[j % 10]
P2 = 0x01
Delay(10)
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)