基于单片机的函数信号发生器设计.docx
《基于单片机的函数信号发生器设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的函数信号发生器设计.docx(21页珍藏版)》请在冰豆网上搜索。
基于单片机的函数信号发生器设计
基于单片机的函数信号发生器
设计所用元器件:
元器件
数量(个)
电阻
3
电容
9
STC89C52芯片
1
DAC0832芯片
1
MAX232芯片
1
按键
7
OP07运算放大器
1
LED发光二极管
1
LCD1602液晶屏幕
1
晶振
1
电位器
1
芯片底座
4
排阻
1
电解电容
2
排针
若干
跳线
若干
基于单片机的函数信号发生器
1.设计目的
1.学习使用keil编程,使用AltiumDesigner绘制原理图;
2.使用单片机产生正弦波、方波、三角波、锯齿波并可通过按键对波形切换、幅值和频率的调整;
3.学习使用示波器显示波形;
2.设计原理
基于单片机的函数发生器原理以STC89C51为整个函数发生器的核心部分,通过编写程序和执行程序,运用示波器显示出四种波形,分别是正弦波、三角波、方波和锯齿波。
本设计拥有五个按键,分别实现波形的切换,改变波形的频率和幅值的大小。
芯片DAC0832将数字信号转换成模拟信号输出并通过外接运算放大器OP07实现电流向电压的转换,最后通过示波器显示出波形。
3.设计内容
3.1基本设计内容
本次设计的主要内容是设计一个基于单片的函数信号发生器实现正弦波、三角波、方波和锯齿波。
利用单片机设计程序,使其能够通过按键有效切换四种波形,并且实现波形幅值和频率的调整满足本设计的要求,进行硬件系统和软件系统的设计,最后调试完成本次设计。
LCD1602液晶显示波形种类、幅值以及频率。
频率的可调范围在1—10HZ,幅值可调范围在1—5V。
显示屏上显示参数,第一行显示波形。
第二行左边显示波形频率,右边显示波形幅值。
本设计由五个功能按键,分别进行波形切换,加减幅值和加减频率。
电压在示波器上显示,硬件原理示意图,如图1.1所示。
图1.1硬件原理设计图
3.2模块设计
3.2.1单片机最小系统模块
本设计STC89C51为整个函数发生器的核心部分,单片机、时钟电路和复位电路构成单片机的最小系统,如图2.1所示。
图2.1单片机最小系统模块原理图
晶体谐振器是时钟电路的重要组成部分,将晶体谐振器放入电路,上电后它会产生机械振荡,单片机凭借晶体谐振器的频率运行所设计出来的频率,所以说晶体谐振器的频率是单片机操作时间规律,保证单片机平稳的工作。
晶体谐振器是控制CPU的时钟频率的。
频率控制运行速度。
晶体谐振器虽然是振荡电路的一部分,但是它自身不会产生震荡,它会有一个固定的频率,然后与外围电路发生谐振。
谐振的产生需要晶体谐振器固定频率和外围电路的频率一致,如果差距大,或者根本对不上则会使电路不在振荡。
单片机会根据实际所能承受的晶体谐振器频率来选择自己的运行频率,不会因为晶体谐振器频率快单片机运行就快,频率慢单片机运行速度就会降低。
复位电路包含一个电容、两个电阻包括一个接地电阻和一个复位按键,电容和电阻采用值为10μF和10K。
复位电路让单片机回到原始工作状态,RST复位引脚高电平有效,高电平有效的持续时间应为24个时钟周期以上,才能有效复位。
根据公式电容的充电时间为t=R*C,则电容的充电时间为100ms,充满使得单片机复位。
电容充满,与地相接的的电阻电压、电流都降为零,在开机上电的0.1s钟内,单片机系统会自动复位,在单片机工作期间,按下复位按键,电容放电,接地电阻出现电压,单片机复位松开按键,电容充电,几个毫秒之后单片机开始工作。
3.2.2显示模块
LCD1602能同时显示32个字符。
LCD1602采用的是数据并行接法,特点主要是使用方便,需要很多的I/O口,函数发生器设计中I/O口是够用的,所以可以使用这种数据传输方式。
八位的数据赋给I/O口。
读取数据时也只要读取整个I/O口。
LCD1602显示模块,如图2.2所示。
图2.2显示模块原理图
3.2.3D/A转换电路
DA转换模块由DAC0832、OP07运算放大电路组成,DAC0832作为函数发生器数模转换模块的核心芯片,转换时间为1us,工作电压为+5v~+15v,基准电压为正负10v。
它主要由两个8为寄存器和一个8位D/A转换器组成,片内有输入数据寄存器,所以芯片可以直接与单片机相接。
DAC0832以电流的形式输出信号,所以需要在Iout后接一个OP07运算放大器,把输出电流信号转换成电压的形式,供示波器显示,在信号输出之前OP07输出口接一个电阻和一个电容组成一个简单的滤波电路,用来抑制其他杂波,得到正常信号。
D/A转换模块,如图2.3所示。
图2.3D/A转换模块原理图
3.2.4提供运放电源电路
DAC0832输出的是电流信号,要将电流转换成电压,OP07运算放大器需要提供正负10v的电压,在单片机与计算机通信时需要加电平转换芯片,MAX232可以完成电平转换功能,因此MAX232芯片上可以找到正、负电压。
根据测量,MAX232芯片的2、6引脚分别输出+10v和-10v左右的电压,所以可以作为运算放大器OP07的电源电压,分别接在运放两端,MAX232芯片,如图2.4所示。
图2.4MAX232原理图
4.硬件设计调试
4.1测试仪器
为确保硬件和软件的正确性及完善性,需要一些测试仪器进行调试,硬件调试所需仪器如表3.1所示:
表3.1测试仪器表
硬件调试所需仪器
数量
电脑
1台
万用表
1个
USB线
1条
示波器
1台
连接板子和示波器的探头线
1条
4.2硬件调试过程
硬件调试是设计是否能成功的关键,通过调试可以检查板子是否能正确运行以及检测设计功能是否按要求实现。
画原理图很多细节需要注意,原理图的正确性很重要,这关系到板子的焊接和实现,原理图布局划线最好规整,本设计需要焊接的元器件不多,但焊接时还是需要认真检查特别注意的,比如短距离焊点的焊接方法,或是线与线之间很近,线与焊盘之间距离太小,线细易断等。
在线密集的地方避免焊接在一起,同时还要避免虚焊、短路、断路等现象。
按照原理图有顺序的焊接器件,从低到高焊接,芯片的焊接需要注意,不可将芯片直接焊上。
在焊接的时候看见虚断的线路,需要用焊锡补,在拉焊锡时为了避免影响其他的线路,在拉完焊锡的路径上进行检测,检查相关电路的连通和无关电路的隔断,找出问题电路线,并及时改正。
在焊完电路以后检查电路的可实际操作性是一定需要的,因为在焊接的时候芯片很容易出现问题,板子上有些元件接口还加有跳线,需要检查是否有正确连接,有无短路、断路、线的连通性,跳线有没有松动等,对照电路图按照顺序逐一对照检查。
板子实物图,如图3.1所示。
图3.1板子实物图
上电后,板子上的最小系统的复位按键,按下是否能复位,LED灯点亮。
检测完毕后在进行下一步的调试工作。
板子通电时不要急于把重要的芯片插上,更不能将芯片或电源插反,若电路出现问题很有可能将芯片烧坏。
通电后查看显示屏能否正常显示。
若板子出现异常现象,例如异常气味、出现烟雾和器件发烫等现象,立即切断电源。
如果测试没有任何问题,硬件也确定是好的,结束硬件调试下载正确程序,并连接示波器。
(1)板子上电后,通过示波器显示频率为1HZ,幅值为5V的正弦波。
图3.2正弦波实现图
(2)通过按键,实现频率和幅值的调整,示波器上显示调整后的正弦波波形,频率为5HZ,幅值为2V。
图3.3正弦波实现图
(3)通过波形切换按键,将正弦波波形切换到三角波波形,并通过示波器上显示频率为5HZ,幅值为2V三角波波形。
图3.4三角波实现图
(4)通过波形切换按键,将三角波波形切换到方弦波波形,并通过示波器上显示频率为5HZ,幅值为2V方波波形。
图3.5方波实现图
(5)通过波形切换按键,将方弦波波形切换到锯齿波波形,并通过示波器上显示频率为5HZ,幅值为2V方波波形。
图3.6锯齿波实现图
4.3调试所遇问题及解决办法
将元器件根据原理图焊接在板子上后,给板子上电,单片机最小系统没有异常,液晶显示屏正常,MAX232芯片在上电几分钟后芯片发烫,立刻切断电源,并检查原理图各个引脚是否焊接正确,地和电源是否焊接错误,检查有无短路现象,发现无误,再次上电,其他模块正常运作,MAX232芯片仍然发烫,断电后将芯片取下,给板子供电,用万用表测量DAC0832输出引脚,万用表显示有电流输出,可以确定DAC0832芯片正常运作。
这时将MAX232换下,换成一个升压模块电路,对OP07运放提供正负电压,将模块接入后,上电,发现几分钟后升压模块也迅速发烫,切断电源将模块取下,这时通过查找资料后发现OP07正负10V引脚接反,这时将OP07运放的正负电源输入端口引脚反过来,将MAX232芯片的6引脚与运放OP07的4引脚相接,之后再将MAX232芯片的2引脚与运放OP07的7引脚相接。
4.4调试结果
通过对软件和硬件的检查,反复的修改和调试,上电后,电源指示灯正常亮,LCD1602液晶显示屏可以正常显示波形种类、幅值和频率大小,按下按键后,相应的显示屏显示的内容会有所改变,示波器显示正确的波形,本设计可以手动复位。
5.软件调试
基于单片机函数信号发生器是由硬件和软件来相互结合实现的,任一部分存在问题都会影响总体功能,达不到预期效果。
在本设计确定硬件电路没有问题以后,就开始对软件的调试了。
由于软硬件相互结合,根据题目要求设计硬件电路,查看相关资料以及整合相关电路功能及性能,将硬件电路设计出来,确定好硬件电路后,根据要实现的硬件功能,软件设计也会逐步确定下来。
根据函数发生器所要实现的具体功能设计出合理的程序结构。
单片机的软件设计调试主要有两种,一是使用软件仿真进行调试,运用计算机软件区模拟单片机环境的指令执行,并虚拟单片机内部资源从而实现功能演示。
另外一种就是通过软硬件结合来进行程序的调试,使用Keil软件编译好程序下载到单片机中,然后在系统中观察软件功能是否实现。
在本次设计中我们先使用proteus对本设计进行仿真,之后再运用软硬结合下载进单片机的方式完成本次设计。
6.心得体会
为期两周的单片机实训结束了,我们小组学到了很多东西。
随着电子技术的发展,特别是随着大规模集成电路的产生,给人们的生活带来了根本性的变化,我们学习了单片机这门课程,感觉是有点难,不过在学习中,我才发现学习单片机不仅仅需要软件的知识,还需要硬件的知识。
单片机是一门很好的学问,需要我们去钻研它。
说起本次设计,我认为最重要的就是做好设计的预习,认真的研究老师给的题目,选一个小组成员都感兴趣的题目。
其次,老师在实验课上的讲解要认真的去听去想,因为只有都明白了,做起设计就会事半功倍,如果没弄明白,就迷迷糊糊的去选题目做设计,到头来一点收获也没有。
最后,要重视程序的规范,便于修改,也要注重程序的调试,掌握其方法。
在全组人竭尽全力,程序编写成功,这是我们共同努力的结果,在享受我们成果之时,不得不感慨单片机的重要性,所以为期两周的单片机课程设计没有浪费我们学到了很多知识,本次设计和课堂上老师所讲的内容有所相似,需要我们在结合所学只是上进一步升华。
也让我们对单片机有了更深一步的了解,虽然最后结果是出来了,可这与老师的精心指导是分不开的她引导我们的思路,所以老师是功不可没的。
总而言之,单片机课程设计对于我们有很大的帮助,我们从中受益匪浅。
附录1
原理图
Protues仿真图
附录2
源程序
#include"reg52.h"
#defineucharunsignedchar
#defineuintunsignedint
sbitkey1=P1^0;
sbitkey2=P1^1;
sbitkey3=P1^2;
sbitkey4=P1^3;
sbitkey5=P1^4;
sbitlcden=P3^4;
sbitlcdrs=P3^5;
sbitdacwr=P3^6;
ucharflag,freq,size;//分别用来标记波的种类、频率HZ、幅值V
ucharnum,key;//定义数组元素、以及是否有按键按下
uintvalue;//定时器装初值
ucharlcd_table[]="wave:
";
ucharlcd_table1[]="fre:
";
ucharlcd_table2[]="amp:
";
ucharlcd_table3[]="sin";//LCD波形种类数组
ucharcodesin_table[64]={
0x00,0x03,0x06,0x0a,0x10,0x17,0x1e,0x27,0x30,0x3b,0x46,0x51,0x5d,0x69,0x76,0x83,0x8f,0x9c,0xa8,0xb3,0xbf,0xc9,0xd3,
0xdc,0xe4,0xec,0xf2,0xf7,0xfb,0xfe,0xff,0xff,0xff,0xfc,0xf9,0xf5,0xef,0xe8,0xe1,0xd8,0xce,0xc4,0xb9,0xae,0xa2,0x96,
0x89,0x7d,0x70,0x64,0x58,0x4c,0x41,0x36,0x2c,0x23,0x1b,0x14,0x0d,0x08,0x04,0x01,0x00,0x00};//正弦波
ucharcodetri_table[64]={
0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,
0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0xfe,0xf6,0xee,0xe6,0xde,0xd6,0xce,0xc6,0xbe,0xb6,0xae,0xa6,0x9e,0x96,
0x8e,0x86,0x7e,0x76,0x6e,0x66,0x5e,0x56,0x4e,0x46,0x3e,0x36,0x2e,0x26,0x1e,0x16,0x0e,0x06};//三角波
ucharcodezig_table[64]={
0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c,0x20,0x24,0x28,0x2c,0x30,0x34,0x38,0x3c,0x40,0x44,0x48,0x4c,0x50,0x54,0x58,
0x5c,0x60,0x64,0x68,0x6c,0x70,0x74,0x78,0x7c,0x80,0x84,0x88,0x8c,0x90,0x94,0x98,0x9c,0xa0,0xa4,0xa8,0xac,0xb0,0xb4,
0xb8,0xbc,0xc0,0xc4,0xc8,0xcc,0xd0,0xd4,0xd8,0xdc,0xe0,0xe4,0xe8,0xec,0xf0,0xf4,0xf8,0xfc};//锯齿波
ucharcodesqu_table[64]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//方波
voiddelayms(ucharxms)
{
uchari,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
voidwrite_com(ucharcom)//液晶写指令
{
lcdrs=0;
P0=com;
delayms
(2);
lcden=1;
delayms
(2);
lcden=0;
}
voidwrite_data(uchardate)//液晶写数据
{
lcdrs=1;
P0=date;
delayms
(2);
lcden=1;
delayms
(2);
lcden=0;
}
voidlcd_init()//液晶初始化
{
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
voidinit()
{
key=1;value=15625;//按键标志位、定时初值(1450微秒为人工减小误差值)初始化
flag=1;freq=1;size=5;//变量初始化,初始产生正弦波,频率为1HZ,幅值为5V
dacwr=0;//0832初始化
TMOD=0x01;//定时器T0初始化
TH0=(65536-value+1400)/256;//频率为1HZ时,每点之间隔15625微秒
TL0=(65536-value+1400)%256;
EA=1;
ET0=1;
TR0=1;
}
voidkeyscan()
{
if(key1==0)//key1选择波形
{
delayms(5);
if(key1==0)
{
while(!
key1);
key=1;
flag++;//flag为1、2、3、4时,分别对应正弦方波、三角方波、锯齿方波、方波
if(flag>=5)flag=1;
}
}
if(key2==0)//频率增大
{
delayms(5);
if(key2==0)
{
while(!
key2);
key=1;
freq++;
if(freq>10)freq=1;
value=1000000/(freq*64);
}
}
if(key3==0)//频率减小
{
delayms(5);
if(key3==0)
{
while(!
key3);
key=1;
freq--;
if(freq<1)freq=10;
value=1000000/(freq*64);
}
}
if(key4==0)//幅值增大
{
delayms(10);
if(key4==0)
{
while(!
key4);
key=1;
size++;
if(size>5)size=1;
}
}
if(key5==0)//幅值减小
{
delayms(10);
if(key5==0)
{
while(!
key5);
key=1;
size--;
if(size<1)size=5;
}
}
}
voidgene_wave()
{
switch(flag)
{
case1:
P2=sin_table[num]*size/5;lcd_table3[0]='s';lcd_table3[1]='i';lcd_table3[2]='n';break;
case2:
P2=tri_table[num]*size/5;lcd_table3[0]='t';lcd_table3[1]='r';lcd_table3[2]='i';break;
case3:
P2=zig_table[num]*size/5;lcd_table3[0]='z';lcd_table3[1]='i';lcd_table3[2]='g';break;
case4:
P2=squ_table[num]*size/5;lcd_table3[0]='s';lcd_table3[1]='q';lcd_table3[2]='u';break;
default:
P2=sin_table[num]*size/5;lcd_table3[0]='s';lcd_table3[1]='i';lcd_table3[2]='n';
}
}
voidlcd_display()
{
uchari,ge,shi;
lcd_init();
key=0;//置按键标志位为0
shi=freq/10;
ge=freq%10;
write_com(0x80);//第一行:
显示波形
for(i=0;i<5;i++)
write_data(lcd_table[i]);
for(i=0;i<3;i++)
write_data(lcd_table3[i]);
write_com(0x80+0x40);//第二行:
显示频率和振幅
for(i=0;i<4;i++)
write_data(lcd_table1[i]);
write_data(shi+0x30);
write_data(ge+0x30);
write_data('H');
write_data('Z');
for(i=0;i<2;i++)
write_data('');
for(i=0;i<4;i++)
write_data(lcd_table2[i]);
write_data(size+0x30);
write_data('v');
}
voidmain()
{
init();
while
(1)
{
keyscan();
if(key)
lcd_display();
}
}
voidT0_time()interrupt1
{
TL0=(65536-value+1400)%256;
TH0=(65536-value+1400)/256;
num++;
if(num>=64)
num=0;
gene_wave();
}