简易频率特性测试仪的设计
加在前面:
术业有专攻。一般写一些东西我也不会在空间瞎发,弄的别人以为自己瞎显摆。不过我觉得我们电子设计的过程确实值得其他小组学习一下,比如说老葛焊板子那种芯片的布局,还有我们用4个按键解决所有数字的设置的思想。我希望大家看到文章的时候不是觉得怎么吊炸天,其实我们这种水平比我们吊炸天的多了去。我们之所以有敢厚着脸皮把这么次的设计思想分享出来,主要希望能把其中的某一些发光点分享给大家,同时希望他人给我们的更宝贵的
意见
文理分科指导河道管理范围浙江建筑工程概算定额教材专家评审意见党员教师互相批评意见
和建议。
----end----
电子设计三中,仪器仪
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
组的第一个题目,是简易频率特性测试仪的设计。这个题目取自2013年的E题:简易频率特性测试仪(E 题)。
为了纪念近一个月的工作,特撰以此文纪念我们第七小组历经了的艰辛岁月。在此,感谢组长葛家瑾大神、还有范一华同学的辛勤付出,还有李煜及其他一些学长的帮助。
特发上图,以作纪念。
在本次完成题目的过程中,葛大神早早完成了公式推导、电路理论和原理的分析,并组织我们在工作上分工(虽然他好像对“被我和范一华排挤去焊电路板”很不满意私下抱怨并耿耿于怀,哈哈)。
下面我简单的回顾一下我们的这次设计:其中,有关硬件电路的部分是葛大神负责的,我只是略懂了原理,故仅仅略述。我主要承担的是AD采样部分的程序,还有就是通过操作液晶屏和按键实现的程序的总体逻辑控制程序。范一华同学主要完成的是AD9854部分的程序,正弦波输出及其幅度补偿,还有扫频部分的程序。下面,我从入手这道题目的开始状态,来一步步回顾一下。
下面,先把题目贴出来:
/*=======================开始贴题目=======================*/
【本科组】
一、任务
根据零中频正交解调原理,设计并制作一个双端口网络频率特性测试仪,包括幅频特性和相频特性,其示意图如图 1 所示。
二、要求
1.基本要求
制作一个正交扫频信号源。
(1)频率范围为 1MHz~40MHz,频率稳定度≤10^-4;频率可设置,最小设置单位 100kHz。
(2)正交信号相位差误差的绝对值≤5o,幅度平衡误差的绝对值≤5%。
(3)信号电压的峰峰值≥1V,幅度平坦度≤5%。
(4)可扫频输出,扫频范围及频率步进值可设置,最小步进 100kHz;要求
连续扫频输出,一次扫频时间≤2s。
2.发挥部分
(1)使用基本要求中完成的正交扫频信号源,制作频率特性测试仪。
a. 输入阻抗为 50?,输出阻抗为 50?;
b. 可进行点频测量;幅频测量误差的绝对值≤0.5dB,相频测量误差的绝对值≤5o;数据显示的分辨率:电压增益 0.1dB,相移 0.1o。
(2)制作一个 RLC 串联谐振电路作为被测网络,如图 2 所示,其中 Ri和Ro分别为频率特性测试仪的输入阻抗和输出阻抗;制作的频率特性测试仪可对其进行线性扫频测量。
a. 要求被测网络通带中心频率为 20MHz,误差的绝对值≤5%;有载品质因数为 4,误差的绝对值≤5%;有载最大电压增益≥ -1dB;
b. 扫频测量制作的被测网络,显示其中心频率和-3dB 带宽,频率数据显示的分辨率为 100kHz;
c. 扫频测量并显示幅频特性曲线和相频特性曲线,要求具有电压增益、相移和频率坐标刻度。
(3)其他。
/*=======================贴题目结束=======================*/
AD9854实验板的程序,我们直接有学长找来的代码,我们需要做的工作只是移植。然而,源程序对应的IO口用到的均为位操作,而我们使用的F020单片机不能直接对P6、P7口直接进行位操作,所以需要将位操作均用“|=bitx”或者“&=!bitx”的方式来置位或者复位。这一段程序由范一华同学完成移植,在此不贴出了。
硬件部分最值得一说的是AD835解调板,该板子由葛大神焊成。
他共焊接了两次,第一次半途而废,因为确实太渣渣了。第二次,板子正面元器件布局很好,但是最终测试的时候,发现还是效果不行,原因可能是高频信号的其板子背面走线,尤其是AD9854的双正弦波输入附近位置的不佳处,受到的影响较大(具体我不清楚为什么)。
你们会发现,途中下面的两块转接板上你看不到芯片,这并不是没有焊芯片,而是焊接时候就把板子反面了一下。这样的话,芯片引脚的布局就和电路的原理图上一样啦,在走线的时候将方便许多,这个小技巧大家可以学习一下。
老哥说了下次还是他要来焊了啦,要给他一个挽回的机会哈哈。
现在贴出AD835解调板原理图:
解调板左边的四个接口,分别对应如下:Q-AD9854cos路,I-AD9854sin路,IN-RLC被测网络输入端,OUT-LC被测网络输出端。右侧分别为Ain0和Ain1路的采样,输给F020单片机的ADC0.
输入解调板的两路正交的sin信号I和Q,期中I路经过RLC网络后分别与I路和Q路相乘。通过AD835完成乘法,其输出:
分别给偏置电压0.125mV和0.25mV。通过TL431给出稳定的偏置。
分别通过低通滤波器,得到直流分量。这里低通的指标是按照截止频率100KHz做得,其实具体是多少,只要足够小就行。
为了让F020能够采样到合适范围的电压值,通过低通滤波器后,再将信号放大10倍。
实际上,我们会发现,因为F020板子上参考电压已经与内部相连,我们无法改变,最大电压只能采样到2.48V,幸好最大电压只能是2.5V,我们在这种情况下可以视为2.5V来算。但是我们设想,如果将电压放大的倍数略设置小一些,如8倍,将解决该问题。
最后,就是在程序中,根据公式算出实际的被测网络的K(幅度衰减)和Fi(相位)值啦。经过滤波器之后,两路直流分量为:
,
由此推出:
,由此再推出K,再代回某个式子推出Fi,这里就略了。
这里建议用sin函数推导(代回Q路公式),我们可以发现asin函数的值域[-90度,+90度]对应的值正好为[-1,+1],这样我们方便在程序中计算。Atan函数毕竟精确度没有asin好,这个自己画函数图像便知。
硬件电路就说这么多了,下面我来show一下我们的代码。
这里补充一些大家在画幅频、相频曲线的时候可能会遇到的问题:
如果你们图像画的不
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
,可能有这些原因:
1、公式形式问题。最开始我们公式中用的是mV做电压的单位,发现计算出来的数值打在屏上是错的。后来发现是因为mV本来就是10^3,再需要平方等等,可能已经造成了数据类型的溢出。后来我们改在计算之前转换成V作为电压的单位,结果就对了。其实我们不难想到,当我们做小数乘法的时候,就算数据类型有溢出,也是向后溢出的,缺失的是我们不太关心的极小的部分。
2、可能是你们的硬件电路有问题。我们的硬件电路跑在我们自己的软件上,画出来的相频曲线明显不对,根本都看不出来是什么。但是换成吴天涯组他焊的板子,结果图像就特别好,是一个从90度逐渐减小的趋势。相频我们的还行。但是由此还是可见,就算程序写的没有问题,如果AD835解调板焊接不行,还是会影响你的软件显示,造成怀疑自己程序错误的假象。
3、可能是你们的公式推导问题: 我们最早把峰峰值和电压幅度值弄混淆的写在一起计算,这样你会发现得出的结果比理论上差个2倍或者多个2倍。这个问题细心看一下就解决了。
--------
关于ADC采样值转化为实际电压值的一些问题:
ADC0H+ADC0L中如果数据为4095,表示的电压:超过了2.48或者引脚悬空的时候都是4095。
问:如果adc采样后,寄存器里面的值为temp,那么电压就是vin=temp/4095*2.48,对吗?
答:如果你这样处理,是不好的。我们知道,AD采样在低于180mV电压和高于2.4V电压的时候是不够准确的,2.48只是一个手册里面给的参考电压。
我们组的做法是,用电源输入一个1v的电压,
记录
混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载
现在的ADC采样数值。再输入一个2V电压,记录现在采样数值。然后,就可以画出一条线性的曲线,以后任意采样到的ADC值,都可以转化成实际的电压。
====================================================
Main.c函数
#include "lcdsys.h"
#include "key.h"
#include "lcd.h"
#include "Device.h"
int main()
{
Device_Init();
KeyPort_Init();
newLCDInit();
//Welcome Pics.
Clear();
DrawcharS("Our AD9854 sys",1,0);
DrawcharS("- to Be No.1",2,4);
while(0==KeyScan()){};
////Go into Our System.
initlcdsys();
while(1)
{
sysfuntion(KeyScan());
}
}
上面是我们的main函数,我们主要就是进来初始化所有需要用到的外围电路,然后就进了一个sysfuntion(KeyScan());函数,这就是我们的LCDsys。
当然了,我们的LCDsys.c有600+行,所以接下来关于这段程序的解读,我会直接在代码里面写。我个人认为我一个比较好的编程习惯就是注释写得非常详细,当然,和别的大牛比起来就很渣渣啦,不过通过注释让隔了一段时间后自己还看得懂自己的程序是非常必要的。然后,我写此文时对程序的解读,我就用【】扩起来表示。
Lcdsys.c函数
#include "lcdsys.h"
#include "DataType.h"
#include "math.h"
#include "string.h"
#include "lcd.h"
#include "key.h"
#include "ADDA.h"
#include "AD9854.h"
#include "c8051F020.h" //c8051f020单片机头文件
【上方都是头文件就没什么说的啦,当然,如果你经常在把别人的程序挪给自己用的时候出错,那么你就需要专门百度一下.c程序的头文件.h需要怎么写了。】
#define Vppadjust 0.819
#define VppFangDaBeiShu 10.0
#define VppPianZhiValue 1250.0
#define GNDBuChang 13.0
【如果你有把不需要改变的值定义成变量的坏习惯,建议你定义他们为常量。这样你不会在程序中不小心的改变他们,更不会让Keil不智能的编译器不知为什么的就让你的程序跑飞。F020单片机的存储单元在你写了一大串自己都不太记得什么用的变量和大量的借鉴了别人的代码后都不知道别人有什么变量的情况下存储空间的资源将会是十分极其以及相当的紧张的,所以你需要有这个习惯】
unsigned int f;//幅度(整型)给AD9854的时候*1000.0
unsigned int a;//幅度(整型)给AD9854的时候*Vppadjust(即0.819)
unsigned int xdata tmp[5];//记录采集出来的ADC0的12位数据
bit JiaoZhunBit;
float xdata ad0bc[5];//补偿值数据
float xdata ad1bc[5];//补偿值数据
float xdata MaxValue;//最大相位或K取值
int xdata MaxPoint;//最大相位或K的频率点、
//float xdata MinValue;//最小相位或K取值
//int xdata MinPoint;//最小相位或K的频率点、
float xdata Value[120];
int xdata ThreeDb[2];
【给自己定义的变量注释清楚到底是用作什么用的】
/*========对应关系========
0- 5000k( 5M)
1-10000k(10M)
2-20000k(20M)
3-30000k(30M)
4-40000k(40M)
========对应关系========*/
unsigned int adtmp,adtmp0,adtmp1;//记录采集出来的ADC0的12位数据
long double ad0,ad1,sinFi,Du,K;//将12位数据转化为实际电压值,保存为浮点数据//cosFi已经不用了
unsigned char wei,count,incount;//LCDsys用的:数据标志位、全局计数位、内嵌套计数位
unsigned char cmd;//画图时候:1-频率特性绘图,2-幅度特性曲线,3-校准,4-退出
//扫频时候:1-步进,2-起始频率,3-截止频率
bit AorF;//用于标志:设置频率或者幅度、的标志位。
unsigned int mo=1;//扫频使用 scan using...
unsigned long Freq1=1000000.0;//扫频使用 scan using...
unsigned int scanstep=1;//扫频使用 scan using... 扫频步进
void initlcdsys()//LCDsys初始化函数
{
ADCcount=0;
f=100;// kHz
a=2000;// mV
wei=0;AorF=0;
Clear();
fun_ok();
JiaoZhunBit=0;
MaxValue=0;
MaxPoint=0;
//MinValue=0;
//MinPoint=0;
for(count=0;count<120;count++){Value[count]=0;}
ThreeDb[0]=0;ThreeDb[1]=0;
}
【其实最好是写一个初始化函数,给自己定义了的变量赋一个初值】
【下面是一个寻找5个数字的中值得函数,用到了冒泡排序,还记得不?】
unsigned int mid5(unsigned int num1,unsigned int num2,unsigned int num3,unsigned int num4,unsigned int num5){
unsigned int a[6],i,start;
a[1]=num1;a[2]=num2;a[3]=num3;a[4]=num4;a[5]=num5;
for(start=5;start>1;start--){
for(i=1;i
a[i+1]){a[0]=a[i];a[i]=a[i+1];a[i+1]=a[0];}
}
}
return a[3];
}
【下面是一个将一位的整型转化成字符串的函数】
//将 1 位的 int 型数据转换,返回‘字符’的子函数
char int2char(int input)
{
return 0x30+input;
}
【在液晶屏上画无符号整型的函数】
void drawint(unsigned int num,unsigned char row,unsigned char col)
{
Drawchar(int2char((num/1)%10),row,col+4);
Drawchar(int2char((num/10)%10),row,col+3);
Drawchar(int2char((num/100)%10),row,col+2);
Drawchar(int2char((num/1000)%10),row,col+1);
Drawchar(int2char((num/10000)%10),row,col+0);
}
【在液晶屏上画有符号整型的函数】
void drawsignedint(int input,unsigned char row,unsigned char col)
{
int num;
if(input<0){Drawchar('-',row,col+0);num=-input;}else{Drawchar('+',row,col+0);num=input;}
Drawchar(int2char((num/1)%10),row,col+4);
Drawchar(int2char((num/10)%10),row,col+3);
Drawchar(int2char((num/100)%10),row,col+2);
Drawchar(int2char((num/1000)%10),row,col+1);
}
【在液晶屏上画有符号浮点数的函数】
void drawsignedfloat2_2(float input,unsigned char row,unsigned char col)
{
float num;
if(input<0){
Drawchar('-',row,col+0);
num=-input;
}else{
Drawchar('+',row,col+0);
num=input;
}
Drawchar(int2char((int)(num/10.0)%10),row,col+1);
Drawchar(int2char((int)(num/1.0)%10),row,col+2);
Drawchar('.',row,col+3);
Drawchar(int2char((int)(num*10.0)%10),row,col+4);
Drawchar(int2char((int)(num*100.0)%10),row,col+5);
}
【这个函数是我们打主屏(F和A设置时候的函数),贴出图片来看看
】
void fun_ok()
{
if(AorF){
DrawcharS("Change A...",0,0);
drawint(a,1,0);
DrawcharS("mV",1,5);
DrawcharS("when F=",3,0);
drawint(f,3,7);
DrawcharS("kHz",3,12);
}else{
DrawcharS("Change F...",0,0);
drawint(f,1,0);
DrawcharS("kHz",1,5);
DrawcharS("when A=",3,0);
drawint(a,3,7);
DrawcharS("mV",3,12);
}
DrawcharS("=",2,wei);
}
【这是画扫频菜单时候的函数。。。
靠。。。找不到照片。。。可能没拍吧。。。
】
void fun_scanmsg()
{ Clear();
DrawcharS("Scaning...",0,0);
DrawcharS(">",cmd+1,0);
DrawcharS("scanStep=",1,1);drawint(100*scanstep,1,10);DrawcharS("k",1,15);
DrawcharS("Start=",2,1);drawint(adtmp0*100,2,7);DrawcharS("kHz",2,12);
DrawcharS("Stop=",3,1);drawint(adtmp1*100,3,6);DrawcharS("kHz",3,11);
}
【下面是两路ADC的补偿函数,根据不同的频率,将电压分别在接直通网络自动校准的时候,分别校准位1250mV和2500mV】
/*========对应关系========
0- 5000k( 5M)
1-10000k(10M)
2-20000k(20M)
3-30000k(30M)
4-40000k(40M)
========对应关系========*/
long double ad0BuChang(long double inputVpp,unsigned int inputf)//(相/频)度数补偿函数
{
long double BuChangVpp,k;
BuChangVpp=inputVpp;
if(1){//修改判断的值,以决定是否进行校正。
if( 11){a-=1;}break;
case 3:if(a>10){a-=10;}break;
case 2:if(a>100){a-=100;}break;
case 1:if(a>1000){a-=1000;}break;
//case 0:if(a>1){a-=10000;}break;
default:break;
}
fun_ok();
}else{
switch(wei){
case 4:if(f>1){f-=1;}break;
case 3:if(f>10){f-=10;}break;
case 2:if(f>100){f-=100;}break;
case 1:if(f>1000){f-=1000;}break;
case 0:if(f>10000){f-=10000;}break;
default:break;
}
fun_ok();
}
break;
【按键3,4控制的是下标表示位数的左移或右移】
case 3: Clear();
if(wei>(0)){wei-=1;}fun_ok();break;
case 4: Clear();
if(wei<(4)){wei+=1;}fun_ok();break;
【改变bit:AorF,区分在显示和加减的时候对应操作是频率或者幅度。】
case 5: Clear();
AorF=!AorF;
fun_ok();
break;
case 6: Clear(); //该按钮完成【正弦波按参数“频率”“幅度”输出】功能
【
】
DrawcharS("Sin:",0,0);
DrawcharS("Vpp=",1,2);
drawint(a,1,6);DrawcharS("mV",1,11);
DrawcharS("Fre=",2,2);
drawint(f,2,6);DrawcharS("kHz",2,11);
//测试正弦波,采用120MHZ SYSCLK时,出来10MHZ波形,波形很好,测试成功
//当采用300MHZ SYSCLK时,测试50MHZ波形时,DDS发热厉害,且波形衰减严重,幅度在35mV左右
AD9854_Init();
//输出的幅度 a mV = (x/4095)*5000mV 那么设置的参数 x 应当为 a*(4095/5000)
AD9854_SetSine((unsigned long)(f*1000.0),(int)(a*Vppadjust));
while(1){if(6==KeyScan()||5==KeyScan()){Clear();fun_ok();break;};};
break;
case 7: Clear();//该按钮完成【点频输出,通过系统后,输入AD后计算“相位”和“参数k”】功能
if(0==JiaoZhunBit){
DrawcharS("No ReSeted!!!",1,1);
while(1){if(0!=KeyScan()){Clear();fun_ok();break;};};
break;
}
DrawcharS("Waiting...",1,1);
DrawcharS("Wave Outputing",2,2);
AD9854_Init();AD9854_SetSine((unsigned long)(f*1000.0),(int)(a*Vppadjust));
delaywateAD9854(5000,5);/*====延时====*/
Clear();
drawint(a,0,0);DrawcharS("mV/",0,5); drawint(f,0,8);DrawcharS("kHz",0,13);//输出额定幅度和频率的正弦波
【case7完成的是点频功能
接的是直通网络时候,任意频率都是接近0度。
接的RLC时候,29.8MHz时候,度数为-21.52度。衰减7db。
】
/****AIN0采集电压****/
ADC0_Init(0,1);ADC0_Enable();count=0;while(count<5){tmp[count]=returnADC0value();count++;} ADC0_Disable();
////while(1){if(5==ADCcount){ADC0_Disable();break;}}//等待采样满足5个点,就【停止AD转换】【跳出采样】。
//从0.2V-2.4V我们测试的数据表明,可以用如下公式将AD转换得到的Value换算成电压值//公式:y=0.591238914x-3.386186509
adtmp=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
ad0=0.0;
if(adtmp<240) {DrawcharS("TooSmall",1,0); }
////else if(adtmp>4094){DrawcharS("TooBig",1,0); }
else {
////ad0=(0.591238914*adtmp-3.386186509);
ad0=GNDBuChang+(0.591238914*adtmp-3.386186509);////这里因为接地电压不统一的缘故,补偿10mv。
////if(adtmp>4094){ad0=2500;};
ad0=ad0BuChang(ad0,f);/****电压**自动校准****/
drawsignedint((int)ad0,1,0);
DrawcharS("mV",1,5);
ad0=((ad0-VppPianZhiValue)/VppFangDaBeiShu);
drawsignedint((int)ad0,2,0);
DrawcharS("mV",2,5);
}
/****AIN1采集电压****/
ADC0_Init(1,1);ADC0_Enable();count=0;while(count<5){tmp[count]=returnADC0value();count++;} ADC0_Disable();
////while(1){if(5==ADCcount){ADC0_Disable();break;}}//等待采样满足5个点,就【停止AD转换】【跳出采样】。
//从0.2V-2.4V我们测试的数据表明,可以用如下公式将AD转换得到的Value换算成电压值//公式:y=0.591238914x-3.386186509
adtmp=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
ad1=0.0;
if(adtmp<240) {DrawcharS("TooSmall",1,8); }
////else if(adtmp>4094){DrawcharS("TooBig",1,8); }
else {
////ad1=(0.591238914*adtmp-3.386186509);
ad1=GNDBuChang+(0.591238914*adtmp-3.386186509);////这里因为接地电压不统一的缘故,补偿10mv。
////if(adtmp>4094){ad1=2500;};
ad1=ad1BuChang(ad1,f);/****电压**自动校准****/
drawsignedint((int)ad1,1,8);
DrawcharS("mV",1,13);
ad1=((ad1-VppPianZhiValue)/VppFangDaBeiShu);
drawsignedint((int)ad1,2,8);
DrawcharS("mV",2,13);
}
/********[end]*******/
if(0.0!=ad0 && 0.0!=ad1){
/******** 显示相位 *******/
/****cosFi=(ad0)/sqrt((ad0)*(ad0)+(ad1)*(ad1));****/
sinFi=0.0-(ad1)/sqrt((ad0)*(ad0)+(ad1)*(ad1));
////drawfloat2_2((acos(cosFi)),3,8);
////DrawcharS("Hu",3,13);
/****Du=180*(acos(cosFi))/3.1415926;****/
Du=180*(asin(sinFi))/3.1415926;
//Du=DuBuChang(Du,f);
/****drawfloat2_2(Du,3,8);****/
/****DrawcharS("Du",3,13); ****/
drawsignedfloat2_2(Du,3,8);
DrawcharS("Du",3,14);
/******** 显示参数 k *******/
/****K=(32.0*ad0*0.001/cosFi)/(a*0.001*a*0.001);****/
K=0.0-(32.0*ad1*0.001/sinFi)/(a*0.001*a*0.001);
K=10.0*log10(K);
//drawint((int)K,3,0);
drawsignedfloat2_2(K,3,0);
DrawcharS("dB",3,6);
}
else{DrawcharS("Input Error!",3,0);}
/**** 按键退出 ****/
while(1){if(7==KeyScan()||5==KeyScan()){Clear();fun_ok();break;};};
break;
case 8: AD9854_Init();
【上图:
】
redodrawpic:Clear();//该按钮完成【画频率特性图】功能
DrawcharS("Picing[Ok]toExit",0,0);
DrawcharS("[Up/6]Fi(Du)",1,0);
DrawcharS("[Down/7]K(dB)",2,0);
DrawcharS("[Right]ReSet",3,0);
cmd='4';
【总共6个选项,1,6键分别画40K-400M和6M-30M的相频曲线,2,7键分别画40K-400M和6M-30M的幅频曲线,右键运行自动校准程序,5(ok)键退出】
while(1){//画图菜单选择
if(5==KeyScan()){
cmd='5';
Clear();
fun_ok();
break;
}
else if(4==KeyScan()){
cmd='4';
Clear();
break;
}
else if(1==KeyScan()){
Clear();
DrawcharS("Du",2,14);
for(count=0;count<100;count++){
DrawPoint(5+count,32);
if(0==(count+1)%5){DrawPoint(5+count,31);DrawPoint(5+count,33);};
}
cmd='1';
break;
}
else if(2==KeyScan()){
Clear();
DrawcharS("dB",2,14);
for(count=0;count<100;count++){
DrawPoint(5+count,58);
if(0==(count+1)%5){DrawPoint(5+count,57);DrawPoint(5+count,59);};
}
cmd='2';
break;
}
else if(6==KeyScan()){
Clear();
DrawcharS("Du",2,14);
for(count=0;count<120;count++){
DrawPoint(5+count,32);
if(0==(count+1)%5){DrawPoint(5+count,31);DrawPoint(5+count,33);};
}
cmd='6';
break;
}
else if(7==KeyScan()){
Clear();
DrawcharS("dB",2,14);
for(count=0;count<120;count++){
DrawPoint(5+count,58);
if(0==(count+1)%5){DrawPoint(5+count,57);DrawPoint(5+count,59);};
}
cmd='7';
break;
}
else{cmd='5';}
};//结束画图菜单选择
/**********************************/
switch (cmd)
{//exit bit
case '1':
case '2':
【
】
/****如果没有自动校准,则功能不可使用****/
if(0==JiaoZhunBit){
Clear();
DrawcharS("No ReSeted!!!",1,1);
while(1){if(0!=KeyScan()){Clear();fun_ok();break;};};
break;
} /****结束判断****/
if('1'==cmd){drawFiPic();DrawcharS("400k-40M",0,2); }else{drawKPic();DrawcharS("400k-40M",3,2);}/****画坐标系****/
AD9854_Init();
//********
count=0;
//MinValue=0;
MaxValue=0;
/****开始循环打点****/
while(count<100){
f=400+count*400;
AD9854_SetSine(400000.0+count*400000.0,(int)(a*Vppadjust));
//这里需要一个延时函数,等待输出的正弦波稳定频率。
delaywateAD9854(5000,5);/*====延时====*/
//开始AD采样。
ADC0_Init(0,1);
ADC0_Enable();
incount=0;while(incount<5){tmp[incount]=returnADC0value();incount++;}
adtmp0=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
ADC0_Init(1,1);
ADC0_Enable();
incount=0;while(incount<5){tmp[incount]=returnADC0value();incount++;}
adtmp1=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
////DrawPoint(count,out0[count]/64);
////DrawPoint(count,out1[count]/64);
ad0=0.0;ad1=0.0;
if(adtmp0<240||adtmp1<240) {DrawcharS("L",0,13); }
////else if(adtmp0>4094||adtmp1>4070){DrawcharS("H",0,14); }
else {
ad0=adtmp0;ad1=adtmp1;
/****原本的补偿现在注释掉,因为有了现在自动校准的补偿****
//if(adtmp0>4094){ad0=2500;};
//if(adtmp1>4094){ad1=2500;};
****/
}
if(0.0!=ad0 && 0.0!=ad1)
{
ad0=GNDBuChang+(0.591238914*adtmp0-3.386186509);
ad0=ad0BuChang(ad0,f);/****电压**自动校准****/
ad0=((ad0-VppPianZhiValue)/VppFangDaBeiShu);
ad1=GNDBuChang+(0.591238914*adtmp1-3.386186509);
ad1=ad1BuChang(ad1,f);/****电压**自动校准****/
ad1=((ad1-VppPianZhiValue)/VppFangDaBeiShu);
/****cosFi=(ad0)/sqrt((ad0)*(ad0)+(ad1)*(ad1));****/
sinFi=0.0-(ad1)/sqrt((ad0)*(ad0)+(ad1)*(ad1));
/******** Drawing 相位 *******/
if('1'==cmd){
/****Du=180*(acos(cosFi))/3.1415926;****/
Du=180.0*(asin(sinFi))/3.1415926;
Value[count]=Du;
if(MaxValue<=Du){MaxValue=Du;MaxPoint=count;}
//if(MinValue>=Du){MinValue=Du;MinPoint=count;}
//DrawPoint(5+count,32);//横轴在中间,可能值为+90~-90度。
DrawPoint(5+count,32+(int)(Du/3.0));//横轴在中间,可能值为+90~-90度。
//DrawPoint(5+count,32+(int)((0.5+Du)/3.0));//解决打点时候-0.1会和0.1除出来分别为-1和0的差异。
}
/******** Drawing k *******/
if('2'==cmd){
/****K=(32.0*ad0*0.001/cosFi)/(a*0.001*a*0.001);****/
K=0.0-(32.0*ad1*0.001/sinFi)/(a*0.001*a*0.001);
K=10.0*log10(K);
Value[count]=K;
if(MaxValue<=K){MaxValue=K;MaxPoint=count;}
//if(MinValue>=K){MinValue=K;MinPoint=count;}
//DrawPoint(5+count,58);//横轴在屏幕上方。
DrawPoint(5+count,((int)(2.0*K))+58);
//DrawPoint(5+count,((int)(2.0*K))+58); //2.0表示:假设最大衰减为20db,那么20db就占了40点的高度。
}
}
else{
////DrawcharS("Error!",3,4);
DrawPoint(count,0);
}
count++;
}
/****结束循环打点****/
//********
DrawcharS("OK",3,14);
//********
while(1){if(0!=KeyScan()){break;};};//画图暂停 break跳出死循环
Clear();
if('1'==cmd){DrawcharS("400k-40M",0,2); }else{DrawcharS("400k-40M",3,2);}
drawint(400+MaxPoint*400,1,0);
//drawint(400+MinPoint*400,2,0);
DrawcharS("KHz:",1,5);
//DrawcharS("KHz:",2,5);
drawsignedfloat2_2(MaxValue,1,9);
//drawsignedfloat2_2(MinValue,2,9);
ThreeDb[0]=0;ThreeDb[1]=0;
if('2'==cmd){//如果是幅频,还要画3Db点。
for(count=0;count=(Max3dbValue-5)&&Value[count]<=(Max3dbValue-1))
{ThreeDb[0]=count;}
}
}
for(count=MaxPoint;count<100;count++){
if(Value[count]>(MaxValue-3.0)){
//if(Value[count]>=(Max3dbValue-5)&&Value[count]<=(Max3dbValue-1))
{ThreeDb[1]=count;}
}
}
drawint(400+ThreeDb[0]*400,0,0);DrawcharS("KHz",0,5);
drawint(400+ThreeDb[1]*400,0,8);DrawcharS("KHz",0,13);
}
while(1){if(0!=KeyScan()){break;};};//画图暂停 break跳出死循环
break;//break case
case '6':
case '7':
【
】
/****如果没有自动校准,则功能不可使用****/
if(0==JiaoZhunBit){
Clear();
DrawcharS("No ReSeted!!!",1,1);
while(1){if(0!=KeyScan()){Clear();fun_ok();break;};};
break;
} /****结束判断****/
if('6'==cmd){drawFiPic();DrawcharS("6M-29.8M",0,2); }else{drawKPic();DrawcharS("6M-29.8M",3,2);}/****画坐标系****/
AD9854_Init();
//********
count=0;
//MinValue=0;
MaxValue=0;
/****开始循环打点****/
while(count<120){
f=6000+count*200;
AD9854_SetSine(400000.0+count*400000.0,(int)(a*Vppadjust));
//这里需要一个延时函数,等待输出的正弦波稳定频率。
delaywateAD9854(5000,5);/*====延时====*/
//开始AD采样。
ADC0_Init(0,1);
ADC0_Enable();
incount=0;while(incount<5){tmp[incount]=returnADC0value();incount++;}
adtmp0=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
ADC0_Init(1,1);
ADC0_Enable();
incount=0;while(incount<5){tmp[incount]=returnADC0value();incount++;}
adtmp1=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
////DrawPoint(count,out0[count]/64);
////DrawPoint(count,out1[count]/64);
ad0=0.0;ad1=0.0;
if(adtmp0<240||adtmp1<240) {DrawcharS("L",0,13); }
////else if(adtmp0>4094||adtmp1>4070){DrawcharS("H",0,14); }
else {
ad0=adtmp0;ad1=adtmp1;
/****原本的补偿现在注释掉,因为有了现在自动校准的补偿****
//if(adtmp0>4094){ad0=2500;};
//if(adtmp1>4094){ad1=2500;};
****/
}
if(0.0!=ad0 && 0.0!=ad1)
{
ad0=GNDBuChang+(0.591238914*adtmp0-3.386186509);
ad0=ad0BuChang(ad0,f);/****电压**自动校准****/
ad0=((ad0-VppPianZhiValue)/VppFangDaBeiShu);
ad1=GNDBuChang+(0.591238914*adtmp1-3.386186509);
ad1=ad1BuChang(ad1,f);/****电压**自动校准****/
ad1=((ad1-VppPianZhiValue)/VppFangDaBeiShu);
/****cosFi=(ad0)/sqrt((ad0)*(ad0)+(ad1)*(ad1));****/
sinFi=0.0-(ad1)/sqrt((ad0)*(ad0)+(ad1)*(ad1));
/******** Drawing 相位 *******/
if('6'==cmd){
/****Du=180*(acos(cosFi))/3.1415926;****/
Du=180.0*(asin(sinFi))/3.1415926;
Value[count]=Du;
if(MaxValueDu){MinValue=Du;MinPoint=count;}
//DrawPoint(5+count,32);//横轴在中间,可能值为+90~-90度。
DrawPoint(5+count,32+(int)((Du-0.2)/3.0));//横轴在中间,可能值为+90~-90度。
//DrawPoint(5+count,32+(int)((0.5+Du)/3.0));//解决打点时候-0.1会和0.1除出来分别为-1和0的差异。
}
/******** Drawing k *******/
if('7'==cmd){
/****K=(32.0*ad0*0.001/cosFi)/(a*0.001*a*0.001);****/
K=0.0-(32.0*ad1*0.001/sinFi)/(a*0.001*a*0.001);
K=10.0*log10(K);
Value[count]=K;
if(MaxValue<=K){MaxValue=K;MaxPoint=count;}
////if(MinValue>=K){MinValue=K;MinPoint=count;}
//DrawPoint(5+count,58);//横轴在屏幕上方。
DrawPoint(5+count,((int)(2.0*K))+58);
//DrawPoint(5+count,((int)(2.0*K))+58); //2.0表示:假设最大衰减为20db,那么20db就占了40点的高度。
}
}
else{
////DrawcharS("Error!",3,4);
DrawPoint(count,0);
}
count++;
}
/****结束循环打点****/
//********
DrawcharS("OK",3,14);
//********
while(1){if(0!=KeyScan()){break;};};//画图暂停 break跳出死循环
Clear();
if('6'==cmd){DrawcharS("6M-29.8M",0,2); }else{DrawcharS("6M-29.8M",3,2);}
drawint(6000+MaxPoint*200,1,0);
//drawint(6000+MinPoint*200,2,0);
DrawcharS("KHz:",1,5);
//DrawcharS("KHz:",2,5);
drawsignedfloat2_2(MaxValue,1,9);
//drawsignedfloat2_2(MinValue,2,9);
ThreeDb[0]=0;ThreeDb[1]=0;
if('7'==cmd){//如果是幅频,还要画3Db点。
for(count=0;count=(Max3dbValue-5)&&Value[count]<=(Max3dbValue-1))
{ThreeDb[0]=count;}
}
}
for(count=MaxPoint;count<120;count++){
if(Value[count]>(MaxValue-3.0)){
//if(Value[count]>=(Max3dbValue-5)&&Value[count]<=(Max3dbValue-1))
{ThreeDb[1]=count;}
}
}
drawint(6000+ThreeDb[0]*200,0,0);DrawcharS("KHz",0,5);
drawint(6000+ThreeDb[1]*200,0,8);DrawcharS("KHz",0,13);
}
while(1){if(0!=KeyScan()){break;};};//画图暂停 break跳出死循环
break;//break case
case '4'://校准
【上图,自动校准的函数在这里
】
Clear();
DrawcharS("ReSeting...",1,2);
/****开始循环打点****/
count=0;
while(count<5){
/*========对应关系========
0- 5000k( 5M)
1-10000k(10M)
2-20000k(20M)
3-30000k(30M)
4-40000k(40M)
========对应关系========*/
switch(count){
case 0:f= 5000;AD9854_SetSine((unsigned long) 5000.0*1000.0,(int)(a*Vppadjust));DrawcharS("==",2,0);break;
case 1:f=10000;AD9854_SetSine((unsigned long)10000.0*1000.0,(int)(a*Vppadjust));DrawcharS("==",2,2);break;
case 2:f=20000;AD9854_SetSine((unsigned long)20000.0*1000.0,(int)(a*Vppadjust));DrawcharS("==",2,4);break;
case 3:f=30000;AD9854_SetSine((unsigned long)30000.0*1000.0,(int)(a*Vppadjust));DrawcharS("==",2,6);break;
case 4:f=40000;AD9854_SetSine((unsigned long)40000.0*1000.0,(int)(a*Vppadjust));DrawcharS("==",2,8);break;
default: break;
}
//这里需要一个延时函数,等待输出的正弦波稳定频率。
//开始AD采样。
ADC0_Init(0,1);
ADC0_Enable();
delaywateAD9854(5000,5);/*====延时====*/
incount=0;while(incount<5){tmp[incount]=returnADC0value();incount++;}
adtmp0=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
ADC0_Init(1,1);
ADC0_Enable();
delaywateAD9854(5000,2);/*====延时====*/
incount=0;while(incount<5){tmp[incount]=returnADC0value();incount++;}
adtmp1=mid5(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4]);
/****这时,adtmp0和adtmp1都是采样到的12位数据了****/
ad0=GNDBuChang+(0.591238914*adtmp0-3.386186509);
ad0bc[count]=2500.0-ad0;/****记录自动校准的数据!****//****严重注意!这里的单位是毫伏!****/
ad0=((ad0-VppPianZhiValue)/VppFangDaBeiShu);
ad1=GNDBuChang+(0.591238914*adtmp1-3.386186509);
ad1bc[count]=1250.0-ad1;/****记录自动校准的数据!****//****严重注意!这里的单位是毫伏!****/
ad1=((ad1-VppPianZhiValue)/VppFangDaBeiShu);
count++;
}
JiaoZhunBit=1;/****将自动校准位设置为“1”,这样才可以使用点频和画幅频曲线功能****/
DrawcharS("[OK]",2,11);
while(1){if(5==KeyScan()){break;};};//画图暂停 break跳出死循环
break;
case '5'://退出
break;
default:break;
}//drawExit bit
if('5'!=cmd){goto redodrawpic;}
break;
case 9: Clear();//该按钮完成【扫频】功能
mo=0;adtmp0=10;adtmp1=400;cmd=0;
resetscan:
fun_scanmsg();
while(1){//扫频菜单
if(1==KeyScan())
{
if(cmd>0){cmd--;}
fun_scanmsg();
}
else if(2==KeyScan())
{
if(cmd<2){cmd++;}
fun_scanmsg();
}
else if(3==KeyScan())
{
switch(cmd)
{
case 0:if(scanstep>1){scanstep--;}break;
case 1:if(adtmp0>10){adtmp0--;}break;
case 2:if(adtmp1>10){adtmp1--;}break;
default:break;
}
fun_scanmsg();
}
else if(4==KeyScan())
{
switch(cmd)
{
case 0:if(scanstep<=100){scanstep++;}break;
case 1:if(adtmp0<400){adtmp0++;}break;
case 2:if(adtmp1<400){adtmp1++;}break;
default:break;
}
fun_scanmsg();
}
else if(5==KeyScan()){
break;//确认参数,跳出循环
}
else{}
};//结束画图菜单选择
if(adtmp0>=adtmp1){goto resetscan;}
//********
Clear();
DrawcharS("Scaning...",0,0);
DrawcharS("[9]toExit",2,0);
//*************
drawint(a,1,2);DrawcharS("mV",1,7);
AD9854_Init();
EIE2 |= BIT0;
Timer3_Init(60000);
while(1){
if(9==KeyScan()){
EIE2 &= ~BIT0;
Clear();
fun_ok();
break;
};
};
break;
default:break;
}
}
}
【定时器的初始化和中断我们也写在这儿啦。。。】
//Timer3初始化
void Timer3_Init(unsigned int counts)
{
TMR3CN &= ~(BIT7 + BIT2 + BIT0); //清零定时器3溢出标志 暂时关闭定时器3 定时器3时钟由T3M定义
TMR3CN |= BIT1; //定时器3时钟为系统时钟
TMR3RLL = ((65536 - counts) & 0xff);
TMR3RLH = (((65536 - counts) >> 8) & 0xff); //计算定时器3重载寄存器值
TMR3L = TMR3RLL;
TMR3H = TMR3RLH; //设定计数初值
//使能定时器3中断
EA = 1;
TMR3CN |= BIT2; //启动定时器3
}
void Timer3_INT_ISR(void) interrupt 14
{
if(TMR3CN & BIT7)
{
EIE2&=~BIT1;
if(mo<=adtmp1)
//if(mo<=400)
{
Freq1=mo*100000.0;
AD9854_SetSine_inTimer3(Freq1,(int)(a*Vppadjust));
mo+=scanstep;
if(mo>adtmp1){mo=adtmp0;}
//if(mo>400){mo=10;}
}
TMR3CN &= ~BIT7;
}
EIE2|=BIT0;
}
ADDA.c函数
#include "c8051f020.h"
#include "ADDA.h"
unsigned long code SYSCLK=12000000.0;// 外部晶振时钟 12MHz;
unsigned int ADC0_Value;
unsigned int ADCcount;
【这个ADC初始化程序我比原来加了两个参数传递进来,以后用起来就方便多了】
/*** ADC0初始化*/
void ADC0_Init(bit select_AIN, bit mood)
{
//AMX0CF位0=0时表示:AIN0 和 AIN1 为独立的单端输入
AMX0CF = 0; //配置AIN0 和 AIN1单通道输入
/**** 通道选择 AMX0SL = 1 代表输入为 F020 开发板 J1 的引脚 10 (AIN_1) ****/
/**** 通道选择 AMX0SL = 0 代表输入为 F020 开发板 J1 的引脚 9 (AIN_0) ****/
AMX0SL = select_AIN;
ADC0CF = ((SYSCLK/SAR0_CLK - 1) << 3); //设置ADC转换时钟
ADC0CF &= ~(BIT2 + BIT1 + BIT0); //PGA增益为1
ADC0CN &= ~(BIT6 + BIT5 + BIT3 + BIT1 + BIT0); //当ADC被使能时,除了转换期间之外一直处于跟踪方式 //清零转换结束标志 清零窗口比较中断标志 数据右对齐
/**** AD采样方式的选择 ****/
if (1==mood)
{//向 AD0BUSY 写 1 启动 ADC0 转换。
ADC0CN &= ~BIT3;
ADC0CN &= ~BIT2;
}
else
{//定时器3溢出启动ADC0转换
ADC0CN &= ~BIT3;
ADC0CN |= BIT2;
}
REF0CN &= ~BIT4; //参考电压取自VREF0
REF0CN |= BIT1 + BIT0; //
EIE2 |= BIT1; //允许ADC转换结束中断
EA = 1;
//ADC0CN |= BIT7; //使能ADC0
ADC0_Disable();//关闭ADC0
//ADC0_Enable;//打开ADC0
}
/*** 关闭ADC0 */
void ADC0_Disable(){ADC0CN &= ~BIT7;}
/*** 打开ADC0 */
void ADC0_Enable(){ADC0CN |= BIT7;}
/*** ADC0转换结束中断入口程序 */
//void ADC0_INT_ISR(void) interrupt 15
//{
// if(AD0INT == 1){{ADC0_Value = (ADC0H << 8) + ADC0L;ADC0_Value &= 0x0fff;
// out1[ADCcount]=ADC0_Value;
// /*每次AD转换结束后,ADCcount 都自加 1 ,在外部,则对应的 unsigned int 数组 *[i] 就代表 i*100 kHz的频率时候的采样值 */
// ADCcount++;
// }AD0INT = 0;}
//}
【这个是我写的置位启动ADC转化了啦。。。直接返回采样值】
/**将当前AD采样的值返回**/
unsigned int returnADC0value()
{
ADC0CN |= BIT4;
while(1){if(AD0INT == 1){break;}}
ADC0_Value = (ADC0H << 8) + ADC0L; ADC0_Value &= 0x0fff;
AD0INT = 0;
return ADC0_Value;
}
Lcd.c中的画图函数
【这里的来那2个图片贴上来:
没错,就是左边这两个小棍棍。。。】
/*********************************************************************
*在屏幕上画一副图像
*参数:pic图像数组名 x图像宽度1~128 y图像高度1~64 row 起始行:0~3 low 起始列:0~15
*********************************************************************/
unsigned char code picFi[] = // 数据表
{
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x02,0x08,0x20,0x80,0x00,0x02,0x08,0x20,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x02,0x08,0x20,0x80,0x00,0x02,0x08,0x20,
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00
};
void drawFiPic()
{
unsigned int i,j;
for(i=0;i<8;i++){
for(j=0;j<8;j++){
LCD_setXY(i,j);
WrateD(picFi[i,i*8+j]);
};
};
}
unsigned char code picK[] = // 数据表
{
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x21,0x84,0x10,0x42,0x08,0x21,0x84,0x10,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x21,0x84,0x10,0x42,0x08,0x21,0x84,0x10,
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
void drawKPic()
{
unsigned int i,j;
for(i=0;i<8;i++){
for(j=0;j<8;j++){
LCD_setXY(i,j);
WrateD(picK[i,i*8+j]);
};
};
}
【看看我们AD9854输出正弦波的软件补偿】
AD9854.c中正弦波产生函数
//====================================================================================
//函数名称:void AD9854_SetSine(ulong Freq,uint Shape)
//函数功能:AD9854正弦波产生程序
//入口参数:Freq 频率设置,取值范围为0~(1/2)*SYSCLK
// Shape 幅度设置. 为12 Bit,取值范围为(0~4095) ,取值越大,幅度越大
//出口参数:无
//====================================================================================
void AD9854_SetSine(ulong Freq,uint Shape)//包括校准。。。
{
uchar count;
uchar Adress;
Adress = 0x04;
if( 100000<=Freq&&Freq< 1000000){ Shape=( 1.0/90000.0)*(Freq- 100000)+Shape;}
else if( 1000000<=Freq&&Freq< 5000000){ Shape=(0.005/1000.0 )*(Freq- 1000000)+Shape+ 10;}
else if( 5000000<=Freq&&Freq< 10000000){ Shape=(0.006/1000.0 )*(Freq- 5000000)+Shape+ 30;}
else if(10000000<=Freq&&Freq< 15000000){ Shape=(0.004/1000.0 )*(Freq-10000000)+Shape+ 60;}
else if(15000000<=Freq&&Freq< 20000000){ Shape=(0.007/1000.0 )*(Freq-15000000)+Shape+ 80;}
//********
else if(20000000<=Freq&&Freq< 25000000){ Shape=(0.009/1000.0 )*(Freq-20000000)+Shape+115;}
else if(25000000<=Freq&&Freq< 30000000){ Shape=(0.013/1000.0 )*(Freq-25000000)+Shape+160;}
else if(30000000<=Freq&&Freq< 35000000){ Shape=(0.016/1000.0 )*(Freq-30000000)+Shape+225;}
else if(35000000<=Freq&&Freq< 40000000){ Shape=(0.017/1000.0 )*(Freq-35000000)+Shape+305;}
else if(40000000<=Freq ){ Shape=(0.017/1000.0 )*(Freq-35000000)+Shape+305;}
Freq_convert(Freq); //频率转换
for(count=6;count>0;) //写入6字节的频率控制字
{AD9854_WR_Byte(Adress++,FreqWord[--count]); }
AD9854_WR_Byte(0x21,(Shape)>>8); //设置I通道幅度
AD9854_WR_Byte(0x22,(uchar)((Shape)&0xff));
//AD9854_WR_Byte(0x23,Shape>>8); //设置Q通道幅度
//AD9854_WR_Byte(0x24,(uchar)(Shape&0xff));
AD9854_WR_Byte(0x23,(Shape-45)>>8); //设置Q通道幅度
AD9854_WR_Byte(0x24,(uchar)((Shape-45)&0xff));
AD9854_UDCLK_H; //更新AD9854输出
AD9854_UDCLK_L;
}
//+++++++++++++++++++++++++++++++++++++++++++++
我这个人真没耐性,不愿写下去了。。。。。。
各位拜拜。。。