多功能信号发生器课程设计报告

河南理工大学

《单片机应用与仿真训练》设计报告

多功能信号发生器设计

姓    名:      张冬波张立中   

学    号:310808010425  310808010426

专业班级:      电气08-4       

指导老师:      刘巍          

所在学院:电气工程与自动化学院  

20##年6月 28 日

摘要

本设计采用基于AT89S52的单片机最小系统为核心,成功产生出幅值和频率都可调的正弦波、梯形波、方波、三角波等波形。频率范围是0-2000Hz,幅值调节范围-10V到+10V。本系统主要由四大模块组成:液晶显示模块、波形发生模块及稳幅输出模块,幅频调节模块、及外部电源模块。各个模块的实现方法如下:

一、液晶显示模块:本系统采用应用较广泛的1602液晶作为显示模块。其显示与控制机理是单片机通过与液晶按照一定的规定相连接,然后再程序中在对液晶进行初始化后,就可以向其写字符或读字符。

二、波形发生模块及稳幅输出模块:产生指定波形可以通过DAC芯片来实现,不同波形产生实质上是对输出的二进制数字量进行相应改变来实现的。本系统采用的是经典的DAC0832  8位数/模转换器。稳幅输出则通过两个LM324集成运放来实现对DAC0832输出电流信号到电压信号的转变。

三、幅频调节模块:通过按键与两个门电路74ls00和74ls04的组合来实现通过产生中断来实现对波形的选择和频率的调节。而幅值调节通过一个10K的电位器来实现参考电压Vref的改变来改变幅值。

四、外部电源模块:变压器将220V交流电降成16V交流后在通过整流桥

经过7812和7912滤波后即产生正负12V直流电用作LM324的电源。

本系统软件主要通过C语言开发,硬件电路设计具有典型性。同时,本系统中任何一部分电路模块均可移植于其它实用开发系统的设计中,电路设计实用性很强。

                       目录

1、    概述. 4

1.1  信号发生器现状. 4

1.2  单片机在波形发生器中的应用. 4

2、   系统总体方案及硬件设计. 5

2.1 系统分析. 5

2.2 总体方案设计. 6

2.2.1系统总体结构框图设计. 6

2.3 总体硬件设计. 6

2.4系统各模块设计. 7

2.4.1 资源分配. 7

2.4.2显示器接口设计. 7

2.4.3 复位与时钟电路设计. 8

2.4.4 按键中断电路设计. 10

2.4.5 D/A转换电路设计. 10

3、   软件设计. 15

3.1软件总体设计. 15

3.2 软件功能设计. 16

3.2.1系统初始化程序设计. 16

3.2.2 按键检测及中断处理程序. 16

3.2.3 液晶显示程序. 17

3.2.4 正弦波发生程序设计. 19

3.2.5方波产生程序. 20

3.2.6三角波产生程序. 20

3.2.7梯形波产生程序. 21

4、   实验仿真. 22

4.1  protues软件仿真步骤. 22

4.2 仿真结果. 23

4.3仿真结论. 25

5、   课程设计体会. 26

参考文献. 27

附1:源程序代码. 28

附2:系统原理图. 35


1、    概述

1.1  信号发生器现状

. 目前,市场上的信号发生器多种多样,一般按频带分为超高频、高频、低频、超低频、超高频信号发生器。其中高频、低频和超低频信号发生器,大多使用文氏桥振荡电路,即RC振荡电路,通过改变电容和电阻值,改变频率。用以上原理设计的信号发生器,其输出波形一般只有两种,即正弦波和脉冲波,其零点不可调,而且价格也比较贵,一般在几百元左右。但是在科学研究和生产实践中,如工业过程控制,生物医学,地震模拟震动等领域往往需要低频信号源,而由硬件搭建的波形发生器效果往往达不到好的效果,而且低频信号源所需要的RC很大,大电阻,大电容在制作上有困难,参数的精度也难以保证,而且体积大,漏电,体积大是该类波形发生器的显著缺点。

1.2  单片机在波形发生器中的应用

随着电子技术的飞快发展,单片机的应用不断的深入,基于单片机的智能仪器的设计技术不断成熟。单片机构成的仪器具有高可靠性,高性价比,单片机技术在智能仪表和自动化等诸多领域有了极为广泛的应用,并应用到各种家庭电器,单片机技术的广泛应用推动了社会的进步。

利用单片机采用程序设计方法来产生波形,线路相对简单,结构紧凑,价格低廉,频率稳定度高,抗干扰能力强等优点,而且还能对波形进行细微的调整,改良波形,易于通过程序控制,只要对电路稍加修改,调整程序,就能实现功能的升级。

2、   系统总体方案及硬件设计

2.1 系统分析

基于单片机的信号发生系统是一个实际应用系统,可为相关实验及实际应用提供支持。本论文包括硬件系统的详细设计及C语言在基本控制中的应用。此系统具有的功能如下:

硬件部分

(1)1602液晶显示电路;

(2)键盘和与非门中断产生电路;

(3)时钟电路与复位电路;

(4)具有8位精度的D/A转换和波形产生电路;

(5)正负12V直流电源转换电路;

软件部分

(1)系统复位初始化;

(2)键盘中断与处理;

(3)中断0服务程序;

(4)定时器0中断服务程序;

(5)正弦波发生程序;

(6)三角波发生程序;

(7)方波发生程序;

(8)梯形波发生程序。

2.2 总体方案设计

2.2.1系统总体结构框图设计

     图2-1  系统主结构框图

2.3 总体硬件设计

(1)程序存贮器

AT89S52内部自带8K的ROM,512B的RAM,所以不需要对其扩展存储器。

(2)按键及中断接口

系统采用按键通过门电路来产生中断,并在中断服务程序里来扫描按键来实现波形切换和频率的调节。

(3)液晶显示

本设计实现了89S52的I/O口液晶显示字符的控制来显示当前波形种类和波形频率。

(4)D/A转换

本设计D/A转换部分采用DAC0808芯片,通过对单片机输出的二进制数字量进行从数字量到模拟量的变换来实现波形的产生。

(5)信号变换部分

对信号的变换部分采用四运放集成芯片LM324,它采用14脚双列直插塑料封装,它的内部包含四组形式完全相同的运算放大器。

(6)外部电源

因LM324工作需要正负12V的直流电源,因此需要通过对变压器输出电压进行整流、滤波然后在通过7812和7912输出所需电压。

2.4系统各模块设计

2.4.1 资源分配

为了满足功能和指标要求,现分配资源如下:

1.晶振采用12MHZ

2.IO端口分配:P0口与DAC0832的DI0-DI7数据输入;P3口的P3.4~P3.7分别与四个按键相连,依次控制波形种类的选择、波形频率的增加、波形频率的减小和波形输出的暂停与恢复。中断0即P3.2与门电路的输入端相连。P2.0和P2.1分别与DAC0832的输入寄存器选择信号CS,输入寄存器写选通信号WR1及DAC寄存器写选通WR2和数据传送信号XFER相连。P1口做液晶的D0—D7的数据输入端口,P2.2~P2.4分别做1602液晶的读写控制端和使能端。

2.4.2显示器接口设计

   本系统采用1602液晶来显示信号输出的状态,液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在各类仪表和低功耗系统中得到广泛的应用。相比较数码管用液晶显示具有以下优点:

1.位数多,可显示32位,32个数码管体积则相当庞大

2.显示内容丰富,可显示所有数字和大、小写字母,能更好的表示信号显示的状态,而数码管只能显示也一个频率值,不能表示正在输出的信号类别

3.程序简单,如果用数码管动态显示,会占用很多时间来刷新显示,而1602自动完成此功能。节省了单片机资源。

图2.2 系统显示电路

2.4.3 复位与时钟电路设计

2.4.3.1复位电路设计

单片机的复位是靠外电路实现的,在时钟电路工作后,只要在单片机的RST引脚上出现24个时钟振荡脉冲(2个机器周期)以上的高电平,单片机便实现初始化状态复位。为了保证应用系统可靠地复位,通常是RST引脚保持10ms以上的高电平。复位电路连接如图3-2所示。此电路仅用一个电容及一个电阻。系统上电时,在RC电路充电过程中,由于电容两端电压不能跳变,故使RESET端电平呈高电位,系统复位。经过一段时间,电容充电,使RESET端呈低电位,复位结束。

                             2-3 复位电路

2.4.3.2 时钟电路设计 


8XX51系列单片机工作时必须要有个时钟脉冲,有两种方法可以向AT89S51提供时钟脉冲:

第一:外部时钟方式。使用外部电路始终给AT89S51提供时钟脉冲如右图

2-4 晶振电路

第二:内部时钟方式。使用晶振利用AT89S51内部电路产生时钟脉冲如左图。我们一般使用这种方式。AT89S51中有一个用于构成内部振荡器的高增益反相放大器,引脚XTAL1和XTAL2分别是该放大器的输入端和输出端。这个放大器与作为反馈元件的片外石英晶体或陶瓷谐振器一起构成自激振荡器

外接石英晶体及电容C1、C2接在放大器的反馈回路中构成并联振荡电路。对外接电容C1、C2虽然没有十分严格的要求,但电容容量的大小会轻微影响振荡频率的高低、振荡器工作的稳定性、起振的难易程度及温度稳定性。如果使用石英晶体,我们推荐使用30pF+/-10pF,而如使用陶瓷谐振器建议选择40pF+/-10PF。

2.4.4 按键中断电路设计

2-5按键中断实现

工作原理如下:

1. 当没有按键按下时,INT0端口保持高电平,中断不触发,当有任何一个按键按下时通过74ls00(双输入与非门)、74ls04(非门)的相互连接,最终实现INT0变成低电平。从而触发中断,进而执行中断服务程序。(注:本来门电路部分通过一个74ls22 这个4输入的与非门就可以实现,但因为我在附近的元器件商店没有买到,只好用74ls00和74ls04代替使电路略显复杂)。

2.进入中断服务程序后,系统执行键盘扫描程序,来识别究竟是哪个按键按下。然后根据识别的按键来进入相关的处理函数,例如按下波形选择键触发中断后,在中断服务程序中,系统将波形符号加1,从而改变波形。

2.4.5 D/A转换电路设计

2.4.5.1  DAC0832基本介绍

DAC0832是双列直插式8位D/A转换器。能完成数字量输入到模拟量(电流)输出的转换。其主要参数如下:

1.分辨率为8位

2.转换时间为1μs

3.满量程误差为±1LSB

4.参考电压为(+10~-10)V

5.供电电源为(+5~+15)V

6.逻辑电平输入与TTL兼容

2.4.5.2 DAC0832引脚图

图2-6 DAC0832引脚图

(1)DI7~DI0 :8位的数据输入端,DI7为最高位。

(2)IOUT1 :模拟电流输出端1,当DAC寄存器中数据全为1时,输出电流最大,当 DAC寄存器中数据全为0时,输出电流为0。

(3)IOUT2 :模拟电流输出端2, IOUT2与IOUT1的和为一个常数,即IOUT1+IOUT2=常数。

(4)RFB :反馈电阻引出端,DAC0832内部已经有反馈电阻,所以 RFB端可以直接接到外部运算放大器的输出端,这样相当于将一个反馈电阻接在运算放大器的输出端和输入端之间。

(5)VREF :参考电压输入端,此端可接一个正电压,也可接一个负电压,它决定0至255的数字量转化出来的模拟量电压值的幅度,VREF范围为(+10~-10)V。VREF端与D/A内部T形电阻网络相连。

(6)Vcc :芯片供电电压,范围为(+5~ 15)V。

(7)AGND :模拟量地,即模拟电路接地端。

(8)DGND :数字量地。

2.4.5.3 内部结构框图

 

图2-7 DAC0832内部结构图

内部结构框图分析:在DAC0832中有两级锁存器,第一级锁存器称为输入寄存器,它的允许锁存信号为ILE,第二级锁存器称为DAC寄存器,它的锁存信号也称为通道控制信号 XFER。当ILE为高电平,片选信号 /CS 和写信号 /WR1为低电平时,输入寄存器控制信号为1,这种情况下,输入寄存器的输出随输入而变化。此后,当 /WR1由低电平变高时,控制信号成为低电平,此时,数据被锁存到输入寄存器中,这样输入寄存器的输出端不再随外部数据DB的变化而变化。对第二级锁存来说,传送控制信号 /XFER 和写信号 /WR2同时为低电平时,二级锁存控制信号为高电平,8位的DAC寄存器的输出随输入而变化,此后,当 /WR2由低电平变高时,控制信号变为低电平,于是将输入寄存器的信息锁存到DAC寄存器中。

2.4.5.4 DAC0832的工作方式

1.单缓冲工作方式

此方式是使两个寄存器中任一个处于直通状态,另一个工作于受控锁存器状态或两个寄存器同步受控。一般的做法是将WR1和XFER接数字地,使DAC 寄存器处于直通状态。另外把ILE接高电平,CS接端口地址译码信号,WR1接CPU系统总线的IOW信号,这样便可通过执行一条输出指令,选中该端口,使 CS和 WR1有效,从而启动D/A转换。

 

图2-8单缓冲工作单极性方式电路连接

双极性模拟输出电压 :

 

图2-9单缓冲工作双极性方式电路连接

(2)双缓冲工作方式

双缓冲方式的一大用途是数据接收和启动转换可以异步进行,即在对某数据转换的同时,能进行下一数据的接收,以提高转换速率。这时,可将ILE接高电平,WR1和WR2接CPU的IOW,CS和XFER分别接两个不同的I/O地址译码信号。

(3)直通工作方式

当DAC0832芯片的片选信号、写信号、及传送控制信号的引脚全部接地,允许输入锁存信号ILE引脚接+5V时,DAC0832芯片就处于直通工作方式,数字量一旦输入,就直接进入DAC寄存器,进行D/A转换。

2.4.5.5本系统采用的AD转换原理图

DAC0832主要由8位输入寄存器、8位DAC寄存器、8位D/A转换器以及输入控制电路四部分组成。8 位输入寄存器用于存放主机送来的数字量,使输入数字量得到缓冲和锁存,由加以控制;8位DAC寄存器用于存放待转换的数字量,由加以控制;8位D/A转换器输出与数字量成正比的模拟电流;由与门、非与门组成的输入控制电路来控制2个寄存器的选通或锁存状态。

DAC0832与反相比例放大器相连,实现电流到电压的转换,因此输出模拟信号的极性与参考电压的极性相反,数字量与模拟量的转换关系为

Vout1=-Vref×(数字码/256)

图2-10 D/A转换器双极性输出电路

图10中,运算放大器U3B的作用是把运算放大器U3A的单向输出电压转换成双向输出电压。D/A转换器的总输出电压为:

VOUT2= -[(R3/R2) VOUT1+(R3/R1)] Vref

因为R2=R3=2R  R1=R,则  VOUT2= -(2VOUT1+Vref)

这样VOUT2的变化范围就是从- VREF到+VREF之间变化。从而实现电压的双极性输出,并且可以通过改变Vref的值变化来实现幅值的改变


3、   软件设计

3.1软件总体设计

应用系统中的应用软件是根据系统功能要求而设计的,能可靠地实现系统的各种功能。一个优秀的应用系统的应具有下列特点:

(1)根据软件功能要求,将系统软件分成若干个独立的部分。设计出软件的总体结构,使其结构清晰、流程合理。

(2)要树立结构化程序设计风格,各功能程序模块化、子程序化。既便于调试、链接,又便于移植、修改。

(3)建立正确的数学模型。即根据功能要求,描述各个输入和输出变量之间的数学关系,它是关系到系统好坏的重要因素。

(4)为提高软件设计的总体效率,以简明、直观法对任务进行描述,在编写应用软件之前,应绘制出程序流程图。

(5)要合理分配系统资源,包括ROM、RAM、定时数器、中断资源等。

(6)注意在程序的有关位置处写上功能注释,提高程序的可读性。

(7)加强软件抗干扰设计,它是提高系统应用可靠性的有利措施。

本系统的软件包括以下几个程序模块:

(1)系统复位初始化;

(2)键盘中断与处理;

(3)中断0服务程序;

(4)定时器0中断服务程序;

(5)正弦波发生程序;

(6)三角波发生程序;

(7)方波发生程序;

(8)梯形波发生程序。

3.2 软件功能设计

3.2.1系统初始化程序设计

初始化程序完成以下工作:初始化1602液晶使其指针指向第一行第一格;初始化DAC0832使其工作在单缓冲方式,其中使DAC寄存器处于直通状态,而使8位输入寄存器处于关断状态;初始化外部中断0使其为下降沿触发,设置定时器0为16位工作方式,开定时器和外部中断,开总中断。

初始化程序如下:

    uchar i=0;

       DA_S2=0;    //使DAC寄存器处于直通状态

       DAdata=0;

       DA_S1=1;    //关闭8位输入寄存器

waveform=0;      

rw=0;  //1602液晶初始化一定要设置为零,表示写数据

write_com(0x38);  //使液晶显示点阵,为下面做准备

write_com(0x0c);  //初始设置

write_com(0x06);  //初始设置

write_com(0x01);  //清零

write_com(0x80);  //使指针指向第一行第一格

       TMOD=0x01;  //设置定时器0为16位工作方式

       IT0=1;      //设置外部中断0为下降沿触发

       ET0=1;      //开定时器中断

       EX0=1;      //开外部中断

       EA=1;       //开总中断

3.2.2 按键检测及中断处理程序

单片机系统中,键盘扫描是CPU工作的一个主要内容之一。CPU忙于各项工作任务时,如何兼顾键盘扫描。既保证不失时机的响应键盘操作,又不过多占用CPU时间。因此,要根据应用系统中的CPU的忙、闲情况,选择好键盘的工作方式。

本系统采用中断工作方式,该方式相交其它方式有节省CPU资源,提高效率等优点。即当键盘有健按下时,才执行键盘扫描,然后执行该键功能程序。

             图3.1按键处理结构图

3.2.3 液晶显示程序

对1602液晶进行初始化后就可以向其写命令和字符了,本程序要用1602液晶显示输出信号的种类和频率,输出的信号共有四种:Sine Wave:正弦波、Triangle Wave:三角波、  Square Wave:方波、Trapezoidal wave:方波。

显示程序如下:

void write_com(uchar com)//写命令函数

{

     rs=0;      //置零,表示写指令

     lcden=0;

     lcd_ports=com;

     delay(5);

     lcden=1;

     delay(5);

     lcden=0;      

}

void write_date(uchar date)//写字符函数

{

     rs=1;      //置1,表示写数据(在指令所指的地方写数据)

     lcden=0;

     lcd_ports=date;

     delay(5);

     lcden=1;

     delay(5);

     lcden=0;      

}

void disp_lcd(uchar addr,uchar *temp1)//写字符串函数

{

     uchar num;

     write_com(addr);

     delay(1);   //延时一会儿

     for(num=0;num<16;num++)

     {

            write_date(temp1[num]);

            delay(1);

     }

}

void init_lcd()

{

     rw=0;  //初始化一定要设置为零,表示写数据

     write_com(0x38);  //使液晶显示点阵,为下面做准备

     write_com(0x0c);  //初始设置

     write_com(0x06);  //初始设置

     write_com(0x01);  //清零

     write_com(0x80);  //使指针指向第一行第一格

    disp_lcd(0x80,&lcd_hang1[4*16]);  //在第一行显示

    disp_lcd(0xc0,&lcd_hang1[5*16]);  //在第二行显示

}

3.2.4 正弦波发生程序设计

     利用MATLAB对正弦曲线均匀取样后,得到等间隔时刻的y方向上的二进制数值,然后依次输出后经D/A转换得到。本程序在一个周期上进行了256次均匀取样结果如下:

uchar code sine_tab[256]={

       //输出电压从0到最大值(正弦波1/4部分)

0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,

0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,

0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,

       //输出电压从最大值到0(正弦波1/4部分)

  0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,

0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,

0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99 ,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,

       //输出电压从0到最小值(正弦波1/4部分)

0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,

0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16 ,0x15,0x13,

0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,

       //输出电压从最小值到0(正弦波1/4部分)

0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02 ,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,

0x11,0x13,0x15 ,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,

0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66 ,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80};

3.2.5方波产生程序

方波信号是利用定时器0中断产生的,每次中断时,将输出的信号按位反即可;

void square_out()  //方波输出

{    

    judge=~judge;

    if(judge==1) DAdata=0xff;

       else  DAdata=0x00;

       DA_S1=0;  //打开8位输入寄存器

       DA_S1=1;  //关闭8位输入寄存器

}

3.2.6三角波产生程序

通过对三角波图形在一个周期上的均匀取样,然后依次输出后经D/A转换得到,本程序在一个周期上进行了64次均匀取样结果如下:

uchar code triangle_tab[]={     //每隔数字8,采取一次

       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,0xff,

       0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x98,0x90,0x88,0x80,

       0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08,0x00};

3.2.7梯形波产生程序

 梯形波产生的原理和三角波相似,也是对其在一个周期上的均匀取样,然后依次输出后经D/A转换得到,取样结果如下:

uchar code tixing_tab[]={  //每隔数字8,采取一次

    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,0xff,0xff,    0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,

0xf0,0xe0,0xd0,0xc0,0xb0,0xa0,0x90,0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10,0x00};

4、   实验仿真

4.1  protues软件仿真步骤

1. 打开PROTEUS软件,选择所需器件。窗口如图4-1所示

 

                               图4-1 器件选择

2.将所有器件排列好。器件排列见图4-2

 

                           图4-2 器件排列

3.连接导线。如图4-3。

 


图4-3 连接导线

4. 打开KEIL软件,调出程序编译,生成HEX文件,并将其载入protues里。调试窗口见图4-4。

 

              图4-4 系统调试

4.2 仿真结果

1.正弦波仿真: 频率10HZ 仿真结果如图4-5

                   图4-5 正弦波

2.三角波仿真:频率100HZ 仿真结果如图4-6

 

                    图4-6 三角波

3.方波仿真:频率200HZ 仿真结果如图4-7

 


                  

图4-7方波

4.梯形波仿真:频率100HZ 仿真结果如图4-11

 

                       图4-11 梯形波

4.3仿真结论

采用PROTEUS进行单片机仿真,可以大大缩短单片机的开发周期。它不仅能仿真单片机CPU 的工作情况,也能仿真单片机外围电路或没有单片机参与的其它电路的工作情况。本系统仿真结果,满足设计需求。实际操作灵活,使用方便。

5、   课程设计体会

这次课程设计主要是基于对单片机的掌握和应用,这是我第一次动手实践制作电路图和焊接硬件电路,从课题的选择、系统原理方案的设计,电路原理的理解,到电路上元器件的焊接、程序的编写,电路的调试,调试下载,一步步,我觉得每个环节我都收获很大。在设计中,我力求硬件电路简单,充分发挥软件灵活方面的特点,在满足系统设计要求的同时在一定程度上作出扩展。在此次课程设计中,我主要有以下几个方面的心得体会:

一、 在对单片机的具体实践掌握方面。上个学期我们开设了单片机原理与接口技术这门专业课,尽管在这门课程的学习上,自己态度非常认真而且也下了很大的功夫。但是在纯粹的理论上,总感觉不是那么的踏实和具体,而这次课程设计就为我具体实践提供了一次很好的机会,我觉得这个教学安排对我们实践能力的锻炼时很有帮助的,通过此次课程设计,我对单片机的掌握有了更加切实的感受和接触,以及简单的应用,收获很大

二、在软件的使用方面。这次课程设计主要用到keil uvision2和Proteus两个软件,这次课程设计使我更加深入和熟练的掌握了这两个软件的使用。特别是protues软件,该软件功能强大,操作简单,可以大大加快单片机的开发过程,是单片机开发的有力帮手。

三、 在C语言程序的编写方面。在大一下学期的时候自己就学过用C语言编写程序的方法,虽然自己在大三也学过汇编编程,但与C语言相比汇编有可读性好,移植容易等优点,所以这次采用了更方便好用的C语言编写程序。此次课程设计是我掌握了编写一个较大型系统软件的思路,提高了自己的编程水平。

单片机课程设计马上就要结束了,自己在设计过程中碰到了不少“难题”,通过自己翻阅大量资料和请教老师,解决了一个个难题。通过这次毕业设计,我深深体会到:世上无难题,只怕有心人。碰到难题不要惧怕,只要你肯钻研,问题总会有解决的办法。最后在此我特别感谢在此次课程设计对我提供帮助的老师和同学,

参考文献

[1]  余发山 王福忠 单片机原理及应用技术 北京:中国矿业大学出版社,2008

[2]  张义和等编. 例说51单片机 北京:人民邮电出版社,2008

[3]  周和琴,吴秀清编著. 微型计算机原理与接口技术北京:中国科学技术大学出版社,2004

[4]  周润景等编著. Proteus在MCS-51&ARM7系统中的应用百例:电子工业出版社,2006

[5]  张靖武,周灵彬著. 单片机系统的PROTEUS设计与仿真 北京:电子工业出版社,2007

[6]  丁新民编著.微机原理与应用 北京:高等教育出版社,2008

[7]  周明德编著.微型计算机原理及应用.北京:清华大学出版社,1998

[8]  张洪润,易涛编著.单片机应用技术教程(第二版).北京:清华大学出版,2003

[9]  求是科技编著.单片机典型模块设计实例导航.北京:人民邮电出版社,2004

[10]  刘坤等编著. 51单片机C语言应用开发技术大全  .北京:人民邮电出版社,2008

[11]  潘新民,王燕芳编著.微型计算机控制技术.北京:电子工业出版社,2004

[12]  全国大学生电子设计竞赛组委会编.第五届全国大学生电子设计竞赛获奖作品选编

.北京:北京理工大学出版社,2003

[13]  杨宁编著.单片机与控制技术.北京:北京航空航天大学出版社,2005

附1:源程序代码

#include<reg52.h>

#define  uchar unsigned char

#define  uint  unsigned int

#define DAdata  P0     //DA数据端口

sbit DA_S1= P2^0;   // 控制DAC0832的8位输入寄存器,仅当都为0时,可以输出数据(处于直通状态),否则,输出将被锁存

sbit DA_S2= P2^1;   // 控制DAC0832的8位DAC寄存器,仅当都为0时,可以输出数据(处于直通状态),否则,输出将被锁存

sbit key=   P3^2;

#define lcd_ports P1

sbit rs=P2^2;

sbit rw=P2^3;

sbit lcden=P2^4;

uchar wavecount;                     //'抽点'计数

uchar THtemp,TLtemp;                //传递频率的中间变量

uchar judge=1;                       //在方波输出函数中用于简单判别作用

uchar judge1=0;                      //在中断处理里做判断暂停和输出状态作用

uchar waveform;                      //当其为0、1、2、3时,分别代表四种波

uchar code freq_unit[4]={10,50,200,50}; //四种波的频率单位

uchar idata wavefreq[4]={1,1,1,1};       //给每种波定义一个数组单元,用于存放单位频率的个数

uchar code lcd_hang1[]={"Sine Wave       " "Triangle Wave   " "Square Wave     " "Trapezoidal wave" "Select Wave:    " "press No.1 key! " "Suspend output: " "waveform!       "};

uchar idata lcd_hang2[16]={"f=    Hz        "};

/***********这两组数组很重要,需要根据波形来调试,选择合适的值,使输出波形达到频率要求************/

uchar code waveTH[]={

    0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

       0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

       0xec,0xf6,0xf9,0xfb,0xfc,0xfc,0xfd,0xfd,0xfd,0xfe,

       0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

uchar code waveTL[]={

    0x06,0x8a,0x10,0x4e,0x78,0x93,0xa8,0xb3,0xbe,0xc6, //正弦波频率调整中间值

       0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde,      //三角波频率调整中间值

       0x88,0x50,0x90,0x32,0x34,0xbe,0x4a,0xa3,0xe5,0x2c,

       0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde}; //矩形波频率调整中间值

/*************************************************************************************************/

uchar code triangle_tab[]={ //每隔数字8,采取一次

       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,0xff,

       0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x98,0x90,0x88,0x80,

       0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08,0x00};

uchar code tixing_tab[]={  //每隔数字8,采取一次

    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

    0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,0xff,0xff,

    0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,0Xff,

    0xf0,0xe0,0xd0,0xc0,0xb0,0xa0,0x90,0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10,0x00};

uchar code sine_tab[256]={

       //输出电压从0到最大值(正弦波1/4部分)

       0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,

       0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,

       0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,

       //输出电压从最大值到0(正弦波1/4部分)

       0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,

       0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,

       0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99 ,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,

       //输出电压从0到最小值(正弦波1/4部分)

       0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,

       0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16 ,0x15,0x13,

       0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,

       //输出电压从最小值到0(正弦波1/4部分)

       0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02 ,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,

       0x11,0x13,0x15 ,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,

       0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66 ,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80};

void delay(uchar z)       

{

    uint x,y;

       for(x=z;x>0;x--)

       for(y=110;y>0;y--);

}

void triangle_out() //三角波输出

{    

    DAdata=triangle_tab[wavecount++];

       if(wavecount>64) wavecount=0;

       DA_S1=0;  //打开8位输入寄存器

       DA_S1=1;  //关闭8位输入寄存器

}

void sine_out()      //正弦波输出

{    

    DAdata=sine_tab[wavecount++];

       DA_S1=0;  //打开8位输入寄存器

       DA_S1=1;  //关闭8位输入寄存器

}

void square_out()  //方波输出

{    

    judge=~judge;

    if(judge==1) DAdata=0xff;

       else  DAdata=0x00;

       DA_S1=0;  //打开8位输入寄存器

       DA_S1=1;  //关闭8位输入寄存器

}

void tixing_out()//梯形波输出

{

 P0=tixing_tab[wavecount++];

 if(wavecount>64)

 wavecount=0;

 DA_S1=0;

 DA_S1=1;

 }

/************1602液晶的相关函数*************/

void write_com(uchar com)//写命令函数

{

       rs=0;       //置零,表示写指令

       lcden=0;

       lcd_ports=com;

       delay(5);

       lcden=1;

       delay(5);

       lcden=0; 

}

void write_date(uchar date)//写字符函数

{

   

       rs=1;       //置1,表示写数据(在指令所指的地方写数据)

       lcden=0;

       lcd_ports=date;

       delay(5);

       lcden=1;

       delay(5);

       lcden=0; 

}

void disp_lcd(uchar addr,uchar *temp1)//写字符串函数

{

       uchar num;

       write_com(0x38);  //使液晶显示点阵,为下面做准备

       write_com(0x0c);  //初始设置

       write_com(0x06);  //初始设置

       write_com(addr);

       delay(1);   //延时一会儿

       for(num=0;num<16;num++)

       {

              write_date(temp1[num]);

              delay(1);

       }

}

void init_lcd()

{

       rw=0;  //初始化一定要设置为零,表示写数据

       write_com(0x38);  //使液晶显示点阵,为下面做准备

       write_com(0x0c);  //初始设置

       write_com(0x06);  //初始设置

       write_com(0x01);  //清零

       write_com(0x80);  //使指针指向第一行第一格

    disp_lcd(0x80,&lcd_hang1[4*16]);  //在第一行显示

    disp_lcd(0xc0,&lcd_hang1[5*16]);  //在第二行显示

      

}

/********************1602液晶函数声明结束*********************/

void main()

{

    uchar i=0;

       DA_S2=0;    //使DAC寄存器处于直通状态

       DAdata=0;

       DA_S1=1;    //关闭8位输入寄存器

       init_lcd(); //初始化lcd液晶

    waveform=0; 

       TMOD=0x01;  //设置定时器0为16位工作方式

       IT0=1;      //设置外部中断0为下降沿触发

       ET0=1;      //开定时器中断

       EX0=1;      //开外部中断

       EA=1;       //开总中断

while(1)

{

  

}

}    

        

void timer0() interrupt 1

{

       TH0=THtemp;

       TL0=TLtemp;       

       if(waveform==0)      sine_out();

       else if(waveform==1) triangle_out();

       else if(waveform==2) square_out();

       else if(waveform==3) tixing_out();

}

void key_int0() interrupt 0

{

    uchar keytemp;

       uint total_freq;          //总频率

       EA=0; TR0=0;          //关总中断与定时器

       delay(8);               //加延时

       if(key==0)             //确实有按键按下而引发中断

       {

              keytemp=P3&0xf0; //获取P3口高四位的值

              switch(keytemp)

              {

                  case 0xe0:      //选择波形

                          waveform++;

                             if(waveform>3) waveform=0;

                             break;

                  case 0xd0:  //频率按规定单位依次增加

                          wavefreq[waveform]++;

                             if(wavefreq[waveform]>10) wavefreq[waveform]=1;

//   这里用>10,因为它比=11更可靠

                             break;                     //   性更高,使加数有个上限,不会一直加下去

                  case 0xb0:  //频率按规定单位依次衰减

                          wavefreq[waveform]--;

                                    if(wavefreq[waveform]<1) wavefreq[waveform]=10; //这边要用<1,比=0可靠性更高

                             break;

                  case 0x70:    //输出状态控制按键

                          DA_S2=~DA_S2; //使DAC寄存器关闭或打开

                             judge1=~judge1;  //取反波形输出状态位,使波形在暂停和输出间切换

                             break;

              }

              if(judge1==0)                               //未处在暂停状态,系统输出波形

              {

           THtemp=waveTH[waveform*10+(wavefreq[waveform]-1)]; //方括号中选取第几个数后,并把该值赋给T_temp

              TLtemp=waveTL[waveform*10+(wavefreq[waveform]-1)];

           total_freq= wavefreq[waveform] * freq_unit[waveform]; //求输出频率(个数*单位)

             lcd_hang2[5]=total_freq%10+0x30;                   //在液晶中显示个位,(0x30 在液晶显示中表示数字0)

           total_freq/=10; lcd_hang2[4]=total_freq%10+0x30; //在液晶中显示时十位

           total_freq/=10; lcd_hang2[3]=total_freq%10+0x30; //在液晶中显示时百位

           total_freq/=10; lcd_hang2[2]=total_freq%10+0x30; //在液晶中显示时千位

           disp_lcd(0x80,&lcd_hang1[waveform*16]);        //在第一行显示

           disp_lcd(0xc0,lcd_hang2);                      //在第二行显示

              }

              else                                       //暂停键按下,系统暂停波形输出

              {

              disp_lcd(0x80,&lcd_hang1[6*16]);  //在第一行显示暂停输出提示

           disp_lcd(0xc0,&lcd_hang1[7*16]);  //在第二行显示暂停输出提示

              }

       }

       wavecount=0; //'抽点'计数清零,使波形从头开始显示

       while(!key);//检测按键是否松开,这个必须加上

       EA=1; TR0=1;     //开启总中断与定时器

}

附2:系统原理图

 

相关推荐