基于51单片机的波形发生器设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

课题要求:
目录:
1、系统总体设计方案规划与选定…………………………………
2、硬件设计…………………………………………………………
3、软件设计………………………………………………………….
4、调试……………………………………………………………….
5、新增功能及实现方法……………………………………………
6、总结与体会………………………………………………………
7、参考文献…………………………………………………………
8、附录(源程序代码、电路图等)………………………………
一. 系统总体设计方案规划与选定
本次设计采用AT89C51单片机为核心,通过与8279芯片和38译码器、锁存器的配合实现对键盘状态的检测和LED 显示的控制,通过D/A 转换器和运算放大器以及示波器实现对波形的输出,并且在8位LED 显示器上显示波形类型的代号、幅值、频率。

键盘为4*8键盘,通过键盘摁键实现对波形种类、幅值、频率等的调节。

图1. 总体方案结构框图
二.硬件设计
硬件的选择对于功能的实现非常重要,我们要了解芯片的功能、性能,根据题目要求选择合适的芯片。

(一)硬件介绍
1.单片机选择AT89C51。

AT89C51 提供以下标准功能:4k 字节Flash 闪速存储器,128字节内部RAM ,32 个I/O 口线,两个16位定时
/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。

同时,AT89C51可降至0Hz
的静态逻辑操作,并支持两种软件可选的节电工作模式。

空闲方式停止CPU
的工作,但允许
RAM ,
定时/计数器,串行通信口及中断系统继续工作。

掉电方式保存
RAM
中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。

AT89C51具有优良的性能,符合题目的要求。

图2. AT89C51引脚图
引脚说明:
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。

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

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

在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,需要接上拉电阻。

本次设计中P0口与8279的AD[0..7]连接,作为数据传输口。

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

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

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

本次设计中P1口与D/A转换器的D10—D17口相连。

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

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

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

P2口当用于外部程序存储器或16位地址外部数据存储器进行
/EA:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。

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

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

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

XTAL2:来自反向振荡器的输出。

2. 8279
8279是一款由单一+5V电源供电的可编程键盘显示接口芯片。

其功能是:对键盘进行管理和控制;对LED显示器进行控制、对显示数据和显示方式进行管理。

图3. 8279芯片
引脚说明:
<1>AD[0..7]:双向数据总线。

在CPU与8279间做数据与命令传送。

<2>CLK:8279的系统时钟,100KHz为最佳选择。

<3>RES:复位输入线。

输入HI时可复位8279。

<4>CS:芯片选择信号线。

当这个输入引脚为低电平时,可将命令写入8279或读取8279的数据。

<5>A0:缓冲器地址选择线。

A0=0时,读写一般数据;A0=1时,读取状态标志位或写入命令。

<6>RD:读取控制线。

RD=0时,8279输送数据到外部总线。

<7>WR:写入控制线。

WR=0时,8279从外部总线接收数据。

<8>IRQ:中断请求。

平常IRQ为LO,在键盘模式下,每次读取FIFO/SENSOR RAM的数据时,IRQ变为HI,读取后转为LO;在传感器模式下,只要传感器一有变化,就会使IRQ变为HI,读取后转为LO。

<9>SL0~SL3:扫描按键开关或传感器矩阵及显示器,可以是编码模式(16对1)或解码模式(4对1)。

<10>RL0~RL7:键盘/传感器的返回线。

无按键被按时,返回线为HI;有按键被按时,该按键的返回线为LO。

在激发输入模式时,为8位的数据输入。

<11>SHIFT:在键盘扫描模式时,引脚的输入状态会与其它按键的状态一同储存(在BIT6),内部有上拉电阻,未按时为HI,按时为LO。

<12>CNTL/STB:在键盘扫描模式时,引脚的输入状态会与SHIFT以及其它按键的状态同一储存,内部有上拉电阻,未按时为HI,按时为LO。

在激发输入模式时,作为返回线8位数据的使能引脚。

<13>OUTA0~OUTA3:动态扫描显示的输出口(高4位)。

<14>OUTB0~OUTB3:动态扫描显示的输出口(低4位)。

<15>BD:消隐输出线。

3. DAC0832
DAC0832是8分辨率的D/A转换集成芯片。

与微处理器完全兼容。

这个DA芯片以其价格低廉、接口简单、转换控制容易等优点,在单片机应用系统中得到广泛的应用。

D/A转换器由8位输入锁存器、8位DAC寄存器、8位D/A转换电路及转换控制电路构成。

图4. DAC0832芯片
引脚介绍:
(1)D10~D17:8位数据输入线,TTL电平,有效时间应大于90ns(否则锁存器的数据会出错);
(2) ILE:数据锁存允许控制信号输入线,高电平有效;
(3) CS:片选信号输入线(选通数据锁存器),低电平有效;
(4)WR1:数据锁存器写选通输入线,负脉冲(脉宽应大于500ns)有效。

由ILE、CS、WR1的逻辑组合产生LE1,当LE1为高电平时,数据锁存器状态随输入数据线变换,LE1的负跳变时将输入数据锁存;
(5)XFER:数据传输控制信号输入线,低电平有效,负脉冲(脉宽应大于500ns)有效;
(6) WR2:DAC寄存器选通输入线,负脉冲(脉宽应大于500ns)有效。

由WR2、XFER的逻辑组合产生LE2,当LE2为高电平时,DAC寄存器的输出随寄存器的输入而变化,LE2的负跳变时将数据锁存器的内容打入DAC寄存器并开始D/A 转换。

(7) IOUT1:电流输出端1,其值随DAC寄存器的内容线性变化;
(8) IOUT2:电流输出端2,其值与IOUT1值之和为一常数;
(9) Rfb:反馈信号输入线,改变Rfb端外接电阻值可调整转换满量程精度;
(10)Vcc:电源输入端,Vcc的范围为+5V~+15V;
(11) VREF:基准电压输入线,VREF的范围为-10V~+10V;
(12) AGND:模拟信号接地;
(13)DGND:数字信号接地。

4. 38译码器74HC138
图5. 74HC138
74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL)系列。

74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2,即图中A,B,C),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。

74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。

除非E1和E2置
低且E3置高,否则74HC138将保持所有输出为高。

利用这种复合使能特性,仅需4片74HC138芯片和1个反相器,即可轻松实现并行扩展,组合成为一个1-32(5线到32线)译码器。

任选一个低有效使能输入端作为数据输入,而把其余的使能输入端作为选通端,则74HC138亦可充当一个8输出多路分配器,未使用的使能输入端必须保持绑定在各自合适的高有效或低有效状态。

74HC138 作用原理于高性能的存贮译码或要求传输延迟时间短的数据传输系统,在高性能存贮器系统中,用这种译码器可以提高译码系统的效率。

将快速赋能电路用于高速存贮器时,译码器的延迟时间和存贮器的赋能时间通常小于存贮器的典型存取时间,这就是说由肖特基钳位的系统译码器所引起的有效系统延迟可以忽略不计。

HC138 按照三位二进制输入码和赋能输入条件,从8 个输出端中译出一个低电平输出。

两个低电平有效的赋能输入端和一个高电平有效的赋能输入端减少了扩展所需要的外接门或倒相器,扩展成24 线译码器不需外接门;扩展成32 线译码器,只需要接一个外接倒相器。

在解调器应用中,赋能输入端可用作数据输入端。

图6. 74HC138真值表
5.锁存器74HC373
373为三态输出的八D 透明锁存器
图 7. 74HC373
当三态允许控制端 OE 为低电平时,Q0~Q7 为正常逻辑状态,可用来驱动负载或总线。

当 OE 为高电平时,Q0~Q7 呈高阻态,即不驱动总线,也不为总线的负载,但
锁存器内部的逻辑操作不受影响。

当锁存允许端 LE 为高电平时,Q 随数据 D 而变。

当 LE 为低电平时,Q 被锁存在已建立的数据电平。

6.键盘
键盘扫描原理:在扫描每一行时,读列线,若全为1,说明此行无键按下;若某一列为0,说明有键按下,且行号和列号已经确定。

然后,用同样的方法,
依次向列线扫描,读行线上的值。

如果,两次所得的行号和列号分别相同,则确定闭合键的键码。

7.运放与示波器
运算放大器将电流信号转换为电压信号,在示波器上显示出来。

(二)硬件连接
图8. 芯片连接图(仿真图)
通过键盘的摁键控制波形类型、频率和幅值。

38译码器对键盘进行行扫描,8279对键盘进行列扫描,扫描结果在通过8279传到单片机中。

CPU可通过查询、中
断方式了解到8279所连键盘中是否有健按下,并且确定是哪个键摁下,发出相应的
指令,一方面在LED上显示相应的数字符号,一方面通过D/A转换器和运放在示波
器上显示输出波形。

其中中断是关键,中断的实现是通过8279内部的FIFO检测键盘的变化,如
INT,向CPU申请中断。

果有键摁下,IRQ信号变为高电平,通过非门送到单片机的1
三、软件设计
本次设计采用C语言编程。

与汇编语言相比,C语言程序更加易于理解,在设计编起来较为容易,而且方便寻找错误。

设计中,正弦波、锯齿波和三角波均采取查表法实现,这样就解决了函数法产生波形在调节频率时影响幅值大小的缺点。

设计中需要注意对于每一个子函数都要定义。

C程序:
#include <reg51.h>
#include <absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define com8279 XBYTE[0x7fff] //adr1-com8279 //命令状态口
#define data8279 XBYTE[0x6fff] // adr2-data8279 //数据口
uchar code hello[]={0x6d,0x06,0x00,0x76,0x79,0x38,0x38,0x3f};
/*液晶显示51 hello字符*/
uchar
duanma[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //顺序0-9显示字符
uchar keyval,boxingfs,boxing,f=1,v=5,i,s; //参数初始化
float code sintab[256]= //正弦波数据点阵 {
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,
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,
0xac, 0xab, 0xa8, 0xa5, 0xa2, 0x9f, 0x9c, 0x99, 0x96, 0x93, 0x90, 0x8d, 0x89, 0x86, 0x83, 0x80,
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 ,
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,
};
uchar code juchitab[128]=
{
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x4e,
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce,
0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, //锯齿波数据点阵
};
uchar code sanjiaotab[256]=
{
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x4e,
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce,
0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
0xfe, 0xfc, 0xfa, 0xf8, 0xf6, 0xf4, 0xf2, 0xf0,
0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0,
0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xd0,
0xce, 0xcc, 0xca, 0xc8, 0xc6, 0xc4, 0xc2, 0xc0,
0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0,
0xae, 0xac, 0xaa, 0xa8, 0xa6, 0xa4, 0xa2, 0xa0,
0x9e, 0x9c, 0x9a, 0x98, 0x96, 0x94, 0x92, 0x90,
0x8e, 0x8c, 0x8a, 0x88, 0x86, 0x84, 0x82, 0x80,
0x7e, 0x7c, 0x7a, 0x78, 0x76, 0x74, 0x72, 0x70,
0x6e, 0x6c, 0x6a, 0x68, 0x66, 0x64, 0x62, 0x60,
0x5e, 0x5c, 0x5a, 0x58, 0x56, 0x54, 0x52, 0x50,
0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x42, 0x40,
0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, 0x12, 0x10,
0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x00, //三角波数据点阵
};
void clrkey(); //清屏函数void init8279(); //初始化8279 void delay(int ms);
//延时函数
void sin(); //正弦波函数
void square(); //方波函数
void sanjiaobo(); //三角波函数
void juchibo(); //锯齿波函数
void dir(); //屏幕显示hello函数void main () //主函数
{
clrkey();
init8279();
dir();
EA=1;
EX1=1;
IT1=1;
while(1)
{
switch(boxing)
{
case 1:{
delay(4500*(10-f)) ;
P1=0x00;
delay(4500*(10-f));
P1=10*v;} break;
case 2:{
for (i=0;i<255;i++)
{
delay(10-f);
P1=0.1*v*juchitab[i];
}
} break;
case 3:{
for(i=0;i<255;i++)
{
delay(10-f);
P1=0.1*v*sanjiaotab[i];
}
}break;
case 4:{
for(i=0;i<255;i++)
{
delay(10-f);
P1=0.1*v*sintab[i];
}
}break;
}
}
}
void dir() //显示hello
{
uint i,j;
com8279=0x90; //1001 0000 写显示用RAM for(i=0;i<8;i++)
{
data8279=hello[i];
}
return;
}
void delay(uchar Ms) //延时Ms*10us
{
uchar data i;
for(;Ms>0;Ms--)
for(i=26;i>0;i--);
}
void init8279() //8279初始化
{
com8279=0xd1; //送清除命令
do
{
s=com8279;
}
while(s&0x80==1);//等待清除结束
com8279=0x2a; //设定分频系数 10
com8279=0x00; //8个字符左端入口方式键盘显示扫描方式 com8279=0x80; //写显示RAM命令,地址不自动加1
}
void clrkey() //清显示屏
{
uchar i;
com8279=0xD1;
i=com8279;i&=0x80;
while(i==0x80)
{
i=com8279;
i&=0x8279;
}
}
void square(void) /* 方波发生函数 */
{
com8279=0xd1; //送清除命令
com8279=0x90; //写显示RAM命令,地址自动加1
data8279=duanma[1]; //第一位显示数字"1",
data8279=0x40; //第二位显示"-"
data8279=0x71; //f段码第三位显示f
data8279=duanma[f]; //第四位显示改变频率数字 data8279=0x00; //第五位不显示data8279=0x00; //第六位不显示
data8279=0x3e; //u //第七位显示U
data8279=duanma[v]; //第八位显示改变电压数字
}
void juchibo(void) //锯齿波函数发生器
{
com8279=0xd1; //送清除命令
com8279=0x90; //写显示RAM命令,地址自动加1
data8279=duanma[2]; //第一位显示2,表示锯齿波
data8279=0x40; //第二位显示-
data8279=0x71; //f段码第三位显示F,表示频率
data8279=duanma[f]; //400hz 第四位显示要改变的频率 data8279=0x00; // 第五位不显示
data8279=0x00; //第六位不显示
data8279=0x3e; //第七位显示U
data8279=duanma[v]; //第八位显示要改变的电压
}
void sanjiaobo(void) //三角波发生函数
{
com8279=0xd1; //送清除命令
com8279=0x90; //写显示RAM命令,自动加1
data8279=duanma[3]; //第一位显示3,表示三角波
data8279=0x40; //第二位显示-
data8279=0x71; //f段码第三位显示F,表示频率
data8279=duanma[f]; // 第四位显示改变频率数字
data8279=0x00; //200hz 第五位
data8279=0x00; // 第六位不显示
data8279=0x3e; // 第七位显示U表示电压
data8279=duanma[v]; // 第八位显示改变电压数字}
void sin(void) //正弦波函数发生函数
{
com8279=0xd1; //送清除命令
com8279=0x90; //写显示RAM命令,地址自动加1
data8279=duanma[4]; //第一位显示4表示正弦波
data8279=0x40; //第二位显示-
data8279=0x71; //f段码第三位显示F
data8279=duanma[f]; //第四位显示输入
data8279=0x00; //第五位不显示
data8279=0x00; //第六位不显示
data8279=0x3e; //第七位显示U
data8279=duanma[v]; //第八位显示输入
}
int1() interrupt 2
{
uchar keyval;
com8279=0x40; //读FIFO命令地址自动加1
keyval=data8279; //读出键值
switch(keyval) //键值判断程序
{
case 0xdf:{square();boxing=1;}break; //方波case 0xd7:{juchibo();boxing=2;}break; //锯齿波case 0xcf:{sanjiaobo();boxing=3;}break; //三角波case 0xc7:{sin() ;boxing=4;}break; //正弦波case 0xc9: ;break;
case 0xca: ;break;
case 0xde:
{
f=f+1;
com8279=0x90;
data8279=0x71; //F
data8279=0x00;
data8279=0x00;
data8279=duanma[f];
if(f==10)
f=0;}break;
case 0xdd:
{
f=f-1;
com8279=0x90;
data8279=0x71;
data8279=0x00;
data8279=0x00;
data8279=duanma[f];
if(f==0)
f=10;}break;
case
0xd6:{v=v+1,com8279=0x90;data8279=0x3e,data8279=0x00;data8279=0x 00;data8279=0x00;data8279=0x00;
data8279=0x00;data8279=0x00;data8279=duanma[v];if(v==10)
v=0;} ;break;
case
0xd5:{v=v-1,com8279=0x90;data8279=0x3e,data8279=0x00;data8279=0x 00;data8279=0x00;data8279=0x00;
data8279=0x00;data8279=0x00;data8279=duanma[v];if(v==0)
v=10;} ;break;
case 0xc5: com8279=0xd1;com8279=0x90;break;
}
}
四、调试
用keil将c语言程序生成hex文件,导入仿真图的单片机中,运行仿真。

通过键盘对波形控制,利用示波器进行观察。

1.初始显示
2.方波
(1)初始“1”代表方波
(2)改变频率
增大频率
减小频率(3)改变幅值
增大幅值减小幅值
3.锯齿波
4.三角波
5.正弦波
锯齿波、三角波、正弦波的幅值频率调节效果类似于方波,在此不作演示。

五、新增功能与实现方法
欲添加一个梯形波,由于找不到合适的实现梯形波的函数或点阵,没有实现;另外有想添加电压表实现对波形电压值的测量,但是没有什么实际意义。

在本次设计中不作其它附加功能的添加。

六.总结与体会
首先,在我看来,单片机的课程设计是非常必要的。

我们学了一个学期的单片机课程,但没有实际地去运用单片机,因此对单片机没有深入的理解。

只有真正使用单片机去完成一个功能的实现,我们才会对单片机有一个本质的把握。

课程设计给了我们这样一个机会,因此我们应该把握住这个机会,认认真真地去完成自己的课程设计。

当看到“波形发生器”的课题时,感觉上是挺熟悉的。

单片机波形发生器在单片机设计的课题中不算新的课题,实现起来难度也不会太大。

但是老师在题目中明确给了要求,要采用8279接口4*8键盘及8位LED显示器。

这其实是增加了设计的难度。

一般的设计者估计会用LCD显示波形数据,因为这样可以大大减少键盘的数量,减少芯片的使用和简化程序。

对键盘的检测和控制是单片机设计中的一大重点和难点,我能体会到老师的用意。

我和队友在刚开始设计的时候也是觉得有些困难。

8279和38译码器还好,
因为在课本上有资料可考,对照课本上的连线图大致能解决。

难点在于D/A转换器的连线。

我们通过查阅资料,了解D/A转换器各引脚的功能,然后一步步完成了D/A转换器与单片机的接线。

其实这个设计的最大好处在于,D/A转换器转换器和8279是分开独立工作的,这样就使得设计大大简化了。

再接上运放和示波器,输出部分很快就完成了。

键盘的检测和控制部分比较明朗,可以直接对照教材上的图加以改动完成。

再完成与单片机的连接之后,硬件部分便完成了。

最大的工作在于C程序的设计。

因为要完成4种波形的设计,而且还要实现幅值、频率的调节。

首先我们要确定大致的框架,然后再一步步完成每一个子程序。

程序众多,难免发生错误和遗漏,我们就会一行一行地查找错误。

终于程序可以运行的时候,我们又发现我们在调节频率的同时,幅值也会改变。

经过认真查找,我们发现问题在于我们程序中实现波形的函数。

方波没有问题,正弦波用的查表发也没有问题。

锯齿和三角波使用的函数方法实现y=i,这样在改变频率时幅值也受影响。

我们决定用实现正弦波的方法来实现锯齿波和三角波,幸运的是锯齿波和三角波的点阵我们可以直接查到,省去了很多工作。

改用了查表法之后,波形幅值、频率的调节就完美的实现了。

在做本次课程设计的过程中,我感触最深的当属查阅大量的设计资料了。

为了让自己的设计更加完善,查阅这方面的设计资料是十分必要的,同时也是必不可少的。

我们是在做单片机课程设计,但我们不是艺术家,他们可以抛开实际尽情在幻想的世界里翱翔,而我们一切都要有据可依,有理可寻,不切实际的构想永远只能是构想,永远无法升级为设计。

其次,在这次课程设计中,我们运用到了以前所学的专业课知识,如:protues制图、C语言、模拟和数字电路知识等。

虽然过去从未独立应用过它们,但在学习的过程中带着问题去学我发现效率很高,这是我做这次课程设计的又一收获。

后,要做好一个课程设计,就必须做到:在设计程序之前,对所用单片机的内部结构有一个系统的了解,知道该单片机内有哪些资源;要有一个清晰的思路和一个完整的的软件流程图;在设计程序时,不能妄想一次就将整个程序设计好,反复修改、不断改进是程序设计的必经之路。

要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便;在设计课程过程中遇到问题是很正常德,但我们应该将每次遇到的问题记录下来,并分析清楚,以免下次再碰到同样的问题的课程设计结束了,但是从中学到的知识会让我受益终身。

发现、提出、分析、解决问题和实践能力的提高都会受益于我在以后的学习、工作和生活中。

设计过程,好比是我们人类成长的历程,常有一些不如意,但毕竟这是第一次做,难免会遇到各种各样的问题。

在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。

我们通过查阅大量有关资料,并在小组中互相讨论,交流经验和自学,若遇到实在搞不明白的问题就会及时请教老师,使自己学到了不少知识,也经历了不少艰辛,但收获同样巨大。

通过这次课程设计我也发现了自身存在的不足之处,虽然感觉理论上已经掌握,但在运用到实践的过程中仍有意想不到的困惑,经过一番努力才得以解决。

这也激发了我今后努力学习的兴趣,我想这将对我以后的学习产生积极的影响。

通过这次设计,我懂得了学习的重要性,了解到理论知识与实践相结合的重要意义,学会了坚持、耐心和努力,这将为自己今后的学习和工作做出了最好
的榜样。

我觉得作为一名自动化专业的学生,单片机的课程设计是很有意义的。

更重要的是如何把自己平时所学的东西应用到实际中。

虽然自己对于这门课懂的并不多,很多基础的东西都还没有很好的掌握,觉得很难,也没有很有效的办法通过自身去理解,但是靠着这一个多礼拜的“学习”,在小组同学的帮助和讲解下,渐渐对这门课逐渐产生了些许的兴趣,自己开始主动学习并逐步从基础慢慢开始弄懂它。

我认为这个收获应该说是相当大的。

觉得课程设计反映的是一个从理论到实际应用的过程,但是更远一点可以联系到以后毕业之后从学校转到踏上社会的一个过程。

小组人员的配合﹑相处,以及自身的动脑和努力,都是以后工作中需要的。

七、参考文献
1.《单片机原理、接口与应用》————肖看李群芳编著
2.《51单片机C语言教程》——————郭天祥编著
八、附录
电路图
程序已在前面给出,在此不重复。

九、结束语
感谢老师这个学期的辛苦工作,感谢老师放弃假期休息给我们做课程设计的面试。

希望老师在以后的教学、工作和生活中事事顺利。

希望同学们以后能有机会继续和老师合作。

相关文档
最新文档