本函数信号发生器主要由AD9851芯片产生我们希望的正弦波,然后通过芯片内部自带的高速比较器得到方波,再将方波通过外围的积分电路得到最后的三角波。综合分析以上四种实现方法的性价比,采用DDS芯片AD9851来设计函数信号发生器。以51单片机为控制核心,一方面,对AD9851的频率相位控制字进行控制,产生所需要的正弦波形。另一方面,对液晶LCD12864进行控制,通过菜单的模式,选择所需要的频率输出方式。采用独立式键盘输入相应的操作命令,使得整个设计显得更加直观明了。
硬件电路主要由AD9851为核心的DDS模块、单片机为核心的按键LCD显示控制模块、滤波模块、供电模块、通信模块等构成。首先,通过供电模块给系统上电,然后,把编写好的程序通过通信模块下载到单片机中,最后,通过液晶和独立式键盘进行菜单式的操作,单片机对AD9851进行控制,进而输出所需要的频率。
DDS的基本原理是利用采样定理,通过查表法产生波形。DDS的结构有很多种,其基本的电路原理可用图 3 来表示。
相位累加器由N位加法器与N位累加寄存器级联构成。每来一个时钟脉冲fs,加法器将频率控制字k与累加寄存器输出的累加相位数据相加,把相加后的结果送至累加寄存器的数据输入端。累加寄存器将加法器在上一个时钟脉冲作用后所产生的新相位数据回馈到加法器的输入端,以使加法器在下一个时钟脉冲的作用下继续与频率控制字相加。这样,相位累加器在时钟作用下,不断对频率控制字进行线性相位累加。由此可以看出, 相位累加器在每一个时钟脉冲输入时,把频率控制字累加一次,相位累加器输出的数据就是合成信号的相位,相位累加器的溢出频率就是DDS输出的信号频率。用相位累加器输出的数据作为波形内存(ROM)的相位取样地址,这样就可把存储在波形内存内的波形抽样值 (二进制编码) 经查找表查出,完成相位到幅值转换。波形内存的输出送到D/A转换器,D/A转换器将数字量形式的波形幅值转换成所要求合成频率的模拟量形式信号。低通滤波器用于滤除不需要的取样分量,以便输出频谱纯净的正弦波信号。DDS在相对带宽、频率转换时间、高分辨力、相位连续性、 正交输出以及集成化等一系列性能指标方面远远超过了传统频率合成技术所能达到的水平,为系统提供了优于模拟信号源的性能。
(1)输出频率相对带宽较宽
输出频率带宽为50%fs(理论值)。但考虑到低通滤波器的特性和设计难度以及对输出信号杂散的抑制, 实际的输出频率带宽仍能达到40%fs。
(2)频率转换时间短
DDS是一个开环系统,无任何反馈环节,这种结构使得DDS的频率转换时间极短。事实上,在DDS的频率控制字改变之后,需经过一个时钟周期之后按照新的相位增量累加,才能实现频率的转换。因此,频率转换的时间等于频率控制字的传输时间,也就是一个时钟周期的时间。时钟频率越高,转换时间越短。DDS的频率转换时间可达纳秒数量级,比使用其它的频率合成方法都要短数个数量级。
(3)频率分辨率极高
若时钟fs 的频率不变,DDS的频率分辨率就由相位累加器的位数N决定。 只要增加相位累加器的位数N即可获得更小的频率分辨率。目前,大多数DDS的分辨率在1Hz数量级,许多小于1mHz甚至更小。
(4)相位变化连续
改变DDS输出频率,实际上改变的每一个时钟周期的相位增量,相位函数的曲线是连续的,只是在改变频率的瞬间其频率发生了突变,因而保持了信号相位的连续性。
(5)输出波形的灵活性
只要在DDS内部加上相应控制如调频控制FM、调相控制PM和调幅控制AM,即可以方便灵活地实现调频、调相和调幅功能,产生FSK、PSK、ASK和MSK等信号。另外,只要在DDS的波形内存存放不同波形数据,就可以实现各种波形输出, 如三角波、锯齿波和矩形波甚至是任意的波形。当DDS的波形内存分别存放正弦和余弦函数表时,既可得到正交的两路输出。
(6)其它优点
由于DDS中几乎所有部件都属于数字电路,易于集成, 功耗低、体积小、重量轻、可靠性高,且易于程控,使用相当灵活,因此性价比极高。
本系统采用了美国仿真器件公司采用先进 DDS 直接数字频率合成技术生产的高集成度产品 AD9851 芯片。AD9851 是在 AD9850 的基础上,做了一些改进以后生成的具有新功能的 DDS 芯片。AD9851 相对于 AD9850 的内部结构,只是多了一个 6 倍参考时钟倍乘器,当系统时钟为 180MHz 时,在参考时钟输入端,只需输入 30MHz 的参考时钟即可。如图 4(AD9851 内部结构)所示,AD9851 是由数据输入寄存器、频率/相位寄存器、具有 6 倍参考时钟倍乘器的 DDS 芯片、10位的模/数转换器、内部高速比较器这几个部分组成。其中具有 6 倍参考时钟倍乘器的 DDS 芯片是由 32 位相位累加器、正弦函数功能查找表、D/A 变换器以及低通滤波器集成到一起。这个高速 DDS 芯片时钟频率可达 180MHz, 输出频率可达 70 MHz,分辨率为 0.04Hz。
AD9851 可以产生一个频谱纯净、频率和相位都可编程控制且稳定性很好的模拟正弦波,这个正弦波能够直接作为基准信号源,或通过其内部高速比较器转换成标准方波输出,作为灵敏时钟发生器来使用。AD9851 的各引脚功能如下,引脚排列,如图 5 :
D0~D7:8 位数据输入口,可给内部寄存器装入 40 位控制数据。
PGND:6 倍参考时钟倍乘器地。
PVCC:6 倍参考时钟倍乘器电源。
W-CLK:字装入信号,上升沿有效。
FQ-UD:频率更新控制信号,时钟上升沿确认输入数据有效。
FREFCLOCK:外部参考时钟输入。
CMOS/TTL 脉冲序列可直接或间接地加到 6 倍参考时钟倍乘器上。在直接方式中,输入频率即是系统时钟;在 6 倍参考时钟倍乘器方式,系统时钟为倍乘器输出。
AGND:模拟地。
AVDD:模拟电源(+5V)。
DGND:数字地。
DVDD:数字电源(+5V)。
RSET、DAC:外部复位连接端。
VOUTN:内部比较器负向输出端。
VOUTP:内部比较器正向输出端。
VINN:内部比较器的负向输入端。
VINP:内部比较器的正向输入端。
DACBP:DAC 旁路连接端。
IOUTB: “互补”DAC 输出。
IOUT:内部 DAC 输出端。
图 5
RESET:复位端。低电平清除 DDS 累加器和相位延迟器为 0Hz 和 0 相位,同时置数据输入为串行模式以及禁止 6 倍参考时钟倍乘器工作。
由于 AD9851 是贴片式的体积非常小,引脚排列比较密,焊接时必须小心,还要防静电,焊接不好就很容易把芯片给烧坏。还有在使用中数据线、电源等接反或接错都很容易损坏芯片。此外,为了不受外界干扰,添加了不少的滤波电路,显得整个电路完美。
AD9851有并行和串行两种控制方式,本设计中采用并行控制方式,在并行输入方式下,通过8位总线D0~D7将外部控制字输入到寄存器,在W-CLK(字输入时钟)的上升沿装入第一个字节,并把指针指向下一个输入寄存器,连续5个W-CLK的上升沿读入5个字节数据到输入寄存器后,W-CLK的边沿就不再起作用。然后在FQ-UD(频率更新时钟)上升沿到来时将这40位数据从输入寄存器装入到频率∕相位寄存器,这时DDS输出频率和相位更新一次,同时把地址指针复位到第一个输入寄存器以等待下一次的频率∕相位控制字输入。图6即为AD9851控制字并行输入时序。
并行方式由5组8位控制字反复送入,前8位控制输出相位、6倍参考时钟倍频器、 电源休眠和输入方式,其余各位构成32位频率控制字。
图6
AD9851在本设计中的应用电路图,如图7所示:
图7
为了节约成本,本电路中采用LQFP封装44脚的单片机,该系列单片机是51单片机中增强型单片机,它体积小,工作稳定可靠,功耗低,抗干扰能力强等优点,使得本设计能顺利地完成。本电路中主要使用了该单片机的P0、P1、P2以及部分P3口,P0口主要是和液晶的8位数据口相连接,以便对液晶进行读写操作;P1口是与AD9851的8位数据口相连,对频率、相位控制字进行控制;P2口中的P2.0、P2.1、P2.2分别与液晶的控制引脚RS、R/W、E相连,其余5位是和独立式键盘S1、S2、S3、S4、S5相连接;P3口中P3.0、P3.1分别是与MAX232的9、10引脚相连,从而进行串口通信,P3.2是和AD9851中的复位引脚(22)相连,P3.6、P3.7分别与AD9851的W_CLK、FQ_UD两个控制引脚相连,另外,还有单片机的第4引脚与一些阻容组件构成系统的复位电路,以及14、15引脚与外部的无源晶振构成系统振荡电路,还有16、38引脚是与电源相连接。以上即为STC89C52的引脚在本电路中的使用分配情况。
由于本设计采用带中文字库的液晶,使得整个系统运行显得更加直观明了,它具有串行、并行两种控制方式,本设计采用8位并行接口方式。
1、引脚说明及在电路中的连接方式
管脚号 |
管脚名称 |
电平 |
管脚功能描述 |
1 |
VSS |
0V |
电源地 |
2 |
VCC |
3.0+5V |
电源正 |
3 |
V0 |
- |
对比度(亮度)调整 |
4 |
RS(CS) |
H/L |
RS=“H”,表示DB7——DB0为显示数据 RS=“L”,表示DB7——DB0为显示指令数据 |
5 |
R/W(SID) |
H/L |
R/W=“H”,E=“H”,数据被读到DB7——DB0 R/W=“L”,E=“H→L”, DB7——DB0的数据被写到IR或DR |
6 |
E(SCLK) |
H/L |
使能信号 |
7 |
DB0 |
H/L |
三态数据线 |
8 |
DB1 |
H/L |
三态数据线 |
9 |
DB2 |
H/L |
三态数据线 |
10 |
DB3 |
H/L |
三态数据线 |
11 |
DB4 |
H/L |
三态数据线 |
12 |
DB5 |
H/L |
三态数据线 |
13 |
DB6 |
H/L |
三态数据线 |
14 |
DB7 |
H/L |
三态数据线 |
15 |
PSB |
H/L |
H:8位或4位并口方式,L:串口方式(见注释1) |
16 |
NC |
- |
空脚 |
17 |
/RESET |
H/L |
复位端,低电平有效(见注释2) |
18 |
VOUT |
- |
LCD驱动电压输出端 |
19 |
A |
VDD |
背光源正端(+5V)(见注释3) |
20 |
K |
VSS |
背光源负端(见注释3) |
1、2引脚分别与电源相连接;3号引脚接电位器的中间部分;4、5、6引脚是与单片机的P2.0、P2.1、P2.2相连;由于采用该液晶的8位并行接口方式,所以7~14引脚与单片机的P0口相连,进行数据传输;16脚悬空;15、17、19接+5V电源;18引脚接电位器的一端;20脚接地。
2.模块主要硬件构成说明
控制器接口信号说明:
1、RS,R/W的配合选择决定控制接口的4种模式:
RS |
R/W |
功能说明 |
L |
L |
MPU写指令到指令缓存器(IR) |
L |
H |
读出忙标志(BF)及地址记数器(AC)的状态 |
H |
L |
MPU写入数据到数据缓存器(DR) |
H |
H |
MPU从数据缓存器(DR)中读出数据 |
2、E信号:
E状态 |
执行动作 |
结果 |
高——>低 |
I/O缓冲——>DR |
配合/W进行写数据或指令 |
高 |
DR——>I/O缓冲 |
配合R进行读数据或指令 |
低/低——>高 |
无动作 |
|
● 忙标志:BF
BF标志提供内部工作情况.BF=1表示模块在进行内部操作,此时模块不接受外部指令和数据.BF=0时,模块为准备状态,随时可接受外部指令和数据.
利用STATUS RD 指令,可以将BF读到DB7总线,从而检验模块之工作状态.
● 字型产生ROM(CGROM)
字型产生ROM(CGROM)提供8192个此触发器是用于模块屏幕显示开和关的控制。DFF=1为开显示(DISPLAY ON),DDRAM 的内容就显示在屏幕上,DFF=0为关显示(DISPLAY OFF)。
DFF 的状态是指令DISPLAY ON/OFF和RST信号控制的。
● 显示数据RAM(DDRAM)
模块内部显示数据RAM提供64×2个字节的空间,最多可控制4行16字(64个字)的中文字型显示,当写入显示数据RAM时,可分别显示CGROM与CGRAM的字型;此模块可显示三种字型,分别是半角英数字型(16*8)、CGRAM字型及CGROM的中文字型,三种字型的选择,由在DDRAM中写入的编码选择,在0000H—0006H的编码中(其代码分别是0000、0002、0004、0006共4个)将选择CGRAM的自定义字型,02H—7FH的编码中将选择半角英数字的字型,至于A1以上的编码将自动的结合下一个字节,组成两个字节的编码形成中文字型的编码BIG5(A140—D75F),GB(A1A0-F7FFH)。
● 字型产生RAM(CGRAM)
字型产生RAM提供图像定义(造字)功能, 可以提供四组16×16点的自定义图像空间,使用者可以将内部字型没有提供的图像字型自行定义到CGRAM中,便可和CGROM中的定义一样地通过DDRAM显示在屏幕中。
● 地址计数器AC
地址计数器是用来贮存DDRAM/CGRAM之一的地址,它可由设定指令缓存器来改变,之后只要读取或是写入DDRAM/CGRAM的值时,地址计数器的值就会自动加一,当RS为“0”时而R/W为“1”时,地址计数器的值会被读取到DB6——DB0中。
●光标/闪烁控制电路
此模块提供硬件光标及闪烁控制电路,由地址计数器的值来指定DDRAM中的光标或闪烁位置。
3、指令说明
模块控制芯片提供两套控制命令,基本指令和扩充指令如下:
指令表1:(RE=0:基本指令)
指 |
指 令 码 |
功 能 | |||||||||
令 |
RS |
R/W |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
清除 显示
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
将DDRAM填满"20H",并且设定DDRAM的地址计数器(AC)到"00H" |
地址 归位 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
X |
设定DDRAM的地址计数器(AC)到"00H",并且将光标移到开头原点位置;这个指令不改变DDRAM 的内容 |
显示状态开/关 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
D |
C |
B |
D=1: 整体显示 ON C=1: 游标ON B=1:光标位置反白允许 |
进入点 设定 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
I/D |
S |
指定在数据的读取与写入时,设定光标的移动方向及指定显示的移位元 |
光标或显示移位元控制 |
0 |
0 |
0 |
0 |
0 |
1 |
S/C |
R/L |
X |
X |
设定光标的移动与显示的移位元控制位;这个指令不改变DDRAM 的内容 |
功能 设定 |
0 |
0 |
0 |
0 |
1 |
DL |
X |
RE |
X |
X |
DL=0/1:4/8位数据 RE=1: 扩充指令操作 RE=0: 基本指令操作 |
设定CGRAM 地址 |
0 |
0 |
0 |
1 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
设定CGRAM 地址 |
设定DDRAM 地址 |
0 |
0 |
1 |
0 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
设定DDRAM 地址(显示位址) 第一行:80H-87H 第二行:90H-97H |
读取忙标志和地址 |
0 |
1 |
BF |
AC6 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
读取忙标志(BF)可以确认内部动作是否完成,同时可以读出地址计数器(AC)的值 |
写数据到RAM |
1 |
0 |
数据 |
将数据D7——D0写入到内部的RAM (DDRAM/CGRAM/IRAM/GRAM) | |||||||
读出RAM的值 |
1 |
1 |
数据 |
从内部RAM读取数据D7——D0 (DDRAM/CGRAM/IRAM/GRAM) |
指令表2:(RE=1:扩充指令)
指 |
指 令 码 |
功 能 | |||||||||
令 |
RS |
R/W |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
待命 模式
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
进入待命模式,执行其它指令都棵终止待命模式 |
卷动地址开关开启 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
SR |
SR=1:允许输入垂直卷动地址 SR=0:允许输入IRAM和CGRAM地址 |
反白 选择 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
R1 |
R0 |
选择2行中的任一行作反白显示,并可决定反白与否。初始值R1R0=00,第一次设定为反白显示,再次设定变回正常 |
睡眠 模式 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
SL |
X |
X |
SL=0:进入睡眠模式 SL=1:脱离睡眠模式 |
扩充 功能 设定 |
0 |
0 |
0 |
0 |
1 |
CL |
X |
RE |
G |
0 |
CL=0/1:4/8位数据 RE=1: 扩充指令操作 RE=0: 基本指令操作 G=1/0:绘图开关 |
设定绘图RAM 地址 |
0 |
0 |
1 |
0 AC6 |
0 AC5 |
0 AC4 |
AC3 AC3 |
AC2 AC2 |
AC1 AC1 |
AC0 AC0 |
设定绘图RAM 先设定垂直(列)地址AC6AC5…AC0 再设定水平(行)地址AC3AC2AC1AC0 将以上16位地址连续写入即可 |
备注:当IC1在接受指令前,微处理器必须先确认其内部处于非忙碌状态,即读取BF标志时,BF需为零,方可接受新的指令;如果在送出一个指令前并不检查BF标志,那么在前一个指令和这个指令中间必须延长一段较长的时间,即是等待前一个指令确实执行完成。
3、读写时序图
3.1 数据传输过程
8位和4位数据线的传输过程
3.2 时序图
单片机向液晶写命令的时序(8位数据线模式)
单片机从液晶中读数据的时序(8位数据线模式)
由于直接从AD9851输出端输出的波形为阶梯波,波形不够平滑,因此,本设计中需要在输出端设置一个截止频率为25MHz的低通滤波器。在AD公司AD9851的数据手册上提供了一个截止频率为70MHz的椭圆低通滤波器,其电路图如图2-4所示。
图2-4
在该电路图上运用反归一化的方法进行更改就可以得到所需的电路,可以省却进行查表计算的麻烦。该滤波器的3dB截止频率为f1=70MHz,与要求的3dB截止频率f0 =25MHz相比,频率标定系数FSF为
FSF=f0/f1=25/70=0.36
将70MHz截止频率的滤波器的电感、电容值同时除以FSF,即可得到25MHz截止频率的椭圆低通滤波器,如图2-4所示。25MHz椭圆低通滤波器的组件值为
L1=470nH/FSF=470nHx2.8=1.32uH
L2=390nH/FSF=390nHX2.8=1.09uH
L3=390nH/FSF=390nH*2.8=1.09uH
C1=22pF/FSF=22pFX2.8=61.6pF
C2=1pF/FSF=1pFPFX2.8=2.8PF
C3=33PF/FSF=33PFX2.8=92.4PF
C4=5.6PF/FSF=5.6PFX2.8=15.68PF
C5=22PF/FSF=22PFX2.8=13.16PF
C6=4.7PF/FSF=4.7PFX2.8=13.94PF
C7=22PF/FSF=22PFX2.8=61.6PF
该滤波器对组件值要求不高,可使用10%误差的电感和5%电容即可。将上述元器件取为标称值,则
Ll=1.5uH;L2=1.2uH;L3=1.2uH;
Cl=56pF;C2=2.7pF;C3=100PF;C4=16PF;C5=13PF;C6=14PF;C7=56PF。
在电路中并没有自带+5V稳压电源模块,为了减小线路板的面积,节约制作成本,因此,用USB代替系统供电,这样不仅可以减少线路板的使用面积,而且USB供电也比较稳定,所受干扰也比较小。另外,电路中还留出了+5V电源的接口,这样可以方便其它+5V电源的接入。电路如下图所示:
由于所用的单片机为LQFP封装,所以在下载程序的时候,本电路中使用了串口下载,因为计算机上的电平为232电平,而本电路中所用的是TTL电平,所以在进行通信时需要一电平转换电路,电路中使用MAX232芯片及其电容构成一个转换电路,如下图所示:
本章主要针对于硬件电路的设计,通过各个子模块来阐述硬件电路的原理。采用DDS技术的AD9851芯片是本电路的核心,通过与单片机的数据传输进行频率的合成,产生正弦波形。经测定该电路整体性能良好,工作稳定且操作方便,电路中使用了液晶显示模块,操作界面非常友好,例如从液晶上面可以很清晰地看到输出频率的三种模式(定频模式、扫频模式、调频模式),通过独立式键盘选择一种模式便可输出相应的频率。整个硬件电路结构简单,焊接美观,能够实现基本的功能。
该信号发生器主要有三点不足,一、所有的输入、输出接口都是采用的排针,使得连接不方便;二、AD9851输出端采用的椭圆低通滤波器,滤波的效果不明显;三、输出波形的幅度随着频率的变化而变化,输出幅度不稳定。针对于以上的不足日后还要加以改善,例如把波形输出端的排针换成圆形插孔形式的,便于与示波器连接,外接5V电源端也可以换成圆形插孔,使得与电源的连接更加稳固;此外,还可以在输出端加上由AD603构成的自动幅度控制,再加上检波电路,使得输出波形的幅度更加趋于稳定。
关于程序的设计,采用模块化的思想,例如程序中的定频模块、扫频模块、跳频模块等这几个都是单独写在一个函数中,然后依次在另一个函数中调用,模块化的设计思想主要有可移植性强,易于整个程序修改等特点。本程序设计步骤主要分为四大块,一是,对液晶的初始化;二是,键盘扫描,如有效按键按下时程序便调用相应的子程序;三是,主程序调用各个函数,实现一个整体;四是定时器T0、T1中断函数;整个系统的程序流程图,如图3-1所示:
![]() |
![]() |
![]() |
N N N
![]() |
![]() |
![]() |
Y Y Y
![]() |
![]() |
![]() |
图3-1
关于AD9851程序的编写,主要从它的初始复位函数以及发送频率控制字函数去写,编写的时候要严格对照它的时序,否则就会出现错误。以下即为AD9851的实用程序:
AD9851初始复位子函数,如下所示:
void DDS_Rest()
{
DDS_WK=0;
DDS_FD=0;
DDS_RT=1;
_nop_();
_nop_();
DDS_RT=0;
}
这个函数被下面发送控制字函数调用;
void Parallel_AD9851()
{
DDS_Data=Control_AD9851;_nop_();_nop_();_nop_();_nop_();//延时很重要,对时序
DDS_WK=1;//字装入信号,上升沿有效
DDS_WK=0;
DDS_Data=W1;_nop_();_nop_();_nop_();_nop_();_nop_();
DDS_WK=1;//字装入信号,上升沿有效
DDS_WK=0;
DDS_Data=W2;_nop_();_nop_();_nop_();_nop_();_nop_();
DDS_WK=1;//字装入信号,上升沿有效
DDS_WK=0;
DDS_Data=W3;_nop_();_nop_();_nop_();_nop_();_nop_();
DDS_WK=1;//字装入信号,上升沿有效
DDS_WK=0;
DDS_Data=W4;_nop_();_nop_();_nop_();_nop_();_nop_();
DDS_WK=1;//字装入信号,上升沿有效
DDS_WK=0;
DDS_FD=1;
DDS_FD=0;
}
单片机向AD9851发送控制字程序:
void Set_Freq(float Freqency)
{
DDS_Freq= (ulong)(23.86115*Freqency); // SYSCLK = 180 MHz
// DDS_Freq = (unsigned long)(23.86092942*Freqency);由于float数据类型的有效位为7位
W4=(uchar)DDS_Freq&0xff;
DDS_Freq=DDS_Freq>>8;
W3=(uchar)DDS_Freq&0xff;
DDS_Freq=DDS_Freq>>8;
W2=(uchar)DDS_Freq&0xff;
DDS_Freq=DDS_Freq>>8;
W1=(uchar)DDS_Freq&0xff;
Parallel_AD9851();
}
关于液晶的操作,在编写程序时也要严格按照数据手册上给出的时序,写它的每一个子模块,下面即为液晶在整个系统中用到的所有子程序:
#define LCD_Data P0 //液晶数据端口
#define Busy 0x80
sbit LCD_E=P2^2; //液晶12864的位定义
sbit LCD_RW=P2^1;
sbit LCD_RS=P2^0;
void Delay1ms(int t) //1毫秒延时子函数
{
int i,j;
for(i=0;i<t;i++)
for(j=0;j<120;j++);
}
//读状态
uchar ReadStatusLCD(void)
{
LCD_Data = 0xFF;
LCD_RS = 0;
LCD_RW = 1;
LCD_E = 1;
while (LCD_Data & Busy); //检测忙信号
LCD_E = 0;
return(LCD_Data);
}
//写数据
void WriteDataLCD(uchar WDLCD)
{
ReadStatusLCD(); //检测忙
LCD_RS = 1;
LCD_RW = 0;
LCD_Data = WDLCD;
LCD_E = 1;
_nop_();
_nop_();
LCD_E = 0;
}
//写指令
void WriteCommandLCD(uchar WCLCD,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCD(); //根据需要检测忙
LCD_RS = 0;
LCD_RW = 0;
LCD_Data = WCLCD;
LCD_E = 1;
_nop_();
_nop_();
LCD_E = 0;
}
//读数据
uchar ReadDataLCD(void)
{
LCD_RS = 1;
LCD_RW = 1;
LCD_E = 0;
_nop_();
_nop_();
LCD_E = 1;
return(LCD_Data);
}
void LCDInit(void) //LCM初始化
{
WriteCommandLCD(0x30,1); //显示模式(基本指令)设置,开始要求每次检测忙信号
WriteCommandLCD(0x01,1); //显示清屏
WriteCommandLCD(0x06,1); // 显示光标移动设置,游标右移
WriteCommandLCD(0x0C,1); // 显示开及光标设置,游标关,反白关
}
void LCDClear(void) //清屏
{
WriteCommandLCD(0x01,1); //显示清屏
WriteCommandLCD(0x34,1); // 显示光标移动设置
WriteCommandLCD(0x30,1); // 显示开及光标设置
}
//按指定位置显示一串字符
void DisplayListChar(uchar X, uchar Y, uchar code *DData)
{
uchar ListLength,X2;
ListLength = 0;
X2=X;
if(Y<1)
Y=1;
if(Y>4)
Y=4;
X &= 0x0F; //限制X不能大于16,Y在1-4之内
switch(Y)
{
case 1:X2|=0X80;break; //根据行数来选择相应地址
case 2:X2|=0X90;break;
case 3:X2|=0X88;break;
case 4:X2|=0X98;break;
}
WriteCommandLCD(X2, 1); //发送地址码
while (DData[ListLength]>=0x20) //若到达字串尾则退出
{
if (X <= 0x0F) //X坐标应小于0xF
{
WriteDataLCD(DData[ListLength]);
ListLength++;
X++;
Delay1ms(5);
}
}
}
//图形显示
void DisplayImage(uchar code *DData)
{
unsigned char x,y,i;
unsigned int;
for(i=0;i<9;i+=8) //分两屏,上半屏和下半屏,因为起始地址不同,需要分开
{
for(x=0;x<32;x++) //32行
{
WriteCommandLCD(0x34,1);
WriteCommandLCD((0x80+x),1);
WriteCommandLCD((0x80+i),1); //行地址,上、下半屏,即第一行0X80、第三行地址0X88
WriteCommandLCD(0x30,1);
for(y=0;y<16;y++)
WriteDataLCD(*DData++); //读取数据写入LCD
}
}
WriteCommandLCD(0x36,1); //扩充功能设定
WriteCommandLCD(0x30,1);
}
void LCDFlash(void) //闪烁效果
{
WriteCommandLCD(0x08,1); //显示清屏
Delay1ms(600);
WriteCommandLCD(0x0c,1); // 显示开及光标设置
Delay1ms(600);
WriteCommandLCD(0x08,1); //显示清屏
Delay1ms(600);
WriteCommandLCD(0x0c,1); // 显示开及光标设置
Delay1ms(600);
WriteCommandLCD(0x08,1); //显示清屏
Delay1ms(600);
}
主程序中集成了初始化部分、键盘扫描部分以及对各个函数的调用,以下即为整个主程序部分:
void main()
{
init();
while(1)
{
if(SF==0)
DDS_JM();// 见附录二
if(SDK==0)
{
if(D_FS==1)
Set_Freq(D_Freq);
if(D_FS==0)
Set_Freq(0);
}
if(ST==1)
{
if(sn1>=1)
Sn=sn1;
else
{
WriteCommandLCD(0x85,1);
Sn=1000;
}
if(s1==0)
{
Delay1ms(2);
if(s1==0)
{
TR0=0;SF=0;ST=0;
while(!s1);
}
}
}
if(TT==1)
{
if(s1==0)
{
Delay1ms(2);
if(s1==0)
{
TR1=0;SF=0;TT=0;
while(!s1);
}
}
}
}
}
中断函数部分主要包括定时器T0、T1中断,这两个函数分别用于扫频和跳频中,下面附上两个中断函数。
T0中断,按照所设定的时间进行中断,连续向AD9851发送频率控制字,产生扫频现象;
void time0() interrupt 1
{
TH0=(65536-Sn)/256;
TL0=(65536-Sn)%256;
S_Freq+=S_bjz2;
if(S_Freq>S_L)
{
S_Freq=S_F;
}
Set_Freq(S_Freq);
if(s1==0)
{
Delay1ms(2);
if(s1==0)
{
TR0=0;SF=0;ST=0;
while(!s1);
}
}
}
T1中断,类似于T0中断,它主要产生跳频现象;
void time1() interrupt 3
{
TH1=(65536-T_bjz2)/256;
TL1=(65536-T_bjz2)%256;
T_Freq=(T_Freq+T_bjz1)*5;
if(T_Freq>20000000)
T_Freq=1000;
Set_Freq(T_Freq);
T_Freq=(T_Freq-4)*8;
if(T_Freq>20000000)
T_Freq=0;
if(s1==0)
{
Delay1ms(2);
if(s1==0)
{
TR1=0;SF=0;TT=0;
while(!s1);
}
}
}
程序的设计主要从三方面编写,一、液晶的显示程序;二、AD9851驱动程序及显示程序;三、主程序以及中断函数的编写;本程序中对于显示程序部分的编写,能够合理地分配变量,充分利用液晶的界面显示资源,并且能很好地把按键与显示变量衔接起来,使得操作更加人性化、简单化。
程序的编写,大体上结构比较清晰,每个子程序都是独立的模块,通过程序间相互调用使之连接起来,不足之处在于子程序的格式比较繁琐,虽然能实现电路的基本功能,但程序运行效率低。可通过把每个子程序建立成C文件的格式,然后通过主程序调用,这样便可提高系统的性能。
实物的使用主要是通过按键进行操作的,本电路中共设置了5个独立式键盘,分别为S1(功能键)、S2(上切键)、S3(下切键)、S4(加号键)、S5(减号键)。
程序下载之后,给系统上电,液晶上面便显示三种模式状态,分别为定频模式、扫频模式、跳频模式,光标默认在定频模式上闪烁,可通过S2、S3进行上下选择,当光标停留在哪个位置时,按下功能键S1即可进入相应的模式。另外,在每个模式界面上都设有上下模式选择按钮,默认情况下,光标都在上模式按钮上闪烁,此时,可通过S2、S3来选择光标闪烁的位置。
1、定频模式
所谓定频模式,就是在输出频率范围内设定任意一个频率值,即可输出相应的频率;在定频模式中主要有步进值的设定和输出频率的设定,在对输出频率设定时,可先设定一下步进值,这样有助于快速设定相应频率值的大小;例如设定一个1.5MHz的频率,在初始界面下,先通过S2选择光标到设定步进值的位置,然后通过S4选择步进值为1MHz,再把光标跳到设定频率的位置,按下S4把频率加到1MHz,按下S3把光标返回到设定步进值的位置,按下S5把步进值减小为100KHz,按下S2再次把光标跳到设定频率的位置,按下 S4继续增加所设定的频率值,一直加到1.5MHz,最后按下功能键S1,即可输出相应的频率。
2、扫频模式
所谓扫频模式,就是在设定的初始、终止频率范围内,按照所设定的时间和增量循环输出相应的频率;在扫频模式中,主要设有初始频率、终止频率以及扫描时间,除了这些还有步进值和扫频增量的设定,由于液晶界面大小有限,所以把这两个放在另一个界面上,在扫频初始界面上有一个中间按钮,可通过这个中间按钮进入次界面,操作的方法是当光标在这个按钮上闪烁时,按下S1即可进入,返回时也是采用这种方法,对于扫频界面上的设定和定频界面上设定的方法一样,可先设定步进值和扫频增量,然后再设定初始频率和终止频率,最后设置一下扫描时间,并按下S1即可进行扫频。
3、跳频模式
所谓跳频,就是在一定的输出频率范围内,按照一定的方式,输出不同的频率;在跳频界面上,设有跳频增量和跳频时间间隔,其对应的操作和上面的一样,最后在设定跳频间隔时,按下S1即可进行跳频输出。
注:在扫频和跳频模式中,最后按下S1后,其他按键就被屏蔽了,再次按下S1时即可恢复,与此同时,扫频与跳频也就终止了。在定频模式中没有,只有切换到其他模式时,结束定频输出。
实物整体结构图,如图4—2—1所示:
图4—2—1
举例说明,定频模式下界面的显示如图4—2—2所示:
图4—2—2
设计完成之后,就进行测试与验证,下面主要对波形的频率范围,输出电压的峰峰值指标,信号频率误差等进行测试与验证。
该电路输出的频率范围为0到25MHz,经验证频率输出范围符合要求。图5-1为25MHz时的正弦波形。
图5-1
正弦波输出电压的峰峰值随着频率的增高,幅度有所衰减,例如图5-2与图5-3之间,幅度明显有差别。
![]() | |||
![]() | |||
图5-2 图5-3
在本电路中通过内部自带的比较器,产生的方波经过测试,在低频段输出波形较好如图5-4所示;如果频率低于100Hz时,由于示波器的原因,波形有点变形,如图5-5所示;但大于3MHz时输出频率开始失真如图5-6所示。由于AD9851内部比较器的增益比较高,使得输出方波的幅度比正弦波高很多,如下面几幅图所示,为此,在输出端通过增加幅度控制单元,便可降幅。
![]() |
![]() | ||
图5-4 图5-5
![]() |
图5-6
频率的输出误差经测试与统计,在100KHz以下测得的频率与设置频率的偏差小于5Hz,在100KHz到700KHz之间,偏差小于30Hz,800KHz到1MHz之间,偏差在30到90Hz之间,输出频率1MHz以上偏差保持在100Hz左右。在波形方面,三角波和方波输出频率比较低,频率越高失真越严重。为此,还要进一步改善。
经过分析,该电路性能稳定,输出误差在允许范围之内,另外,在扫频与跳频上,也能满足设计要求,美中不足的是输出波形缺乏幅度增益控制,日后还得进一步完
原理图:
PCB图:
1、变量定义
uchar Control_AD9851=0x01;
volatile ulong idata DDS_Freq,D_Freq=1000,S_Freq,T_Freq;
volatile ulong idata D_bjz;//定频步进值变量
volatile ulong idata S_bjz1=1,S_bjz2=10,S_bjz3=1,S_bjz3_1=1000;//扫频中 设置步进值 扫频增量 扫描时间
volatile ulong idata S_F=10,S_L=1000;//扫频初 终变量
volatile ulong idata SC_F,sc_f1;
volatile ulong idata T_bjz1=1,T_bjz2=1;
idata uint Sn,sn1;
uchar W1;
uchar W2;
uchar W3;
uchar W4;
uchar SDK,D_FS,ST,SF,TS,TT;
uchar MX=1,JM_1=1;
uchar DM,JM_2=1;
uchar SM,SM_1,JM_3=1,JM_5=1;
uchar TM,JM_4=1;
char M_num;
char D_num,D_num2;
char S_num,S_num1,S_num2,S_num3,S_num4;
char T_num,T_num1,T_num2;
sbit DDS_RT=P3^2;
sbit DDS_WK=P3^6;
sbit DDS_FD=P3^7;
sbit s1=P2^3;
sbit s2=P2^4;
sbit s3=P2^5;
sbit s4=P2^6;
sbit s5=P2^7;
2、数组定义
code uchar KJHM_1[]="电子专071-郑井尚";
code uchar KJHM_2[]="毕业设计";
code uchar KJHM_3[]=" DDS信号发生器";
code uchar KJHM_4[]="指导老师: 查老师";
code uchar MSXZ_1[]="模式选择: ";
code uchar MSXZ_2[]="1.定频模式";
code uchar MSXZ_3[]="2.扫频模式";
code uchar MSXZ_4[]="3.跳频模式";
code uchar DPMS_1[]="定频模式";
code uchar DPMS_2[]="步进值:0000001Hz";
code uchar DPMS_3[]="设定频率: ";
code uchar DPMS_4[]="00001000Hz";
code uchar SPMS_1[]="扫频模式";
code uchar SPMS_2[]="起频: 00000010Hz";
code uchar SPMS_3[]="终频: 00001000Hz";
code uchar SPMS_4[]="扫描时间:00001ms";
code uchar SPMS_5[]="步进值设定: ";
code uchar SPMS_5_1[]="0000001Hz";
code uchar SPMS_6[]="扫频增量设定: ";
code uchar SPMS_6_1[]="0000010Hz";
code uchar TPMS_1[]="跳频模式";
code uchar TPMS_2[]="频率宽度: 20MHz ";
code uchar TPMS_3[]="跳频增量:00001Hz";
code uchar TPMS_4[]="跳频间隔:00001us";
3、初始化程序
void init()
{
LCDInit();
DisplayListChar(0,1,KJHM_1);
DisplayListChar(2,2,KJHM_2);
DisplayListChar(0,3,KJHM_3);
DisplayListChar(0,4,KJHM_4);
Delay1ms(2000);
LCDFlash();
LCDClear();
DDS_Rest();
EA=1;ET0=1;ET1=1;TMOD=0x11;//TR0=1;
TH0=(65536-10)/256;
TL0=(65536-10)%256;
TH1=(65536-1)/256;
TL1=(65536-1)%256;
}
void DDS_Change(uchar add,ulong date)
{
ulong aa,aa1,bb,bb1,cc,cc1,dd,dd1,ee,ee1,ff,ff1,gg,hh;
aa=date/10000000;
aa1=date%10000000;
bb=aa1/1000000;
bb1=aa1%1000000;
cc=bb1/100000;
cc1=bb1%100000;
dd=cc1/10000;
dd1=cc1%10000;
ee=dd1/1000;
ee1=dd1%1000;
ff=ee1/100;
ff1=ee1%100;
gg=ff1/10;
hh=ff1%10;
WriteCommandLCD(add,1);
WriteDataLCD(0x30+aa);
WriteDataLCD(0x30+bb);
WriteDataLCD(0x30+cc);
WriteDataLCD(0x30+dd);
WriteDataLCD(0x30+ee);
WriteDataLCD(0x30+ff);
WriteDataLCD(0x30+gg);
WriteDataLCD(0x30+hh);
WriteDataLCD(0x48);
WriteDataLCD(0x7A);
WriteCommandLCD(add,1);
}
void DDS_BjzChange(uchar add,ulong date)
{
ulong aa,aa1,bb,bb1,cc,cc1,dd,dd1,ee,ee1,ff,gg;
aa=date/1000000;
aa1=date%1000000;
bb=aa1/100000;
bb1=aa1%100000;
cc=bb1/10000;
cc1=bb1%10000;
dd=cc1/1000;
dd1=cc1%1000;
ee=dd1/100;
ee1=dd1%100;
ff=ee1/10;
gg=ee1%10;
WriteCommandLCD(add,1);
WriteDataLCD(0x3A);
WriteDataLCD(0x30+aa);
WriteDataLCD(0x30+bb);
WriteDataLCD(0x30+cc);
WriteDataLCD(0x30+dd);
WriteDataLCD(0x30+ee);
WriteDataLCD(0x30+ff);
WriteDataLCD(0x30+gg);
WriteDataLCD(0x48);
WriteDataLCD(0x7A);
WriteCommandLCD(add,1);
}
void DDS_BjzChange_T(uchar add,ulong date)
{
ulong aa,aa1,bb,bb1,cc,cc1,dd,ee;
aa=date/10000;
aa1=date%10000;
bb=aa1/1000;
bb1=aa1%1000;
cc=bb1/100;
cc1=bb1%100;
dd=cc1/10;
ee=cc1%10;
WriteCommandLCD(add,1);
WriteDataLCD(0x3A);
WriteDataLCD(0x30+aa);
WriteDataLCD(0x30+bb);
WriteDataLCD(0x30+cc);
WriteDataLCD(0x30+dd);
WriteDataLCD(0x30+ee);
WriteDataLCD(0x6D);
WriteDataLCD(0x73);
WriteCommandLCD(add,1);
}
void DDS_TBjzChange(uchar add,ulong date)
{
ulong aa,aa1,bb,bb1,cc,cc1,dd,ee;
aa=date/10000;
aa1=date%10000;
bb=aa1/1000;
bb1=aa1%1000;
cc=bb1/100;
cc1=bb1%100;
dd=cc1/10;
ee=cc1%10;
WriteCommandLCD(add,1);
WriteDataLCD(0x3A);
WriteDataLCD(0x30+aa);
WriteDataLCD(0x30+bb);
WriteDataLCD(0x30+cc);
WriteDataLCD(0x30+dd);
WriteDataLCD(0x30+ee);
WriteDataLCD(0x48);
WriteDataLCD(0x7A);
WriteCommandLCD(add,1);
}
void DDS_TBjzChange_T(uchar add,ulong date)
{
ulong aa,aa1,bb,bb1,cc,cc1,dd,ee;
aa=date/10000;
aa1=date%10000;
bb=aa1/1000;
bb1=aa1%1000;
cc=bb1/100;
cc1=bb1%100;
dd=cc1/10;
ee=cc1%10;
WriteCommandLCD(add,1);
WriteDataLCD(0x3A);
WriteDataLCD(0x30+aa);
WriteDataLCD(0x30+bb);
WriteDataLCD(0x30+cc);
WriteDataLCD(0x30+dd);
WriteDataLCD(0x30+ee);
WriteDataLCD(0x75);
WriteDataLCD(0x73);
WriteCommandLCD(add,1);
}
void DDS_BjzChange_1(uchar add,ulong date)
{
ulong aa,aa1,bb,bb1,cc,cc1,dd,dd1,ee,ee1,ff,gg;
aa=date/1000000;
aa1=date%1000000;
bb=aa1/100000;
bb1=aa1%100000;
cc=bb1/10000;
cc1=bb1%10000;
dd=cc1/1000;
dd1=cc1%1000;
ee=dd1/100;
ee1=dd1%100;
ff=ee1/10;
gg=ee1%10;
WriteCommandLCD(add,1);
WriteDataLCD(0x30+aa);
WriteDataLCD(0x30+bb);
WriteDataLCD(0x30+cc);
WriteDataLCD(0x30+dd);
WriteDataLCD(0x30+ee);
WriteDataLCD(0x30+ff);
WriteDataLCD(0x30+gg);
WriteDataLCD(0x48);
WriteDataLCD(0x7A);
WriteCommandLCD(add,1);
}
/******定频模式选择界面函数******/
void DP_JM()
{
if(JM_2==1)
{
WriteCommandLCD(0x01,1);
DisplayListChar(0,1,DPMS_1);
DisplayListChar(0,2,DPMS_2);
DisplayListChar(0,3,DPMS_3);
DisplayListChar(0,4,DPMS_4);
WriteCommandLCD(0x86,1);
WriteDataLCD(0x1E);
WriteCommandLCD(0x87,1);
WriteDataLCD(0x1F);
WriteCommandLCD(0x0F,1);
SDK=0;
}
JM_2++;
if(JM_2>=2)
{
JM_2=2;
}
if(s2==0)
{
Delay1ms(4);
if(s2==0)
{
D_num++;
while(!s2);
if(D_num==4)
D_num=0;
}
}
if(s3==0)
{
Delay1ms(4);
if(s3==0)
{
D_num--;
while(!s3);
if(D_num==-1)
D_num=3;
}
}
if(D_num==0)
{
WriteCommandLCD(0x86,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
D_FS=0;
while(!s1);
MX=1;DM=0;SM=0;TM=0;JM_1=1;
M_num=0;
}
}
}
if(D_num==1)
{
WriteCommandLCD(0x87,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
D_FS=0;
while(!s1);
WriteCommandLCD(0x01,1);
MX=0;DM=0;SM=1;TM=0;JM_3=1;
S_num=0;
}
}
}
if(D_num==2)
{
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
D_num2++;
while(!s4);
if(D_num2==7)
D_num2=0;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
D_num2--;
while(!s5);
if(D_num2==-1)
D_num2=6;
}
}
if(D_num2==0)
{
D_bjz=1;
}
if(D_num2==1)
{
D_bjz=10;
}
if(D_num2==2)
{
D_bjz=100;
}
if(D_num2==3)
{
D_bjz=1000;
}
if(D_num2==4)
{
D_bjz=10000;
}
if(D_num2==5)
{
D_bjz=100000;
}
if(D_num2==6)
{
D_bjz=1000000;
}
if(D_bjz==0)
D_bjz=1000000;
DDS_BjzChange(0x93,D_bjz);
}
if(D_num==3)
{
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
while(!s4);
D_Freq=D_Freq+D_bjz;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
while(!s5);
D_Freq=D_Freq-D_bjz;
}
}
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
D_FS=1;
}
}
DDS_Change(0x98,D_Freq);
}
}
/******扫频模式选择界面函数******/
void SP_JM()
{
if(JM_3==1)
{
WriteCommandLCD(0x01,1);
DisplayListChar(0,1,SPMS_1);
DisplayListChar(0,2,SPMS_2);
DisplayListChar(0,3,SPMS_3);
DisplayListChar(0,4,SPMS_4);
WriteCommandLCD(0x85,1);
WriteDataLCD(0x12);
WriteCommandLCD(0x86,1);
WriteDataLCD(0x1E);
WriteCommandLCD(0x87,1);
WriteDataLCD(0x1F);
WriteCommandLCD(0x0F,1);
}
JM_3++;
if(JM_3>=2)
JM_3=2;
if(s2==0)
{
Delay1ms(4);
if(s2==0)
{
S_num++;
while(!s2);
if(S_num==6)
S_num=0;
}
}
if(s3==0)
{
Delay1ms(4);
if(s3==0)
{
S_num--;
while(!s3);
if(S_num==-1)
S_num=5;
}
}
if(S_num==0)
{
WriteCommandLCD(0x86,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
MX=0;DM=1;SM=0;TM=0;JM_2=1;
D_num=0;SDK=0;
}
}
}
if(S_num==1)
{
WriteCommandLCD(0x87,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
MX=0;DM=0;SM=0;TM=1;JM_4=1;
T_num=0;SDK=0;
}
}
}
if(S_num==2)
{
WriteCommandLCD(0x85,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
SM=0;SM_1=1;JM_5=1;
}
}
}
if(S_num==3)
{
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
while(!s4);
S_F=S_F+S_bjz1;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
while(!s5);
S_F=S_F-S_bjz1;
}
}
if(S_F<=0)
S_F=9999999;
DDS_Change(0x93,S_F);
}
if(S_num==4)
{
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
while(!s4);
S_L=S_L+S_bjz1;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
while(!s5);
S_L=S_L-S_bjz1;
}
}
if(S_L<=0)
S_L=9999999;
DDS_Change(0x8B,S_L);
}
if(S_num==5)
{
WriteCommandLCD(0x9C,1);
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
while(!s4);
S_num4++;
if(S_num4==5)
S_num4=0;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
while(!s5);
S_num4--;
if(S_num4==-1)
S_num4=4;
}
}
if(S_num4==0)
S_bjz3=1;
if(S_num4==1)
S_bjz3=10;
if(S_num4==2)
S_bjz3=100;
if(S_num4==3)
S_bjz3=1000;
if(S_num4==4)
S_bjz3=10000;
if(S_bjz3==0)
S_bjz3=10000;
S_bjz3_1=S_bjz3*1000;
DDS_BjzChange_T(0x9C,S_bjz3);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
S_Freq=S_F;
SC_F=S_L-S_F;
sc_f1=SC_F/S_bjz2;
sn1=S_bjz3_1/sc_f1;
while(!s1);
ST=1;TR0=1;SF=1;
SDK=1;
}
}
}
}
/******扫频增量界面函数******/
void SPZ_JM()
{
if(JM_5==1)
{
WriteCommandLCD(0x01,1);
DisplayListChar(0,1,SPMS_5);
DisplayListChar(0,2,SPMS_5_1);
DisplayListChar(0,3,SPMS_6);
DisplayListChar(0,4,SPMS_6_1);
WriteCommandLCD(0x87,1);
WriteDataLCD(0x12);
WriteCommandLCD(0x0F,1);
}
JM_5++;
if(JM_5>=2)
JM_5=2;
if(s2==0)
{
Delay1ms(4);
if(s2==0)
{
S_num1++;
while(!s2);
if(S_num1==3)
S_num1=0;
}
}
if(s3==0)
{
Delay1ms(4);
if(s3==0)
{
S_num1--;
while(!s3);
if(S_num1==-1)
S_num1=2;
}
}
if(S_num1==0)
{
WriteCommandLCD(0x87,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
SM_1=0;SM=1;JM_3=1;
WriteCommandLCD(0x0C,1);
}
}
}
if(S_num1==1)
{
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
S_num2++;
while(!s4);
if(S_num2==7)
S_num2=0;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
S_num2--;
while(!s5);
if(S_num2==-1)
S_num2=6;
}
}
if(S_num2==0)
{
S_bjz1=1;
}
if(S_num2==1)
{
S_bjz1=10;
}
if(S_num2==2)
{
S_bjz1=100;
}
if(S_num2==3)
{
S_bjz1=1000;
}
if(S_num2==4)
{
S_bjz1=10000;
}
if(S_num2==5)
{
S_bjz1=100000;
}
if(S_num2==6)
{
S_bjz1=1000000;
}
if(S_bjz1==0)
S_bjz1=1000000;
DDS_BjzChange_1(0x90,S_bjz1);
}
if(S_num1==2)
{
WriteCommandLCD(0x98,1);
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
S_num3++;
while(!s4);
if(S_num3==6)
S_num3=0;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
S_num3--;
while(!s5);
if(S_num3==-1)
S_num3=5;
}
}
if(S_num3==0)
{
S_bjz2=10;
}
if(S_num3==1)
{
S_bjz2=100;
}
if(S_num3==2)
{
S_bjz2=1000;
}
if(S_num3==3)
{
S_bjz2=10000;
}
if(S_num3==4)
{
S_bjz2=100000;
}
if(S_num3==5)
{
S_bjz2=1000000;
}
if(S_bjz2==0)
S_bjz2=1000000;
DDS_BjzChange_1(0x98,S_bjz2);
}
}
/******跳频模式选择界面函数******/
void TP_JM()
{
if(JM_4==1)
{
WriteCommandLCD(0x01,1);
DisplayListChar(0,1,TPMS_1);
DisplayListChar(0,2,TPMS_2);
DisplayListChar(0,3,TPMS_3);
DisplayListChar(0,4,TPMS_4);
WriteCommandLCD(0x86,1);
WriteDataLCD(0x1E);
WriteCommandLCD(0x87,1);
WriteDataLCD(0x1F);
WriteCommandLCD(0x0F,1);
}
JM_4++;
if(JM_4>=2)
JM_4=2;
if(s2==0)
{
Delay1ms(4);
if(s2==0)
{
T_num++;
while(!s2);
if(T_num==4)
T_num=0;
}
}
if(s3==0)
{
Delay1ms(4);
if(s3==0)
{
T_num--;
while(!s3);
if(T_num==-1)
T_num=3;
}
}
if(T_num==0)
{
WriteCommandLCD(0x86,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
MX=0;DM=0;SM=1;TM=0;JM_3=1;
S_num=0;SDK=0;
}
}
}
if(T_num==1)
{
WriteCommandLCD(0x87,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
MX=1;DM=0;SM=0;TM=0;JM_1=1;
M_num=0;SDK=0;
}
}
}
if(T_num==2)
{
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
T_num1++;
while(!s4);
if(T_num1==5)
T_num1=0;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
T_num1--;
while(!s5);
if(T_num1==0)
T_num1=3;
}
}
if(T_num1==0)
T_bjz1=1;
if(T_num1==1)
T_bjz1=10;
if(T_num1==2)
T_bjz1=100;
if(T_num1==3)
T_bjz1=1000;
if(T_num1==4)
T_bjz1=10000;
if(T_bjz1==0)
T_bjz1=10000;
DDS_TBjzChange(0x8C,T_bjz1);
}
if(T_num==3)
{
if(s4==0)
{
Delay1ms(4);
if(s4==0)
{
T_num2++;
while(!s4);
if(T_num2==5)
T_num2=0;
}
}
if(s5==0)
{
Delay1ms(4);
if(s5==0)
{
T_num2--;
while(!s5);
if(T_num2==0)
T_num2=4;
}
}
if(T_num2==0)
T_bjz2=1;
if(T_num2==1)
T_bjz2=10;
if(T_num2==2)
T_bjz2=100;
if(T_num2==3)
T_bjz2=1000;
if(T_num2==4)
T_bjz2=10000;
if(T_bjz2==0)
T_bjz2=10000;
DDS_TBjzChange_T(0x9C,T_bjz2);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
while(!s1);
TR1=1;SF=1;TT=1;SDK=1;
}
}
}
}
void DDS_JM()
{
/******主模式选择界面函数******/
if(MX==1)
{
Delay1ms(4);
if(JM_1==1)
{
WriteCommandLCD(0x01,1);
DisplayListChar(0,1,MSXZ_1);
DisplayListChar(0,2,MSXZ_2);
DisplayListChar(0,3,MSXZ_3);
DisplayListChar(0,4,MSXZ_4);
}
JM_1++;
if(JM_1>=2)
{
JM_1=2;
}
if(s2==0)
{
Delay1ms(4);
if(s2==0)
{
M_num++;
while(!s2);
if(M_num==3)
M_num=0;
}
}
if(s3==0)
{
Delay1ms(4);
if(s3==0)
{
M_num--;
while(!s3);
if(M_num==-1)
M_num=2;
}
}
if(M_num==0)
{
WriteCommandLCD(0x90,1);
WriteCommandLCD(0x0F,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
MX=0;DM=1;JM_2=1;
while(!s1);
WriteCommandLCD(0x0C,1);
}
}
}
if(M_num==1)
{
WriteCommandLCD(0x88,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
MX=0;SM=1;JM_3=1;
while(!s1);
WriteCommandLCD(0x0C,1);
}
}
}
if(M_num==2)
{
WriteCommandLCD(0x98,1);
if(s1==0)
{
Delay1ms(4);
if(s1==0)
{
MX=0;TM=1;JM_4=1;
while(!s1);
WriteCommandLCD(0x0C,1);
}
}
}
}
/******定频模式选择界面******/
if(DM==1)
{
Delay1ms(4);
DP_JM();
}
/******扫频模式选择界面******/
if(SM==1)
{
Delay1ms(4);
SP_JM();
}
/******扫频增量界面******/
if(SM_1==1)
{
Delay1ms(4);
SPZ_JM();
}
/******扫频增量界面******/
if(TM==1)
{
Delay1ms(4);
TP_JM();
}
}
用户1834705 2015-4-13 11:11