单片机课程设计波形发生器剖析.docx

上传人:b****6 文档编号:8156066 上传时间:2023-01-29 格式:DOCX 页数:26 大小:784.85KB
下载 相关 举报
单片机课程设计波形发生器剖析.docx_第1页
第1页 / 共26页
单片机课程设计波形发生器剖析.docx_第2页
第2页 / 共26页
单片机课程设计波形发生器剖析.docx_第3页
第3页 / 共26页
单片机课程设计波形发生器剖析.docx_第4页
第4页 / 共26页
单片机课程设计波形发生器剖析.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

单片机课程设计波形发生器剖析.docx

《单片机课程设计波形发生器剖析.docx》由会员分享,可在线阅读,更多相关《单片机课程设计波形发生器剖析.docx(26页珍藏版)》请在冰豆网上搜索。

单片机课程设计波形发生器剖析.docx

单片机课程设计波形发生器剖析

单片机课程设计报告

烟台大学

 

题目波形发生器

专业机械设计制造及其自动化

班级机101—4

学生姓名

同组人员

学号

指导老师:

姜风国

机电汽车工程学院

2013年6月6日

波形发生器

一、设计目的

(1)利用所学单片机机的理论知识进行软硬件整体设计,锻炼学生理论联系实际、提高我们的综合应用能力。

(2)我们这次的课程设计是以单片机为基础,设计并开发能输出多种波形(正弦波、三角波、锯齿波等)且频率、幅度可变的波形发生器。

(3)掌握各个接口芯片(如0832等)的功能特性及接口方法,并能运用其实现一个简单的单片机应用系统功能器件。

(4)在平时的学习中,我们所学的知识大都是课本上的,在机房的练习大家也都是分散的对各个章节的内容进行练习。

因此,缺乏一种系统的设计锻炼。

在课程所学结束以后,这样的课程设计十分有助于学生的知识系统的总结到一起。

(5)通过这几个波形进行组合形成了一个波形发生器,使得我对系统的整个框架的设计有了一个很好的锻炼。

这不仅有助于大家找到自己感兴趣的题目,更可以锻炼大家单片机知识的应用。

二、设计的主要内容和要求

1.1基本内容和要求

(1)设计一款能够产生3种波形的波形发生器;

(2)设计波形选择按钮;

(3)LED或LCD显示波形代号;

(4)其他功能(创新部分)。

(5)波形频率调节;

(6)波形幅值调节;

三、整体设计思路

3.1设计思路

1、课设需要各个波形的基本输出。

如输出正弦波、锯齿波、三角波。

这些波形的实现的具体步骤:

(1)正弦波:

通过手动的方法计算出输出各点的电压值,然后在编写程序时以数组的方式给出。

当需要时,只要按照顺序进行输出即可。

这种方法比在软件中计算速度快且曲线的形状修改灵活。

在本设计中将一个周期(360度)分为256个点,则每两个点之间的间隔为1.4度,然后计算出每个点电压对应的数字量,形成数组。

只要反复输出这组数据到DAC0832,就可以在系统输出端得到想要的正弦波。

(2)锯齿波:

也使用查表法。

将三角波的一个周期(360度)分为256个点,相邻点等差,生成数组。

反复输出前128个数据到DAC0832,就可以在系统输出端得到想要的锯齿波。

(3)三角波:

将(3)中的数组256个数据全部输出到DAC0832,循环,就可以在系统输出端得到想要的三角波。

2、通过P1口和轻触开关S1-S4相连接来切换波形输出(如按S1键输出正弦波,按S2键产生方波,按S3键产生锯齿波,按S4键产生三角波)。

用P0口控制数码管静态显示波形代号。

用P2口向DAC0832发送数据,经DAC0832转换后,再把信号放大,最后接到示波器上显示。

3.2元件选型

单片机AT89C51系统,DAC0832一片,PC机一台,运算放大器。

3.3功能原理图

P0

P1

P2

P3

四、方案论证

任务要求实现波发生器产生正弦波、锯齿波、三角波,由于正弦波的存在,采用单片机直接运算是不合理的,故采取按时将存储的数字量送出的方法实现;为简化编程,锯齿波与三角波也采取按时送数字量的方式实现。

将一个周期分为256份,幅值0至255,取数据后分别存入数组。

利用定时器中断函数实现数据按时送出,改变定时器的初值设置即可改变频率。

送出的数据由指针循环指向相应数组的值,改变指针的地址,指向不同的数组首地址即可改变波形。

幅值的改变由DAC的参考电压和反馈电阻改变。

采用AT89C51单片机和DAC0832芯片,直接连接键盘和显示。

该种方案主要对AT89C51单片机的各个I/O口充分利用。

P3口是连接键盘,P2口接显示电路,P0口连接DAC0832输出波形。

这样总体来说,能对单片机各个接口都利用上,而不在多用其它芯片,从而减小了系统的成本。

也对按照系统便携式低频信号发生器的要求所完成。

占用空间小,使用芯片少,低功耗。

五、硬件电路设计

5.1电路连线图

通过P1.0-P1.5口和轻触开关相连接来切换波形输出(如按S1键输出锯齿波,按S2键产生三角波,按S3键产生正弦波),P1.4、P1.5接波形频率调节开关,如图所示。

用P0口控制数码管静态显示波形代号,如图所示。

用P0口向DAC0832发送数据,经DAC0832转换后,再把信号放大,最后接到示波器上显示如图所示。

图1总电路图

 

5.2主要芯片介绍

(1)51单片机的内部结构

基本组成部分:

1一个8位的CPU

2128B或256B单元内数据存储器(RAM)

34KB或8KB片内程序存储器(ROM或EPROM)

44个8位并行I/O接口P0~P3。

5两个定时/计数器。

65个中断源的中断管理控制系统。

7一个全双工串行I/O口UART(通用异步接收、发送器)

8一个片内振荡器和时钟产生电路。

图751单片机引脚

管脚说明:

VCC:

供电电压。

GND:

接地。

P0口:

P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。

当P1口的管脚第一次写1时,被定义为高阻输入。

P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。

在FIASH编程时,P0口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

P1口:

P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。

P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。

在FLASH编程和校验时,P1口作为第八位地址接收。

P2口:

P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。

并因此作为输入时,P2口的管脚被外部拉低,将输出电流。

这是由于内部上拉的缘故。

P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。

在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。

P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

P3口:

P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。

当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。

作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

RST:

复位输入。

当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

ALE/PROG:

当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。

在FLASH编程期间,此引脚用于输入编程脉冲。

在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。

因此它可用作对外部输出的脉冲或用于定时目的。

然而要注意的是:

每当用作外部数据存储器时,将跳过一个ALE脉冲。

如想禁止ALE的输出可在SFR8EH地址上置0。

此时,ALE只有在执行MOVX,MOVC指令是ALE才起作用。

另外,该引脚被略微拉高。

如果微处理器在外部执行状态ALE禁止,置位无效。

 /PSEN:

外部程序存储器的选通信号。

在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。

但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

 /EA/VPP:

当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。

注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。

在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。

XTAL1:

反向振荡放大器的输入及内部时钟工作电路的输入。

XTAL2:

来自反向振荡器的输出。

(2)DAC0832芯片

DAC0832是采样频率为八位的D/A转换芯片,集成电路内有两级输入寄存器。

DAC0832输出的是电流,一般要求输出是电压,所以还必须经过一个外接的运算放大器转换成电压。

DAC0832芯片具备双缓冲、单缓冲和直通三种输入方式,以便适于各种电路的需要(如要求多路D/A异步输入、同步转换等)。

所以这个芯片的应用很广泛,关于

DAC0832的引脚功能如下:

D0~D7:

数字信号输入端。

ILE:

输入寄存器允许,高电平有效。

CS:

片选信号,低电平有效。

WR1:

写信号1,低电平有效。

XFER:

传送控制信号,低电平有效。

WR2:

写信号2,低电平有效。

IOUT1、IOUT2:

DAC电流输出端。

RfB:

是集成在片内的外接运放的反馈电阻。

VREF:

基准电压(-10~10V)。

VCC:

是源电压(+5~+15V)。

GND:

地。

图8DAC0832芯片图

(3)1602液晶显示器引脚功能如下:

  

第1脚:

VSS为电源地  

第2脚:

VDD接5V电源正极 

第3脚:

V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。

 

第4脚:

RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。

  

第5脚:

RW为读写信号线,高电平

(1)时进行读操作,低电平(0)时进行写操作。

  

第6脚:

E(或EN)端为使能(enable)端。

  

第7~14脚:

D0~D7为8位双向数据端。

  

第15~16脚:

空脚或背灯电源。

15脚背光正极,16脚背光负极。

(4)DAC0832说明:

DAC0832选用直通方式,所以CS,XFER,WR1和WR2接地;D0—D7是数据量数据输入线,接收P0口输出的数据;VREF接基准电压,其中串接一个滑动电阻器,通过改变阻值,从而改变电压,达到改变幅值的目的;芯片内已有反馈电阻,所以RFB接到运算放大器输出端;GND接地;VCC接工作电源;IOUT1和IOUT2输出电流接运算放大器。

(5)按键工作说明:

采用独立式按键输入的处理,软件查询方式,也就是说,先逐位查询每根I\0口线输入为低电平,则可确认该I\0口线所对应的按键已按下,再转向该按键的功能处理程序。

 

六、软件设计

6.1正弦波的产生过程

通过手动的方法计算出输出各点的电压值,形成数组sin_tab[256],反复顺序输出这组数据到DAC0832,就在系统输出端得到正弦波。

6.2锯齿波的产生过程

将一个周期(360度)分为128个点,递增,生成数组saw_tab[256],反复顺序输出这组数据到DAC0832,就在系统输出端得到锯齿波。

6.3三角波的产生过程

将三角波的一个周期(360度)分为256个点,相邻点等差,前128个点递增,后128个点递减,生成数组tri_tab[256],反复顺序输出这组数据到DAC0832,就在系统输出端得到三角波。

6.4通过开关实现波形切换和调频

轻触开关S1-S4切换波形输出(S1键输出正弦波,按S2键产生方波,按S3键产生锯齿波,按S4键产生三角波),S5、S6调节方波占空比,S7、S8调节波形频率。

七、调试与仿真

6.1正弦波的仿真结果

使用有源低通滤波器,输出波形变得更平滑了,但会出现畸变。

这是符合实际情况的。

如下图分析。

图11调频前波形图12调频后波形

6.2锯齿波的仿真结果

图13调频前波形图14调频后波形

6.3三角波的仿真结果

图15调频前波形图16调频前波形

八、总结

本次的设计中利用AT89C51和DAC0832以及放大器完成电路的设计,用开关来控制各种波形的转换和波形频率,用单片机输出后,经过数模转换器生成波形,最终可以通过示波器观察。

在这次的软件设计中,程序设计采用的是C语言。

C语言简洁高效,是最贴近硬件的高级编程语言,经过多年的发展,现在已成熟为专业水平的高级语言。

因此,在大型程序的设计中,多采用C语言进行程序编译。

而且,现在单片机产品推出时纷纷配套了C语言编译器,应用广泛。

由于真正意义上的程序设计还不多,因此还不是很得心应手,所以在设计中遇到一些问题和一些难点。

比如:

在程序设计中如何实现程序结构的最优化,以达到较高的质量。

这是以后设计中要注意的问题。

通过这次课程设计,我进一步了解了波形发生器的原理,在实际动手操作过程中,使我接触了许多我以前没接触过的元件,而且重新温习了刚学不久的C语言,使我学得了许多知识,使我获益匪浅。

这次课程设计,使我的动手能力得到了很大的提高,更使我们懂得理论知识的重要性,没有理论的指导一切实际行动都是盲目的,且实际操作是我们得到的理论知识得到验证,更能增加对理论知识的理解。

九、参考文献

[1]汪贵平,李登峰,龚贤武,雷旭《新编单片机原理及应用》机械工业出版社,2012年1月第三次印刷。

[2]赵文博,刘文涛《单片机语言C51程序设计》人民邮电出版社,2005年10月北京第一次印刷。

[3]

 

附录

附录一:

硬件图

main函数

中断函数

附录二:

流程图

附录三:

程序清单

/**********************main.c文件*************************/

/****含有*************/

/****定时器初始化函数*************/

/******main函数*************/

/******定时器1中断函数*************/

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

#include"head.H"//包含函数、变量声明

#include"lcd.c"//lcd1602液晶显示器的函数

#include"fun.c"//包含键盘扫描、延时等功能函数

/*********************初始化函数*******************/

voidini(){

table=tri_tab;//给予初值

THHL=65535;//

TH1=THHL/256;//定时器1高八位赋值

TL1=THHL%256;//定时器1第八位赋值

TMOD=0x10;//定时器1模式设置方式1,十六位不自动重装

EA=1;//开总中断

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

TR1=1;//启动定时器1

}

/***********主函数*************************/

main()

{

lcdini();//lcd初始化程序

writdatas(0x80,lcdtable);//调用显示字符串函数显示选项

writdatas(0x80+0x41,select);

ini();//初始化程序

while

(1){

keyplay();//键盘扫描函数

}

}

/************T1中断函数*************************/

voidtime()interrupt3

{

TR1=0;

TH1=THHL/256;

TL1=THHL%256;

DataOut=*(table+n);

n++;//加一,满255自动溢出

TR1=1;

}

 

/**********************fun.c文件*************************/

/******含有*************/

/******延时函数*************/

/******键盘扫描函数*************/

/******键盘功能函数*************/

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

/**************延时函数*****************/

voiddelays(uint8x){

uint8i;

for(;x>0;x--)

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

}

/******************键盘扫描函数********************/

voidkeyplay(){

uint8temp;//定义一个变量

Key=0xff;//赋初值

temp=Key;//key的值赋予temp

if(temp!

=0xff){//判断temp中的值是否等于Oxff

delays

(2);//推迟2ms

temp=Key;//key中的值赋予temp

if(temp!

=0xff){//判断temp中的值是否等于Oxff

while(Key!

=0xff);//程序等待释放。

switch(temp){//选择按键

case0xfe:

KeySaw();//按键1锯齿波

break;

case0xfd:

KeyTri();//按键2三角波

break;

case0xfb:

KeySin();//按键3正弦波

break;

case0xf7:

KeyPinUp();//频率增加

break;

case0xef:

KeyPinDow();//频率降低

break;

default:

break;

}

}

}

}

/*********************键盘功能函数****************************/

voidKeySaw(){

lcdclear();

writdatas(0x80,str_saw);

table=saw_tab;

}

voidKeyTri(){

table=tri_tab;

lcdclear();

writdatas(0x80,str_tri);

}

voidKeySin(){

table=sin_tab;

lcdclear();

writdatas(0x80,str_sin);

}

voidKeyPinUp(){

if(THHL<=65525){

THHL=THHL+LEV;

//P2_0=~P2_0;

}

else{

THHL=65530;

}

 

}

voidKeyPinDow(){

if(THHL>=500){

THHL=THHL-LEV;

//P2_0=~P2_0;

}

else{

THHL=500;

}

}

/**********************lcd.c文件*************************/

/******含有*************/

/******写命令函数*************/

/******写数据函数*************/

/******写字符串*************/

/******初始化*************/

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

//#include"reg51.h"

//#include"fun.c"

//#include"head.H"

#defineLCDATAP2//p2口

sbitrs=P3^5;//

sbitrw=P3^6;

sbitlcde=P3^4;

 

uint8codelcdtable[]="start,saw-k1";//定义字符串

uint8codeselect[]="tri-k2,sin-k3";//定义字符串

uint8codestr_sin[]="sine";//正弦波

uint8codestr_tri[]="triangular";//三角波

uint8codestr_saw[]="sawtooth";//锯齿波

 

/**************写命令函数*********************/

voidwritcom(uint8com){

rs=0;//选择写命令模式

LCDATA=com;//将要写的命令字送到数据总线上

lcde=1;//使能端给一高脉冲,因为初始化函数中已经将lcden置为0

delays

(1);//稍作延时

lcde=0;//将使能端置0以完成高脉冲

}

voidwritdat(uint8dat)

{

//while(lcdzt());

rs=1;//选择写数据模式

//delays(5);

LCDATA=dat;//将要写的数据传到数据总线上

//delays

(1);

lcde=1;//使能端给一高脉冲,因为初始化函数中已经将lcden置为0

delays(5);

lcde=0;//将使能端置0以完成高脉冲

//rw=1;

//delays(5);

}

voidlcdini(){

rw=0;//低电平为写模式

lcde=0;//使能端置低

writcom(0x38);//显示模式设置

delays

(1);//延时1秒

writcom(0x0c);//设置开显示,不显示光标

delays

(1);//延时1秒

writcom(0x06);//写一个字符后地址指针加1

delays

(1);//延时1秒

writcom(0x01);//显示清0,数据指针清0

delays

(1);//延时1秒

}

//lcd清屏

voidlcdclear(){

rw=0;

lcde=0;

writcom(0x01);

delays

(1);

}

/************************字符串函数******************************/

voidwritdatas(uint8posi,uint8*ldate)

{

writcom(posi);//调用写命令函数定义位置

while(*ldate!

='\0'){//依次送字符

writdat(*ldate++);

}

}

/****************lcd**************/

/************************测试主函数************************

voidmain(){

lcdini();

writdatas(0x80,lcdtabl);

writdatas(0x80+0x

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 工学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1