单片机原理及应用课程设计--信号发生器
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
武汉纺织大学
单片机原理及应用课程设计
姓名:向彬彬
学号: 1103751068
班级:光电1102班
指导教师:邹崇涛
所在院系:电子与电气工程学院
2013年12月
精选文档
目录
1 设计目的及要求 (3)
1-1 设计目的 (3)
1-2 设计要求 (3)
2 方案设计 (3)
2-1 总体方案设计 (3)
2-1.1 系统原理分析 (3)
2-2 硬件电路设计 (4)
2-2.1 主要芯片介绍 (4)
2-3 软件设计 (7)
2-3.1 软件程序流程图 (7)
2-3.2 发送数据子程序 (8)
2-3.3 波形产生过程 (8)
3 Protues仿真......................................................... . (9)
4 调试及实验结果 (10)
5 实验中遇到的问题 (12)
5-1 错误 (12)
5-2 不足 (12)
6 心得体会 (12)
7 参考文献 (13)
附录程序清单......................................................... . (14)
精选文档
基于STC89C52的信号发生器课程设计报告1设计目的及要求
1-1 设计目的
(1) 掌握各个接口芯片(如DAC0832等)的功能特性及接口方法,并能运用其实现一个简单的微机应用系统功能器件。
(2) 以单片机为基础,设计并开发能输出多种波形(正弦波、三角波、方波等)且频率可变的函数发生器。
(3) 利用所学单片机的理论知识进行软硬件整体设计,锻炼我们理论联系实际、提高我们的综合应用能力。
(4) 通过运用相关芯片实现信号发生器的功能,从而达到熟练掌握各种器件的目的,同时,锻炼动手能力及编程调试能力,更深地理解课上所学的单片机的知识,增加电子电路知识,提升作为一个电子信息工程专业学生的专业素养
1-2 设计要求
(1)用单片机加之DAC芯片等器件,实现能产生方波,三角波,正弦波且频率可变的信号发生器。
(2)熟悉各个器件的性能和使用方法,特别是89c52,掌握他们之间的连接和数据传输方法,能够熟练使用它们及编写程序。
(3)完成单片机和DAC的选型,了解不同波形的产生原理和设计方案,画出硬件电路图,并编程完成软件部分,最后调试观察产生不同类型的波形信号。
2方案设计
2-1 总体方案设计
通过要求分析,以下几点是解题的关键:
用单片机加之DA芯片,实现能产生方波,三角波,正弦波信号发生器
掌握89c51和DAC0832转换芯片之间的连接和数据传输方法,熟练使用它们及编写程序
2-1.1系统原理分析
数字信号可以通过数/模转换器转换成模拟信号,因此可通过产生数字信号再转换成模拟信号的方法来获得所需要的波形。
89C52单片机本身就是一个完整的微型计算机,具有组成微型计算机的各部分部件:中央处理器CPU、随机存取存储器RAM、只读存储器ROM、I/O 接口电路、定时器/计数器以及串行通讯接口等,只要将89C51再配置键盘及、数模转换及波形输出、放大电路等部分,即可构成所需的波形发生器,其信号发生器构成系统框图如下图所示。
精选文档
图1 系统框图
2-2 硬件电路设计
2-2.1主要芯片介绍
1 单片机STC89C52介绍
STC89C52是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash存储器。
STC89C52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能。
在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,3个16 位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口。
另外 STC89C52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。
空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
最高运作频率35MHz,6T/12T可选。
外形及引脚排列如下图所示:
AT89C51管脚说明:
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 STC89C52引脚图
2 DAC0832介绍:
1) DAC0832是8分辨率的D/A转换集成芯片。
与微处理器完全兼容。
这个DA芯片以其价格低廉、接口简单、转换控制容易等优点,在单片机应用系统中得到广泛的应用。
D/A 转换器由8位输入锁存器、8位DAC寄存器、8位D/A转换电路及转换控制电路构成。
图中,VDD和AGND为电源端和接地端,DIN,OUT 为数据输入端和输出端,REFIN应给予2.7-5.5v的参考电压,此电压根据所需波形的复制而定。
精选文档
2) 5616的十六位数据值包括两部分:
D0~D7:8位数据输入线,TTL电平,有效时间应大于90ns(否则锁存器的数据会出错) ILE:数据锁存允许控制信号输入线,高电平有效;
CS:片选信号输入线(选通数据锁存器),低电平有效;
WR1:数据锁存器写选通输入线,负脉冲(脉宽应大于500ns)有效。
由ILE、CS、WR1的逻辑组合产生LE1,当LE1为高电平时,数据锁存器状态随输入数据线变换,LE1的负跳变时将输入数据锁存;
XFER:数据传输控制信号输入线,低电平有效,负脉冲(脉宽应大于500ns)有效;
WR2:DAC寄存器选通输入线,负脉冲(脉宽应大于500ns)有效。
由WR2、XFER的逻辑组合产生LE2,当LE2为高电平时,DAC寄存器的输出随寄存器的输入而变化,LE2的负跳变时将数据锁存器的内容打入DAC寄存器并开始D/A转换。
IOUT1:电流输出端1,其值随DAC寄存器的内容线性变化;
IOUT2:电流输出端2,其值与IOUT1值之和为一常数;
Rfb:反馈信号输入线,改变Rfb端外接电阻值可调整转换满量程精度;
Vcc:电源输入端,Vcc的范围为+5V~+15V;
VREF:基准电压输入线,VREF的范围为-10V~+10V;
AGND:模拟信号地;
DGND:数字信号地。
图3 DAC0832芯片引脚图
3)硬件连接
如图4,是DAC0832与51单片机的连接方式。
精选文档
图4 DAC0832与单片机连接图
3 LCD1602介绍
工业字符型液晶,能够同时显示16x02即32个字符。
(16列2行)
1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。
它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
市面上字符液晶大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
图5 LCD1602引脚图
4 LM324介绍
LM324系列器件带有差动输入的四运算放大器。
与单电源应用场合的标准运算放大器相比,它们有一些显著优点。
该四放大器可以工作在低到3.0伏或者高到32伏的电源下,静态电流为MC1741的静态电流的五分之一。
共模输入范围包括负电源,因而消除了在许多应用场合中采用外部偏置元件的必要性。
每一组运算放大器可用图6所示的符号来表示,它有5个引出脚,其中“+”、“-”为两个信号输入端,“V+”、“V-”为正、负电源端,“Vo”为输出端。
两个信号输入端中,Vi-(-)为反相输入端,表示运放输出端Vo的信号与该输入端的位相反;Vi+(+)为同相输入端,表示运放输出端Vo的信号与该输入端的相位相同。
精选文档
精选文档
图6 LM324芯片引脚图 2-3
软件设计 2-3.1 软件程序流程图如下:
需要明确的是,该设计最核心的部分是信号发生部分,要想完成此设计,最先应该设计
的是怎样产生各种波形,只有产生了波形,才会有后续进行精确地调试,产生完波形后,需要完成单片机与DAC0832之间的数据通信,编写程序,可以先编写该程序进行数据传送的调试。
初始化开始
根据地址标志位查表
while 循环
输出数字量给DAC0832数据口
根据a,b,c,d,e 的值进入相
应的while 循环地址标志位加1
地址标志位是
否等于64否
地址标志位置0
相应延时(对应频
率)
图7 程序流程图
2-3.2发送数据子程序:
DAC0832单缓冲方式是控制输入寄存器和DAC寄存器同时接收资料,或者只用输入寄存器而把DAC寄存器接成直通方式。
此方式适用只有一路模拟量输出或几路模拟量异步输出的情形。
2-3.3波形产生过程
1)方波产生过程
方波的实现只需开始的时候设置一个初值然后直接输出这个值就行了,输出一段时间后,然后再重新置一个数据,然后再输出这个数据一段时间,但是此时的时间一定要等于前面那段时间。
这样才是一个方波。
由此可以调节两个电压维持的时间,产生占空比不同的方波,相比于模拟电驴,这样的方式输出的方波占空比更加精确,且电压更加稳定。
2)三角波产生过程
三角波的输出的基础是锯齿波,将锯齿波的产生当作是三角波的前半部分,然后再相反的举行减法,逐渐减为零,如此循环,即可产生三角波。
类似的,通过改变延时时间可以改变输出的频率,通过改变最大值,可以改变输出的电压。
输出的波形连续性好,且波形很光滑。
3)正弦波产生过程
正弦波的实现实际上是一个查表过程,所查的每一个值都对应着一个电压,并且对应着的电压汇成图形即为正弦波,然后重复这样一个过程即可产生连续的正弦波.产生的正弦波,波形光滑且频率可调。
3Protues仿真
1 仿真连接图
精选文档
图8 仿真连接图 2 仿真波形图
图9 三角波仿真图
精选文档
精选文档
图10 方波仿真图
图11 正弦波仿真图
4调试及实验结果
1 开始时,我们并未接低通滤波电路。
因此所得到的波形误差很大,但是基本形状大致一样。
图12 实际方波图1
精选文档
图13 实际三角波图1
图14 实际正弦波图1
最终,我们加入低通滤波电路之后,所得到的波形图得到了很大的改善,但是由于我们设计的波形频率范围在1000Hz以下,所以还是有一些误差。
图15 修改后的实际三角波
精选文档
图16 修改后的实际方波
图17 修改后的实际正弦波
5实验中遇到的问题
5-1 错误
1)最初LCD1602显示错误,总是一排黑方块;后来通过搜索,终于知道是因为初始化程序有问题,改正之后正常显示。
2)在实验室调试波形时,最开始因为没有加低通滤波器,导致输出波形失真严重;后来加了低通滤波电路后,效果大大改善。
3)开始复位电路不起作用,后来经检查是因为线路连接时出现问题,最后复位电路正常。
5-2 不足
1)由于我们设计的低通滤波电路截止频率为1500Hz,而信号发生器的频率范围在1000Hz以下,因此还是有噪声的影响。
2)由于运放的参数是理想值,实际有差距,因此幅度误差比较大。
3)本设计只能频率可调,幅度无法调整。
6心得体会
通过这次课程设计,令我们对单片机有了更好的掌握,锻炼了我们的编程能力,在课程设计中,我们遇到的最大的挑战,就是对程序的调试,我们收获最大的地方也在于此,我们需要逐条运行每一小段调试程序,逐段逐句进行编程调试,我们尝试用汇编和C语言两种语言进行编程,将课上的学习的知识进行了运用。
在此次试验中,我们还深刻体会到了理论与
精选文档
现实的差别。
在Protues仿真中,只要将线路连接好后,所得的仿真结果便是理想中的波形,而现实中还必须考虑到电路中的噪声,电磁干扰等。
通过此次课程设计,我们真的学到了许多课堂上学不到的实战经验。
精选文档
7参考文献
《单片机原理与应用设计》,张毅刚,电子工业出版社, 2011年。
《单片微机原理及其接口技术》,胡汉才,清华大学出版社,2003年。
《单片机原理与应用》,孙亟芳,北京航空航天大学出版社,2004年。
《单片机程序设计基础》,周航慈,北京航空航天大学出版社,2001年。
附录
精选文档
程序清单
1 波形生成数组(PLTABLE.H)
#ifndef __PLTABLE_h__
#define __PLTABLE_h__
/***********这两组数组很重要,需要根据波形来调试,选择合适的值,使输出波形达到频率要求************/
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};
uchar code waveTL[]={
0x16,0x9a,0x20,0x5e,0x88,0xa3,0xb8,0xc3,0xce,0xd6, //正弦波频率调整中间值0xbc,0xce,0x58,0x8a,0xa9,0xbf,0xcb,0xd8,0xe0,0xee, //三角波频率调整中间值0x98,0x60,0xa0,0x42,0x44,0xce,0x5a,0xb3,0xf5,0x3c};
/****************************************************************************** *******************/
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 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};
#endif
2 键盘控制子程序(KEY.H)
#ifndef __KEY_h__
#define __KEY_h__
#include "adc0832.h"
#include "delay.h"
#include "lcd1602.h"
bit ST=0;
bit DUQU=0;
sbit key=P3^2;
unsigned char keytemp;
unsigned int total_freq; //总频率
void key_int0() interrupt 0
{
EA=0; TR0=0; //关总中断与定时器
delay(50); //延时够吗
if(key==0) //确实有按键按下而引发中断
{ delay(50);
if (key==0)
{
keytemp=P3&0xf8;
switch(keytemp)
{
case 0xf0: //选择波形
精选文档
waveform++;
if(waveform>2) waveform=0;
break;
case 0xe8: //频率按规定单位依次增加
wavefreq[waveform]++;
if(wavefreq[waveform]>10) wavefreq[waveform]=1;
break;
case 0xd8: //频率按规定单位依次衰减
wavefreq[waveform]--;
if(wavefreq[waveform]<1) wavefreq[waveform]=10;
break;
}
}
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;lcd_hang3[5]=total_freq%10+0x30; //在液晶中显示个位,(0x30 在液晶显示中表示数字0)
total_freq/=10;
lcd_hang2[4]=total_freq%10+0x30;lcd_hang3[4]=total_freq%10+0x30; //在液晶中显示
时十位
total_freq/=10;
lcd_hang2[3]=total_freq%10+0x30;lcd_hang3[3]=total_freq%10+0x30; //在液晶中显示
时百位
total_freq/=10; lcd_hang2[2]=total_freq%10+0x30;
精选文档
lcd_hang3[2]=total_freq%10+0x30;//在液晶中显示时千位
精选文档
disp_lcd(0x80,&lcd_hang1[waveform*16]); //在第一行显示
disp_lcd(0xc0,lcd_hang2); //在第二行显示
}
wavecount=0; //'抽点'计数清零
while(!key);
EA=1; TR0=1; //开启总中断与定时器
}
#endif
3 DAC0832数模转换子程序(DAC0832.H)
#ifndef __ADC0832_H__
#define __ADC0832_H__
#define DAdata P1 //DA数据端口
uchar wavecount; //'抽点'计数
uchar THtemp,TLtemp;//传递频率的中间变量
uchar judge=1; //在方波输出函数中用于简单判别作用
uchar waveform; //当其为0、1、2时,分别代表三种波
uchar code freq_unit[3]={5,25,100}; //三种波的频率单位
uchar idata wavefreq[3]={1,1,1}; //给每种波定义一个数组单元,用于存放单位频率的个数
sbit DA_S1= P2^7; // 控制DAC0832的8位输入寄存器,仅当都为0时,可以输出数据(处于直通状态),否则,输出将被锁存
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位输入寄存器
}
#endif
4 LCD1602显示子程序(LCD1602.H)
#ifndef __LCD1602_h__
#define __LCD1602_h__
#include "delay.h"
uchar code lcd_hang1[]={"ZX Wave " "SJ Wave " "JX Wave " "System Is Ready! " "Now to switch.." "SAVE ...... " "Finish! " "Reading ... " };
uchar idata lcd_hang2[16]={"F= Hz "};
uchar idata lcd_hang3[16]={"F= Hz . V"};
/************1602液晶的相关函数*************/
sbit rs=P2^0;
sbit rw=P2^1;
sbit lcden=P2^2;
sbit lcdbf=P0^7;
//sbit st=P2^1;
//sbit sh=P2^2;
//sbit ds=P2^0;
unsigned char i,j;
/*void LCD_Wait(void) //读忙状态
{
rs=0;
rw=1;
lcden=1;lcden=0; //下降沿
while(lcdbf);
{
精选文档
lcden=0;lcden=1; //仿真才需要此语句,实际硬件中不需要
}
delay(10);
}*/
void write_com(uchar dat)
{
//LCD_Wait();
lcden=0;
rs=0;
rw=0;
lcden=1;
P0=dat;
lcden=0;
delay(10);
}
void write_date(uchar date)
{
//LCD_Wait();
lcden=0;
rs=1;
rw=0;
lcden=1;
P0=date;
lcden=0;
delay(10);
}
void disp_lcd(uchar addr,uchar *temp1) reentrant
{
uchar num;
write_com(addr);
delay(1); //延时一会儿???
for(num=0;num<16;num++)
{
write_date(temp1[num]);//或者这样写write_date(*(temp1+num));
delay(1);
}
}
void init_lcd()
{
精选文档
//uchar num;
lcden=0; //可有可无???
rw=0; //初始化一定要设置为零,表示写数据
write_com(0x38); //使液晶显示点阵,为下面做准备
write_com(0x38);
write_com(0x0c); //初始设置
write_com(0x06); //初始设置
write_com(0x01); //清零
delay(10);
write_com(0x80); //使指针指向第一行第一格
disp_lcd(0x80,&lcd_hang1[3*16]); //在第一行显示
disp_lcd(0xc0,&lcd_hang1[4*16]); //在第二行显示
}
/********************1602液晶函数声明结束*********************/ #endif
5 延时子程序(DELAY.H)
#ifndef __DELAY_h__
#define __DELAY_h__
#define uchar unsigned char
#define uint unsigned int
void delay(uchar z)
{
uchar x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void delay5us()
{ uchar i;
for(i=1;i>0;i--) ;
}
#endif
6 主程序(main.c)
#include<reg52.h>
#include "lcd1602.h"
#include "delay.h"
#include "pltable.h"
#include "key.h"
#include "adc0832.h"
精选文档
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();
}
void main()
{
DAdata=0;
DA_S1=1; //关闭8位输入寄存器
init_lcd();
TMOD=0x01; //设置定时器0为16位工作方式IT0=1; //设置外部中断0为下降沿触发
ET0=1; //开定时器中断
EX0=1;
EA=1;
while(1) ;
}
. .
精选文档。