ORG 0000H
AJMP START
ORG 0040H
START:
MOV SP,#60H
MOV
A,#00H
MOV DPTR,#4000H 锯齿波缓冲区首址
NEXT:
MOVX @DPTR,A
填锯齿波数据
INC DPTR
INC A
JZNEXT1
写完256个数据后退出
AJMP NEXT
NEXT1:
MOV A,#00H
MOV
R0,#00H
MOV DPTR,#4100H 三角波缓冲区首址
NEXT2:
MOVX @DPTR,A
填三角波数据(上升部分)
INC DPTR
ADD A,#02H
INC R0
CJNE
R0,#80H,NEXT2
SUBB A,#02H
CLR C
NEXT3:
MOVX
@DPTR,A 填三角波数据(下升部分)
INC DPTR
SUBB A,#02H
INC
R0
CJNE R0,#00H,NEXT3写完256个数据后退出
--------------SIN
WAVE------------------
MOV R0,#10H
MOV R1,#00H
MOV
DPTR,#STEP 步长的浮点ASCII起始地址
READ:
MOV A,R1
MOVC
A,@A+DPTR
MOV @R0,A
INC R1
INC R0
CJNE
R1,#0AH,READ 将程序区的数据移到内部RAM区
MOV R0,#10H 十进制浮点数的首址
MOV
R1,#30H 三字节浮点数的首址(步长)
LCALL %FDTB3
带符号十进制数ASCII码浮点数
转换成三字节浮点数
MOV R2,#00H
MOV R3,#80H
电压的最大值
MOV R0,#18H 三字节浮点数的首址(最大电压)
LCALL %WTF31
双字节无符号数转换成
三字节浮点数
MOV R3,#00H STEP LENGTH
MOV
DPTR,#4200H 正弦波数据表首址
CALCSIN:
PUSH 3
PUSH DPH
PUSH
DPL
MOV R2,#00H
MOV R0,#38H FLOAT STEP ADDRESS
LCALL %WTF31 双字节无符号数转换成
三字节浮点数
MOV R0,#30H
MOV
R1,#38H
LCALL %FMUL3 三字节浮点数乘法子程序
MOV 40H,R4 MUL
ADDRESS
MOV 41H,R2
MOV 42H,R3
MOV R0,#40H
MOV R1,#48H SIN VALUE ADDRESS
LCALL %FSIN3
三字节浮点数正弦子程序
MOV R0,#18H
MOV R1,#48H
LCALL
%FMUL3 三字节浮点数乘法子程序
MOV 38H,R4 MUL ADDRESS
MOV
39H,R2
MOV 3AH,R3
MOV R0,#38H
LCALL %FTW3
三字节浮点数转换成
双字节无符号数
POP DPL
POP DPH
MOV
A,#80H
ADD A,R3
JNZ SIN90判断峰值
MOV
A,0FFH
SIN90:
MOVX @DPTR,A 把计算值填表
MOV A,DPL
ORL A,#80H 计算sin(a+180)
MOV DPL,A
MOV A,#80H
CLR C
SUBB A,R3
MOVX @DPTR,A 把计算值填表
MOV
A,DPL
ANL A,#7FH
MOV DPL,A
INC DPTR
POP
3
INC R3
CJNE R3,#80H,CALCSIN
判断计算完毕
波形显示程序
WAVE:
MOV R1,#00H
WAVE1:
MOV
DPTR,#4000H 显示锯齿波(256次)
LCALL D_A
DJNZ
R1,WAVE1
WAVE2:
MOV DPTR,#4100H 显示三角波(256次)
LCALL
D_A
DJNZ R1,WAVE2
WAVE3:
MOV DPTR,#4200H
显示正弦波(256次)
LCALL D_A
DJNZ R1,WAVE3
SJMP WAVE
循环显示
D_A:
MOV R0,#00H 置计数器
LOOP:
MOVX
A,@DPTR 查波形表
PUSH DPL
PUSH DPH
MOV
DPTR,#D_APORT
MOVX @DPTR,A 启动 D/A
POP DPH
POP
DPL
INC DPTR改变表格地址
INC R0
CJNE
R0,#00H,LOOP判断是否显示完
RET
步长的十进制ASCII码浮点数
STEP DB
30H,2EH,30H,32H,34H,35H,34H,34H,2CH'0.024544,'
END
#include<reg52.h> //包含头文件#include<intrins.h>
#define uchar unsigned char //宏定义
#define uint unsigned int
sbit s1=P3^5 //定义按键的接口
sbit s2=P3^6
sbit s3=P3^7
sbit s4=P3^4
sbit s5=P2^3
sbit led0=P3^0 //定义四个LED,分别表示不同的波形
sbit led1=P3^1
sbit led2=P3^2
sbit led3=P3^3
sbit lcdrs=P2^7 //液晶控制引脚,还有一个控制脚是RW,因为我们只需要向液晶里写数据系那是就好了,所以,我们直接将RW引脚接地
sbit lcden=P2^6
char num,boxing,u //定义全局变量
uchar pinlv=100,bujin=1,bujin1=1//频率初始值是10Hz,步进值默认是0.1,显示步进值变量
uchar code table[]="0123456789" //定义显示的数组
uchar code table1[]="Fout= Wave form:"//初始化显示字符
unsigned int m,pwm=50 //定义变量 m
int a,b,h,num1 //定义全局变量
//自定义字符
uchar code zifu[]={ //此数组内数据为液晶上显示波形符号的自定义字符
0x0e,0x11,0x11,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x11,0x11,0x0e,0x00, //正弦波0 1
0x00,0x07,0x04,0x04,0x04,0x04,0x1c,0x00,
0x00,0x1c,0x04,0x04,0x04,0x04,0x07,0x00, //矩形波2 3
0x00,0x01,0x02,0x04,0x08,0x10,0x00,0x00,
0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00, //三角波4 5
0x00,0x01,0x03,0x05,0x09,0x11,0x00,0x00, //锯齿波6
}
uchar code sin[64]={//此数组内的数据为,da输出对应电压值对应的数字量,0是0V,255是5V
135,145,158,167,176,188,199,209,218,226,234,240,245,249,252,254,254,253,251,247,243,237,230,222,213,204,193,182,170,158,
146,133,121,108,96,84,72,61,50,41,32,24,17,11,7,3,1,0,0,2,5,9,14,20,28,36,45,55,66,78,90,102,114,128
} //正弦波取码
uchar code juxing[64]={ //一个周期是采样64个点, 所以数组内是64个数据
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
} //矩形波取码
uchar code sanjiao[64]={
0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,
248,240,232,224,216,208,200,192,184,176,168,160,152,144,136,128,120,112,104,96,88,80,72,64,56,48,40,32,24,16,8,0
} //三角波取码
uchar code juchi[64]={
0,4,8,12,16,20,24,28,32,36,40,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125,130,134,138,142,
146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,215,219,223,227,231,235,239,243,247,251,255
} //锯齿波取码
void delay(uint xms) //延时函数
{
int a,b
for(a=xmsa>0a--)
for(b=110b>0b--)
}
void write_com(uchar com) //写命令函数
{
lcdrs=0
P0=com
delay(1)
lcden=0
delay(1)
lcden=1
}
void write_date(uchar date) //写数据函数
{
lcdrs=0
P0=date
delay(1)
lcden=0
delay(1)
lcden=1
}
//自定义字符集
void Lcd_ram()
{
uint i,j,k=0,temp=0x04
for(i=0i<7i++)
{
for(j=0j<8j++)
{
write_com(temp+j)
write_date(zifu[k])
k++
}
temp=temp+8
}
}
void init_lcd() //初始化函数
{
uchar i
lcden=0//默认开始状态为关使能端,见时序图
Lcd_ram()
write_com(0x01) //显示清屏,将上次的内容清除,默认为0x01.
write_com(0x0f)
write_com(0x38) //显示模式设置,默认为0x38,不用变。
write_com(0x0c) //显示功能设置0x0f为开显示,显示光标,光标闪烁;0x0c为开显示,不显光标,光标不闪
write_com(0x06) //设置光标状态默认0x06,为读一个字符光标加1.
write_com(0x80) //设置初始化数据指针,是在读指令的 *** 作里进行的
for(i=10i<20i++) //显示初始化
{
write_date(table1[i])//显示第一行字符
}
write_com(0x80+40) //选择第二行
for(i=0i<9i++)
{
write_date(table1[i])//显示第二行字符
}
write_com(0x80+10) //选择第一行第十个位置
write_date(0)
write_date(1)
write_date(0)
write_date(1)
write_date(0)
write_date(1) //显示自定义的波形图案
write_com(0x80+40+9)//选择第二行第九个位置
write_date(' ')
write_date('1')
write_date('0')
write_date('.')
write_date('0')
write_date('H')
write_date('z') //显示初始的频率值
}
void initclock() //定时器初始化函数
{
TMOD=0x01 //定时器的工作方式
TH0=a
TL0=b //定时器赋初值
EA=1 //打开中断总开关
ET0=1 //打开定时器允许中断开关
TR0=1 //打开定时器定时开关
}
void display() //显示函数
{
uchar qian,bai,shi,ge //定义变量用于显示
qian=pinlv/1000//将频率值拆成一位的数据,将数据除以1000,得到的商是一位数,赋值给qian
bai=pinlv%1000/100//将频率除以1000的余数再除以100就得到了频率的百位,赋值给bai
shi=pinlv%1000%100/10 //同上,得到频率的十位
ge=pinlv%1000/100%10
write_com(0x80+40+9)//选中第二行第九个位置
if(qian==0) //千位如果为0
write_date(' ')//不显示
else//千位不为0
write_date(table[qian]) //正常显示千位
if(qian==0&&bai==0) //千位和百位都为0
write_date(' ')//百位不显示
else//不都为0
write_date(table[bai]) //百位正常显示
write_date(table[shi]) //显示十位数
write_date('.')//显示小数点
write_date(table[ge]) //显示个位
write_date('H')//显示频率的单位Hz
write_date('z')
if(boxing==0) //判断波形为正弦波
{
write_com(0x80+10) //选中一行频率图案位置
write_date(0)//显示正弦波图案
write_date(1)
write_date(0)
write_date(1)
write_date(0)
write_date(1)
led3=1
led0=0//点亮正弦波指示灯
}
if(boxing==1)//注释同上
{
write_com(0x80+10)
write_date(2)
write_date(3)
write_date(2)
write_date(3)
write_date(2)
write_date(3)
led0=1
led1=0
}
if(boxing==2)
{
write_com(0x80+10)
write_date(4)
write_date(5)
write_date(4)
write_date(5)
write_date(4)
write_date(5)
led1=1
led2=0
}
if(boxing==3)
{
write_com(0x80+10)
write_date(6)
write_date(6)
write_date(6)
write_date(6)
write_date(6)
write_date(6)
led2=1
led3=0
}
}
void keyscan() //频率调节键盘检测函数
{
if(s1==0) //加按键是否按下
{
EA=0//关闭中断
while(!s1) //按键松开
pinlv+=bujin //频率以步进值加
if(pinlv>1000) //最大加到100Hz
{
pinlv=100 //100Hz
}
display() //显示函数
m=65536-(15000/pinlv)//计算频率
/*频率值最小是10Hz,pinlv的值是100(因为要显示小数点后一位),150000/100=1500,这个1500就是定时器需要计时的,单位是us,65536-1500得到的是定时器的初值,
先不管初值,先看定时时间,1500us,一个波形的周期是由64个定时组成的,所以,一个波形周期就是64*1500us=96000,也就是96ms,约等
于100ms,也就是10Hz的频率*/
a=m/256 //将定时器的初值赋值给变量
b=m%256
EA=1 //打开中断总开关
}
if(s2==0) //减按键按下
{
EA=0
while(!s2)
pinlv-=bujin//频率以步进值减
if(pinlv<100)
{
pinlv=100
}
display()
m=65536-(15000/pinlv)
a=m/256
b=m%256
EA=1
}
if(s3==0) //波形切换按键
{
EA=0
while(!s3)
boxing++ //波形切换
if(boxing>=4) //4种波形
{
boxing=0
}
display()
EA=1
}
if(s5==0) //PWM切换按键
{
EA=0
while(!s5)
pwm+=10
if(pwm>90)
{
pwm=10
}
// display()
EA=1
}
}
void bujindisplay() //步进值设置界面显示程序
{
uint bai,shi,ge //定义步进值 百十个位
bai=bujin1/100//将步进值除以100得到百位,也就是频率值的十位,因为有一个小数位
shi=bujin1%100/10 //将步进值除以100的余数除以十得到十位
ge=bujin1%100%10 //取余10后得到个位,也就是频率步进值的小数点后一位
write_com(0x80+11) //选中液晶第一行第十一列
if(bai==0) //百位是否为0
write_date(' ') //百位不显示
else //百位不为0
write_date(table[bai]) //显示百位数据
write_date(table[shi]) //显示十位数据
write_date('.') //显示小数点
write_date(table[ge]) //显示个位,也就是小数点后一位
}
void bujinjiance() //步进值设置键盘程序
{
if(s4==0) //步进设置按键按下
{
delay(5)//延时去抖
if(s4==0) //再次判断按键
{
while(!s4) //按键释放,按键松开才继续向下执行
h++//变量加
if(h==1)//进入设置状态时
{
write_com(0x01)//清屏
write_com(0x80)//初始化显示步进设置界面
write_date('S')delay(1) //step value
write_date('t')delay(1)
write_date('e')delay(1)
write_date('p')delay(1)
write_date(' ')delay(1)
write_date('v')delay(1)
write_date('a')delay(1)
write_date('l')delay(1)
write_date('u')delay(1)
write_date('e')delay(1)
write_date(':')delay(1)
bujin1=bujin //步进值赋值给临时变量
bujindisplay()//显示步进值
}
if(h==2)//退出设置
{
h=0 //清零
bujin=bujin1 //设置好的临时步进值赋值给步进变量
init_lcd() //初始化液晶显示
initclock() //定时器初始化
display() //调用显示程序
}
}
}
if(h==1) //设置步进值时
{
if(s1==0) //加按键按下
{
delay(5) //延时去抖
if(s1==0)//再次判断
{
while(!s1) //按键释放
bujin1++ //步进值加1
if(bujin1>=101) //步进值最大100,也就是10.0Hz
{
bujin1=1 //超过最大值就恢复到0.1Hz
}
bujindisplay() //步进显示
}
}
if(s2==0) //减按键,注释同上
{
delay(5)
if(s2==0)
{
while(!s2)
bujin1-- //步进减
if(bujin1<=0)
{
bujin1=100
}
bujindisplay()
}
}
}
}
void main() //主函数
{
init_lcd()//调用初始化程序
m=65536-(15000/pinlv) //定时器初值
a=m/256
b=m%256
initclock() //定时器初始化
led0=0 //点亮第一个波形指示灯
while(1) //进入while循环,括号内为1,一直成立,所以也叫死循环,程序不会跳出,一直在内执行
{
if(h==0)//正常模式不是步进调节
{
keyscan() //扫描按键
// display()
}
bujinjiance() //扫描步进调节程序
switch(boxing) //选择波形
{
case 0 : P1=sin[u]break //正弦波
case 1 : //矩形波
if(u<pwm*64/100)P1=255
else
P1=0
break
case 2 : P1=sanjiao[u]break //三角波
case 3 : P1=juchi[u]break //锯齿波
}
}
}
void T0_time()interrupt 1 //定时器
{
TH0=a
TL0=b
u++//变量加
if(u>=64)//一个周期采样64个点, 所以加到64就清零
u=0//u清零
//根据不同的初值,定时器定时时间不同,达到不同频率的目的
}
1.2.1 课题背景随着科学技术的迅速发展,数字化技术已渗透到各个领域。智能仪表装置由于其安全、方便、高效、快捷、智能化等特点,使它在21世纪成为各种科学技术领域和工程实践的助手。它对于改善现代人类的生活质量,创造、安全、便利的生活空间有着非常重要的意义。随着电子技术的发展 , 数字化技术在智能仪表 ,外设控制等方面取得了广泛的运用。其中幅值、波形和频率可调的智能信号发生器经常要用在各种科学技术领域和工程实践中。函数信号发生器和示波器、电压表、频率计等仪器一样是最普通、最基本的 ,也是应用最广泛的电子仪器之一 ,几乎所有的电参量的测量都需要用到信号发生器 。频率越高、产生的波形种类越多的发生器性能越好,但器件的成本和技术要求也大大提高。比如:利用专用直接数字合成DDS芯片实现信号发生器。这种信号发生器能产生任意波形并达到很高的频率,但成本很高。因此,综合成本和性能等多方面考虑,设计出一款单片集成芯片配合52单片机实现的智能信号发生器是一次非常有意义的尝试。该种智能信号发生器能产生多种波形信号,达到较高的频率,易于调试,且有很高的性价比。怎么样才能设计出一款内部功能齐全,外围电路简单,使用方便的智能信号发生器呢?这就需要用到集成信号发生芯片。随着半导体芯片制造业的迅速发展和研制水平的飞速提高,出现了很多功能强大且性能可靠的集成信号发生芯片 ,几乎代替了以前用分立元件搭成的信号发生电路模块。精密函数发生芯片MAX038就是其中之一,而且在众多的信号发生芯片中MAX038 芯片的性价比较高 。所以本设计选用精密函数发生芯片MAX038。本设计中,用户可根据自己的需要,将要输出的波形种类通过外置键盘输入单片机,调用其相应的子程序,再通过与MAX038相连的可变电阻来调节波形的频率和占空比,经MAX038输出到放大电路,最后接到示波器,由示波器显示产生的波形。这种信号源的频率改变十分方便 ,而且线路简单,调试和修理简捷,性能价格比较高。1.2.2 技术指标本文设计的智能信号发生器的技术指标如下:(1)可以输出正弦波、矩形波及三角波;(2)输出方波的占空比可调范围在10%~90%;(3)输出信号的频率稳定度和准确度: ;(4)正弦波非线性失真度 :小于1%;(5)频率可调范围:0.1HZ~20MHZ;(6)幅度:6V为了达到这一目标,本课题重点在以下几个方面展开工作:(1)信号发生器的基本原理及相关技术的研究学习本课题工作初期主要阅读了大量相关书籍,特别是MAX038芯片的资料,还深入研究了信号发生器的基本原理、技术特点等。在这些工作的基础上,提出了系统的解决方案,并解决了其中的关键技术难题。(2)硬件系统设计 硬件电路设计主要包括键盘电路、单片机外围电路、MAX038外围电路(占空比调节、频率调整电路)、放大电路的设计。根据系统方案的要求,ATMEL公司的8位Flash 单片机AT89C52作为系统的控制核心及数据处理中心,接距阵式键盘和MAX038电路部分。 (3)软件系统设计软件系统主要包括键盘去抖动延时程序、键盘扫描程序、波形选择程序。软件编程用C51语言。第二章 系统方案及原理框图2.1 系统方案设计MAX038是单片集成芯片,需要通过单片机的控制实现函数信号的波形选择。波形选择由两个输入引脚A0 和A1的逻辑电平设定。通过4*4键盘输入要产生的波形的种类,单片机判断键码并通过两个I/O口控制MAX038的A0和A1引脚,从而控制MAX038输出相应的波形。关于占空比调节和频率调整,为简单起见,可采用外部电位器调整控制。2.2 系统工作原理及框图从图2-1可以看出,系统按功能模块可分为几个部分:单片机系统:控制外围的信号发生芯片,完成波形选择。外围电路:实现外围的信号发生芯片和单片机之间的接口电路。C51程序:编写单片机外围信号发生芯片的接口程序,实现单片机函数信号输出功能。AT89C52单片机
4*4键盘
波形选择
占空比调节节
MAX038
频率调整
放大电路
波形输出
图2-1 系统原理框图工作过程为:打开电源开始工作,按复位键复位,在键盘上输入所需波形,调用单片机的程序存储器中其相应的子程序 ,再通过与MAX038相连的可变电阻来调节波形的频率和占空比,经MAX038输出到放大电路,最后接到示波器,由示波器显示产生的波形。第三章 硬件电路设计本章将介绍信号发生器的电路设计原理,对各个功能模块分别进行讨论,主要包括键盘电路、单片机外围电路、MAX038外围电路(占空比调节、频率调整电路)、放大电路。3.1 键盘电路行列式键盘也即矩阵式键盘,它由行和列组成,在每个行列的交叉点上放置一个按键。4*4键盘是一种常见的键盘,用在本设计中完全能够满足要求。4*4行列式键盘共由16个键盘组成。图3-1是键盘电路图。矩阵键盘原理:矩阵键盘中,一个按键按下后会触发两个电平信号:X、Y,单片机通过扫描X、Y的值判断按键状态。
把单片机AT89C52中的P1.0-P1.7端口用8芯排线连接到“4*4行列式键盘”区域中的L1-L4、C1-C4端口上。图3-1 键盘电路3.2 单片机外围电路设计MAX038是单片集成芯片,需要通过单片机的控制实现函数信号的波形选择。单片机是核心器件之一,通过它对MAX038的设置,实现不同波形的选择和输出。由于系统控制方案不太复杂 ,数据量也不太大,我们选用 AT89C52 作为控制系统的核心。它极为常用,价格便宜,易于获取。3.2.1 单片机外围电路硬件部分AT89C52是美国Atmel公司生产的低电压、高性能CMOS 8位单片机,片内含8KB的可
图 3-2 AT89C52管脚图反复檫写的程序存储器和12B的随机存取数据存储器(RAM),器件采用Atmel公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内配置通用8位中央处理器(CPU)和Flash存储单元,功能强大的AT89C52单片机可灵活应用于各种控制领域。AT89C52单片机属于AT89C51单片机的增强型,与Intel公司的80C52在引脚排列、硬件组成、工作特点和指令系统等方面兼容。图 3-2 是AT89C52的管脚图。其主要工作特性是:片内程序存储器内含8KB的Flash程序存储器,可擦写寿命为1000次;片内数据存储器内含256字节的RAM;具有32根可编程I/O口线;具有3个可编程定时器;中断系统是具有8个中断源、6个中断矢量、2个级优先权的中断结构;串行口是具有一个全双工的可编程串行通信口;具有一个数据指针DPTR;低功耗工作模式有空闲模式和掉电模式具有可编程的3级程序锁定位;AT89C52工作电源电压为5(1+0.2)V,且典型值为5V;AT89C52最高工作频率为24MHz。单片机正常工作时,都需要有一个时钟电路和一个复位电路,来构成单片机的最小电路。如图3-3所示。
(1) 时钟电路
XTAL0(18脚)和XTAL1(19脚):计算机工作时,是在统一的时钟脉冲控制下一拍一拍的进行的,这个脉冲是由单片机控制器中的时序电路发出的。单片机的时序就是CPU在执行指令时所需控制信号的时间顺序。为了保证各部件间的同步工作。单片机内部电路就在唯一的时钟信号控制下严格地按时序进行工作。要给单片机提供时序要有相关的硬件电路,即振荡器和时钟电路。因此选择了内部时钟方式。利用芯片内部的振荡器,然后在引脚XTAL0和XTAL1两端跨接晶体或陶瓷谐振器,就构成了稳定的自激振荡器,其发出的脉冲直接送入内部时钟电路,AT89C52最高工作频率为24MHz,在本设计中采用11.0592 MHz晶振。外接晶振时,C1和C2值通常选择为22PF左右。C1,C2对频率有微调作用。晶体的频率范围可在1.2~12MHZ之间选择。在实际连接中,为了减少寄生电容,更好地保证振荡器稳定、可靠地工作,振荡器和电容应尽可能安装得与单片机芯片靠近。
(2) 复位电路
RESET( 9脚)是复位, 由图3-3可以看出,按键电平复位电路相当于按复位键S1后复位端通过电阻与Vcc电源接通。复位是单片机的初始化 *** 作。单片机在启动运行时,都需要先复位,其作用是使CPU和系统中其他部件都处于一个确定的初始状态,并从这个状态开始工作。因而,复位是一个很重要的 *** 作方式。但单片机本身是不能自动进行复位的,必须配合相应的外部电路来实现。(3) 单片机电源(40脚)是电源:AT89C52工作电源电压为5(1+0.2)V,且典型值为5V;在线路中,电源去藕是一个关键问题。整个线路往往会由于电源引线而产生电路谐振,当有大的瞬时变化时,也会产生尖峰干扰信号。消除这两种现象的有效办法就是在片子的电源管脚与地之间加上适当的去藕电容,如图3-3中的C4。(4) P1、P2口P1口:是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作为输入口。作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。在图3-3中,KEY为单片机的外围4*4键盘接口,它和单片机的P1.0~P1.7连接,P1.0~P1.3对应于键盘的行1~4,P1.4~P1.7对应键盘的列1~4。P2口:P2是一个带有内部上拉电阻的8位双向I/O口,P2的输出缓冲极可驱(吸收或输出电流)4个TTL逻辑门电路。Flash编程或校验时,P2也接收高位地址和一些控制信号。在本设计中,单片机的P2.0和P2.1脚和MAX038的A0和A1相连,用于选择输出波形种类。
图3-3 单片机部分硬件电路
3.2.2 单片机外围仿真电路部分仿真软件:Proteus7.1A0=0或者1、A1=1,即键盘第一行第一列的情况。表示选择的是正弦波。A0=0、A1=0,即键盘第一行第二列的情况,表示选择的是矩形波;A0=1、A1=0,即键盘第一行第三列,表示选择三角波输出。D1(A0)D2(A1)选择的波形暗(0)或者亮(1)亮(1)正弦波暗(0)暗(0)矩形波亮(1)暗(0)三角波表3-1单片机部分仿真结果图3-4仿真的是A0=0、A1=1,即键盘第一行第一列。表示选择的是正弦波的情况。图3-4 单片机部分软件仿真电路3.3 MAX038外围电路设计3.3.1 MAX038的基本工作原理MAX038是美国Maxim公司的一款高频率、高精度、低输出电阻、驱动能力强的函数信号发生器芯片,它是新一代的单片函数信号发生芯片。MAX038内部含有精密带隙电压基准、鉴相器和TTL同步输出,能以最少的外部元件构成波形高频函数信号发生器,也可以应用于压控振荡器(PPL)、脉宽调制器、锁相环、频率调制器、频率合成器及FSK信号(正弦波和方波)发生器,是目前较为理想的信号发生集成芯片 。如图3-5所示MAX038内部主要由振荡器、参考电压源2.5V、 恒流源250UA发生电路、多路选择开关 、比较器、相位监测器、输出缓冲器等电路组成。MAX038是单片精密函数信号产生器 ,它用±5V电源工作 ,基本的振荡器是一个交变地以恒定电流向电容器充电和放电的驰张振荡器 ,同时产生一个三角波和矩形波。通过改变COSC引
脚的外接电容 和流入 引脚的充放电电流的大小来控制输出信号频率, 工作频率范围为0.1Hz~20MHz。 流入 引脚的电流由加到FADJ 和DADJ 引脚上的电压来调制, 通过这两个引脚可用外接电压信号分别调整频率和占空比。MAX038内部有一个正弦波形成电路把振荡器的三角波转变成一个具有等幅的低失真度正弦波。三角波、正弦波和矩形波输入一个多路器,两根地址线A0和A1从这三个波形中选出一个。图3-5 MAX038的内部结构(虚线框内)
MAX038内部有一个2.5V的基准电压源,由REF引脚输出。基准电压源电路由两个运放LF353及电阻、电容组成,分别组成放大倍数为+1和-1的缓冲器,因而得到 的基准电源。这个电压源对整机的性能很重要,因为各控制电路均需要参考输入。图3-6 MAX038管脚图鉴相器是作为锁相环的备用单元,为异或门电路结构,输入信号一路来自内部差动矩形波OSCA和OSCB,另一路来自外部引脚PD1。鉴相器输出信号为电流,由PD0引脚输出,平均值变化范围为0~550 。当两路输入信号的相位差为 时,输出电流的占空比为50%,平均值为250 。如果构成锁相环电路,则PDO和FADJ相连,并且对地连接一个电阻 ,同时并联一个电容 。 决定鉴相器的灵敏度, 则滤除电流中的高频成分。MAX038的各引脚功能见于表3-2。
表3-2 MAX038引脚功能注:5个GND脚在MAX038内部是不连接的,在电路设计时,需要一个地平面,然后所有5个GND脚连到靠近MAX038器件的地平面上。表3-3是MAX038 地址线A0和A1对波形选择的取值。
表3-3 MAX038 地址线A0和A1对波形选择的取值波形选择由A0和A1两个输入引脚的逻辑电平设定:当A0=0或1、A1=1时为正弦波;当A0=0、A1=0时输出矩形波;当A0=1、A1=0时输出三角波。MAX038的关键特性如下:(1)工作频率范围从 0.1HZ~ 20MHZ,各种波形的输出幅度均为2 V(P-P);(2)能精密地产生三角波、方波、正弦波信号;(3)占空比调节范围宽, 占空比和频率均可单独调节, 互不影响, 占空比最大调节范围10%~90%;(4)波形失真小, 正弦波失真度低于1%;(5) 采用±5V双电源供电, 允许有5%变化范围,电源电流为 80mA , 典型功耗 400 mW, 工作温度范围为0~70℃;(6) 内设2.5V电压基准,利用控制端FADJ、DADJ实现频率微调和占空比调节;(7)频率扫描范围:350倍;(8)输出电阻:0.1 ;(9)温度系数: 。MAX038核心部分是一个电流控制的振荡器,通过恒定的电流对外部电容 充电和放电,获得三角波和方波信号输出。充、放电电流由流进MAX038的 脚的电流控制,由加在引脚FADJ、DADJ上的电压调整。电路的振荡频率为:f= (1-0.2915 )= (1-0.2915 )/ (1)波形的占空比为: (2)当 =0时, 可设为2~750 ,对应中心频率为350:1的变化范围;当= 时,调制频偏为 。控制外部电容 充、放电电流的比值,当 =0时,波形的占空比为50%;当 = 时,占空比为10%~90%。在FADJ和DADJ端口的内部,设置了250 的下拉电流源,可简化外部电路设计,仅用电阻 (连接引脚FADJ和2.5V基准电压的可变电阻)和 (连接引脚DADJ和2.5V基准电压的可变电阻)就可以对频偏和占空比进行调整。 端口由内部的运放强制为虚地,故仅用电阻 就能调整输入电流 ,实现中心频率的调节。3.3.2 占空比调节原理MAX038的DADJ引脚上的电压可控制波形的占空比 (定义为输出波形为正时所占时间的百分数),并且能够改善正弦波的波形,可进行脉冲宽度调制和产生锯齿波。当 接地(即 =0)时,由 可得其占空比为50%。当 =±2.3V时,占空比可在 10%~90%范围内调整;当电压超过±2.3V 时,将使频率偏移或引起不稳定。加在DADJ上的电压: (3)其中: 为 DADJ 引脚上的电压, 为定义为输出波形的占空比。由公式(3)可完成的占空比设置。在本设计中要求占空比 在10%~90%的变化范围,这样 的范围为-2.3V~+2.3V之间变化。因为:为内部恒流源; :连接引脚DADJ和2.5V基准电压的可变电阻。基准电压 :+2.5V由以上分析,可以计算出要使 的范围为-2.3V~+2.3V之间变化时 的范围在0.8K~19.2K 之间变化。所以 可以选择20K 的可变电阻。综上,MAX038工作时引脚DADJ电压的变化可引起电容 充电和放电的相对速率的变化,由此引起矩形波占空比发生变化 ,当 时矩形波占空比为50%,即输出为方波。 的变化范围为±2.3V则占空比的变化范围为10%~90%。所以 ,可使 变化 ,从而改变占空比,这即是设置占空比调节的原理。3.3.3 频率调整原理(1) 频率粗调原理由MAX038内部结构及参考文献[4]可得,当引脚FADJ的电压 =0时,MAX038输出信号频率的计算由式(1)给出:(4)(4)式中, 的计算为 (5) (5)式中 为内部输出的2.5V恒定参考电压,可见 时, 输出信号的频率完全由内部结构及充电电容 决定。 电流大小在2~750μA内变化,电容大小若为pF量级,则输出频率的大小为MHz量级电容大小若为 μF量级 则输出频率的大小为kHz量级电容大小若为μF量级,则输出频率的大小为Hz量级所以其输出频率范围为0.1Hz~20MHz。由此可通过改变电容 的大小达到大幅度地改变输出信号频率,这即是设置频率粗调的原理。在本设计中要求频率在0.1HZ~20MHZ的变化范围,所以选择电容大小若为pF量级。(2) 频率细调原理MAX038工作时引脚FADJ的电压 由参考电压 及可调电阻 决定 = -250μA× (6)由(6)式得 (7)= 时,代入(7)式得到 的变化范围为0.4K~19.6K,所以 可以选择20K 的可变电阻。由(6)式调节 ,可变化FADJ引脚的电压,其变化范围为±2.4V。而 的变化可引起电容充电电流的变化 输出频率则以(4)式的频率 为中心频率,产生±70%左右的变化。由此可通过调节可变电阻 的大小,达到小幅度改变输出信号的频率,这即是设置细调输出信号频率的原理。综上所述,MAX038的输出频率 由 、 、 三者共同决定,当 =0时 = = / = / * ,实现粗调;当 0时, = (1-0.2915 ),实现细调。3.3.4 MAX038外围电路
图 3-7 MAX038外围电路原理图由以上的分析,设计出的MAX038部分的电路如图3-7。SYNC电路具有单独的电源引线因而可被禁止。 数字电压 (+5V)电源端,如果没有用到SYNC的时候 应该悬空。PDI、PDO引脚分别是相位检波器的输入和输出端,在本设计中不用应该接地。3.3.5 MAX038外围电路注意事项由MAX038实现的信号发生电路是模数混合电路,因此在电路设计和线路板布局上都必须注意。具体有:(1)如果PCB板中,MAX038的模拟电源和数字电源需要分开,在供电时要分别供电,即分别取不同的电源,以防数字信号通过电源线干扰模拟部分;同样,模拟地和数字地的处理要慎重,万用板上要用低阻地平面分别将模拟地和数字地连接,再在某点上将两地相连。(2)信号线要尽量部在焊接面,元件面为地平面,这样就可减少信号间的干扰,这一点对系统性能的稳定尤为重要,因为系统性能受 、FADJ、COSC、DADJ等引脚周围的分布电容及信号环境变化的影响特别敏感。此外,这些引脚引线的长度和面积还应尽量短小。(3)由于不同结构的电阻具有不同的寄生电容和寄生电感,因此选择电阻时,应选用寄生电容和寄生电感小的电阻。推荐使用1%以上精度的金属膜电阻。(4)在高频线路中,电源去藕是一个关键问题。整个线路往往会由于电源引线而产生电路谐振,当有大的瞬时变化时,也会产生尖峰干扰信号。消除这两种现象的有效办法就是在片子的电源管脚与地之间加上适当的去藕电容,一般使用1 以上的优质电容。在许多场合,采用2个电容并联的方法(并联一个0.1 电容),则去藕效果更佳。3.4 幅度放大电路
由于MAX038的输出信号为恒定的2V(P-P),且输出电流不高,所以必须在输出级至少有一级的放大电路来提供足够的输出电压和电流,以满足一般的使用要求。以下是放大电路设计的几点考虑:图3-8 放大电路(1) 首先,要求放大电路具有很高的频宽。因为输出信号最大基频为20MHZ,其三角波和矩形波的高次谐波成分很高,只有高频宽才能得到不失真的输出波形。(2) 其次,高频大信号放大要求电路有足够的输出电压转换速率。(3) 另外,要带动低阻负载,放大电路的电流输出能力也是个重要参数。要在10 负载上输出6V信号,则放大器至少要有60mA的连续电流输出能力。居于以上要求本设计的放大电路部分如图3-8。采用低功耗,宽带,高速运算放大器AD8055提高了放大电路的带宽和转换速率,把电压由原来MAX038输出的2V放大到6V。而9013和9012构成了“推挽式电路”也叫做互补对称电路,实现了在静态时管子不取电流,而在有信号时,T1、T2轮流导电。T1、T2是工作在乙类的放大电路,管耗小,提高了电流,从而提高了效率,而且减少了失真。最后接的电阻是为了防止输出端的外接负载短路,所以加一个电阻限制电流。3.5 软件设计软件需要实现的主要功能是检测键盘的输入,根据输入结果选择输出相应的波信号。键盘 *** 作和对应的输出如下:输入按键“0”(第一行第一列),得到正弦波;输入按键“1”(第一行第二列),得到矩形波;输入按键“2”(第一行第三列),得到三角波;软件编程用C51语言,主要包括键盘去抖动延时程序、键盘扫描程序、波形选择程序。单片机控制MAX038实现波形输出的程序流程图3-9。
开始
初始化
键盘扫描
键码为11?
键码为21?
键码为41?
NO
NO
NO
输出正弦波
输出矩形波
输出三角波图3-9 单片机控制MAX038实现波形输出的程序流程图键码为11对应的是第一行第一列的按键;键码为21对应的是第一行第二列的按键;键码为41对应的是第一行第三列的按键。
希望对你能有所帮助。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)