一、实习目的与要求
学习51系列单片机的基本原理,并能熟练运用其基本功能。
用单片机和DS1302时钟芯片做一个实时时钟,用数码管显示年、月、日、星期、时、分、秒,利用独立键盘对其进行时间和日历调整。
二、51系列单片机的管脚介绍
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)这是由于上拉的缘故。
P3口也可作为AT89C51的一些特殊功能口,如下表所示:
口管脚 备选功能
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 /INT0(外部中断0)
P3.3 /INT1(外部中断1)
P3.4 T0(记时器0外部输入)
P3.5 T1(记时器1外部输入)
P3.6 /WR(外部数据存储器写选通)
P3.7 /RD(外部数据存储器读选通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
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:来自反向振荡器的输出。
三、DS1302的结构及工作原理
1、DS1302的介绍
现在流行的串行时钟电路很多,如DS1302、 DS1307、PCF8485等。这些电路的接口简单、价格低廉、使用方便,被广泛地采用。本文介绍的实时时钟电路DS1302是DALLAS公司的一种具有涓细电流充电能力的电路,主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。采用普通32.768kHz晶振。
DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
2、DS1302的引脚功能及结构
DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768kHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc≥2.5V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK始终是输入端。 图(1)为DS1302的封装图,图(2)为引脚说明图。
图(1)
图(2)
四、DS1302的操作
(1)DS1302的控制字节
DS1302 的控制字节如图2所示。控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
(2)数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
(3)DS1302的寄存器
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表1。
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。 DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
五、DS1302与CPU的连接
实际上,在调试程序时可以不加电容器,只加一个32.768kHz 的晶振即可。只是选择晶振时,不同的晶振,误差也较大。另外,还可以在上面的电路中加入DS18B20,同时显示实时温度。只要占用CPU一个口线即可。 LCD还可以换成LED,还可以使用北京卫信杰科技发展有限公司生产的10位多功能8段液晶显示模块LCM101,内含看门狗(WDT)/时钟发生器及两种频率的蜂鸣器驱动电路,并有内置显示RAM,可显示任意字段笔划,具有3-4线串行接口,可与任何单片机、IC接口。功耗低,显示状态时电流为2μA (典型值),省电模式时小于1μA,工作电压为2.4V~3.3V,显示清晰。
DS1302 与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM数据;D5~D1指定输入或输出的特定寄存器;最低位LSB(D0)为逻辑0,指定写操作(输入), D0=1,指定读操作(输出)。
在DS1302的时钟日历或RAM进行数据传送时,DS1302必须首先发送命令字节。若进行单字节传送,8位命令字节传送结束之后,在下2个SCLK周期的上升沿输入数据字节,或在下8个SCLK周期的下降沿输出数据字节。
DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;再一类为突发方式下的RAM寄存器,在此方式下可一次性读、写所有的RAM的31个字节。
要特别说明的是备用电源B1,可以用电池或者超级电容器(0.1F以上)。虽然DS1302在主电源掉电后的耗电很小,但是,如果要长时间保证时钟正常,最好选用小型充电电池。可以用老式电脑主板上的3.6V充电电池。如果断电时间较短(几小时或几天)时,就可以用漏电较小的普通电解电容器代替。
六、电路原理图
89C52管脚图
8位数码管的管脚
独立键盘
数码管段选限流电阻
单片机复位电路
单片机晶振电路
DS1302管脚及电路
七、总结及体会
DS1302 存在时钟精度不高,易受环境影响,出现时钟混乱等缺点。DS1302可以用于数据记录,特别是对某些具有特殊意义的数据点的记录,能实现数据与出现该数据的时间同时记录。这种记录对长时间的连续测控系统结果的分析及对异常数据出现的原因的查找具有重要意义。传统的数据记录方式是隔时采样或定时采样,没有具体的时间记录,因此,只能记录数据而无法准确记录其出现的时间;若采用单片机计时,一方面需要采用计数器,占用硬件资源,另一方面需要设置中断、查询等,同样耗费单片机的资源,而且,某些测控系统可能不允许。但是,如果在系统中采用时钟芯片DS1302,则能很好地解决这个问题。
这次实习让我受益匪浅,无论从知识上还是其他的各个方面。上课的时候的学习从来没有见过真正的单片机,只是从理论的角度去理解枯燥乏味。但在实习中见过甚至使用了单片机及其系统,能够理论联系实际的学习,开阔了眼界,提高了单片机知识的理解和水平。在这次课程设计中又让我体会到了合作与团结的力量,当遇到不会或是设计不出来的地方,我们就会在QQ群里讨论或者是同学之间相互帮助。团结就是力量,无论在现在的学习中还是在以后的工作中,团结都是至关重要的,有了团结会有更多的理念、更多的思维、更多的情感。
单片机是很重要的一门课程,老师和一些工作的朋友都曾说过,如果学好一门单片机,就凭这个技术这门手艺找一个好工作也不成问题。尽管我们在课堂学到的内容很有限,但在以后的学习中单片机还需要好好的深入研究和学习,学好了单片机也就多了一项生存的本钱。最后感谢老师对我们的精心指导和帮助,感谢同学们对我的帮助。
第二篇:51单片机生产实习报告
学 号 10780220
实习报告
起止日期: 2013 年 6 月 24 日 至 2013 年 7 月 19 日
计算机与信息工程学院
20##年 7 月 19 日
目录
第一章 系统开发与调试.............................................. 1
1.1生产实习介绍................................................ 1
1.1.1生产实习的目的......................................... 1
1.1.2生产实习的意义......................................... 1
1.1.3生产实习的重要性....................................... 1
1.2 单片机开发系统介绍.......................................... 2
1.2.1 STC12C5A60S2单片机.................................... 2
1.2.2 LCD1602............................................... 7
1.2.3 系统原理图............................................ 8
1.3单片机开发板的焊接.......................................... 9
1.3.1焊接操作要领及注意事项................................. 9
1.3.2注意事项.............................................. 10
第二章 开发板的调试与检测......................................... 12
2.1开发板硬件调试............................................. 12
2.2开发板软件调试............................................. 12
2.3测试程序................................................... 12
2.3.1流水灯................................................ 12
2.3.2数码管................................................ 13
2.3.3按键控制数码管........................................ 15
2.3.4 LCD1602显示.......................................... 16
2.3.5串口发送.............................................. 21
2.3.6串口接收.............................................. 23
2.3.7 A/D数模转换显示...................................... 25
第三章 开发板拓展应用............................................. 34
3.1利用蜂鸣器弹奏音乐......................................... 34
3.1.1蜂鸣器音调控制原理.................................... 34
3.1.2蜂鸣器弹奏音乐的程序.................................. 34
第四章 开发过程中遇见的问题现象以及解决方法....................... 40
4.1硬件问题................................................... 40
4.2软件问题................................................... 40
第五章 实习体会................................................... 40
第六章 参考文献................................................... 40
第一章 系统开发与调试
1.1生产实习介绍
1.1.1生产实习的目的
本次生产实习是学校教务规定,由电子信息工程教研室组织在电信楼实验室进行的一个单片机的开发、生产与应用的实习。此实习的目的旨在理论学习的基础上,通过完成一个涉及51单片机多种资源应用并具有综合功能的最小系统目标板的设计与编程应用,通过我们独立进行单片机开发板的焊接、调试以及应用扩展,提高我们的专业技能,为今后工作或是深造打好坚实的基础,让我们真正从这次实习中收获到对自己有价值的东西。
1.1.2生产实习的意义
此次生产实习是将理论知识与实际应用结合起来,从实际出发分析、研究和解决问题,将单片机的知识系统化,而且能对电子电路、电子元器件、印制电路板等方面的知识进一步加深认识,同时在软件编程、纠错、调试、焊接技术相关仪器设备的使用技能方面得到全面的锻炼和提高,为今后独立进行某些单片机应用系统的开发设计打下坚实基础。
1.1.3生产实习的重要性
生产实习是电子信息工程专业教学计划的一个重要部分,是培养学生理论学习与实践相结合的重要实践性教学环节。通过生产实习使学生了解实习单位的工作方式和工作流程;对以后大单片机课程设计,帝业设计做基础,了解一个开发板的开发制作的整个过程以及元器件的采购;对生产现场、生产过程中的电子信息设备、计算机设备的应用状况有较为深刻的认识,掌握常规电子信息设备的使用维护方法;在实践中进一步加强专业教育,了解本专业工程技术岗位和生产劳动岗位的工作情况和工作内容,培养团队精神和吃苦耐劳的精神;同时可以使学生学到企业的管理经验和工人师傅的艰苦创业精神,激励学生奋发向上的开拓精神。
1.2 单片机开发系统介绍
系统原理及功能介绍
1.2.1 STC12C5A60S2单片机
1.增强型8051 CPU,1T,单时钟/机器周期,指令代码完全兼容传统8051
2.工作电压:STC12C5A60S2系列工作电压:5.5V- 3.3V(5V单片机)STC12LE5A60S2系列工作电压:3.6V- 2.2V(3V单片机)
2.工作频率范围:0 - 35MHz,相当于普通8051的 0~420MHz
3.用户应用程序空间8K /16K / 20K / 32K / 40K / 48K / 52K / 60K / 62K字节......
4.片上集成1280字节RAM 6.通用I/O口(36/40/44个),复位后为:准双向口/弱上拉(普通8051传统I/O口) 可设置成四种模式:准双向口/弱上拉,推挽/强上拉,仅为输入/高阻,开漏 每个I/O口驱动能力均可达到20mA,但整个芯片最大不要超过55mA
5. ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器,无需专用仿真器 可通过串口(P3.0/P3.1)直接下载用户程序,数秒即可完成一片
6.有EEPROM功能(STC12C5A62S2/AD/PWM无内部EEPROM)
7. 看门狗
8.内部集成MAX810专用复位电路(外部晶体12M以下时,复位脚可直接1K电阻到地)
9.外部掉电检测电路:在P4.6口有一个低压门槛比较器5V单片机为1.32V,误差为+/-5%,3.3V单片机为1.30V,误差为+/-3%
10.时钟源:外部高精度晶体/时钟,内部R/C振荡器(温漂为+/-5%到+/-10%以内) 1用户在下载用户程序时,可选择是使用内部R/C振荡器还是外部晶体/时钟常温下内部R/C振荡器频率为:5.0V单片机为:11MHz~15.5MHz 3.3V单片机为: 8MHz~12MHz 精度要求不高时,可选择使用内部时钟,但因为有制造误差和温漂,以实际测试为准
11.共4个16位定时器 两个与传统8051兼容的定时器/计数器,16位定时器T0和T1,没有定时器2,但有独立波特率发生器做串行通讯的波特率发生器再加上2路PCA模块可再实现2个16位定时器
12. 2个时钟输出口,可由T0的溢出在P3.4/T0输出时钟,可由T1的溢出在P3.5/T1输出时钟
13.外部中断I/O口7路,传统的下降沿中断或低电平触发中断,并新增支持上升沿中断的PCA模块,Power Down模式可由外部中断唤醒,INT0/P3.2, INT1/P3.3, T0/P3.4, T1/P3.5, RxD/P3.0, CCP0/P1.3(也可通过寄存器设置到P4.2 ), CCP1/P1.4 (也可通过寄存器设置到P4.3)
14. PWM(2路)/PCA(可编程计数器阵列,2路)也可用来当2路D/A使用-也可用来再实现2个定时器也可用来再实现2个外部中断(上升沿中断/下降沿中断均可分别或同时支持)
15.A/D转换, 10位精度ADC,共8路,转换速度可达250K/S(每秒钟25万次) 18.通用全双工异步串行口(UART),由于STC12系列是高速的8051,可再用定时器或PCA软件实现多串口
16. STC12C5A60S2系列有双串口,后缀有S2标志的才有双串口,RxD2/P1.2(可通过寄存器设置到P4.2),TxD2/P1.3(可通过寄存器设置到P4.3)
16.工作温度范围:-40 - +85℃(工业级) / 0 - 75℃(商业级)
17.封装: PDIP-40,LQFP-44,LQFP-48 I/O口不够时,可用2到3根普通I/O口线外接 74HC164/165/595(均可级联)来扩展I/O口, 还可用A/D做按键扫描来节省I/O口,或用双CPU,三线通信,还多了串口。
STC12C5A60S2 为可电气烧录清洗的 8051 相容单芯片,其内部程序代码容量为4KB
STC12C5A60S2主要功能列举如下:
1、为一般控制应用的 8 位单芯片
2、晶片内部具时钟振荡器(传统最高工作频率可至 12MHz)
3、内部程式存储器(ROM)为 4KB
4、内部数据存储器(RAM)为 128B
5、外部程序存储器可扩充至 64KB
6、外部数据存储器可扩充至 64KB
7、32 条双向输入输出线,且每条均可以单独做 I/O 的控制
8、5 个中断向量源
9、2 组独立的 16 位定时器
10、1 个全多工串行通信端口
11、8751 及 8752 单芯片具有数据保密的功能
12、单芯片提供位逻辑运算指令
STC12C5A60S2
STC12C5A60S2各引脚功能介绍:
VCC:
STC12C5A60S2 电源正端输入,接+5V。
VSS:
电源地端。
XTAL1:
单芯片系统时钟的反相放大器输入端。
XTAL2:
系统时钟的反相放大器输出端,一般在设计上只要在 XTAL1 和 XTAL2 上接上一只石英振荡晶体系统就可以动作了,此外可以在两引脚与地之间加入一 20PF 的小电容,可以使系统更稳定,避免噪声干扰而死机。
RESET:
STC12C5A60S2的重置引脚,高电平动作,当要对晶片重置时,只要对此引脚电平提升至高电平并保持两个机器周期以上的时间,AT89S51便能完成系统重置的各项动作,使得内部特殊功能寄存器之内容均被设成已知状态,并且至地址0000H处开始读入程序代码而执行程序。
EA/Vpp:
"EA"为英文"External Access"的缩写,表示存取外部程序代码之意,低电平动作,也就是说当此引脚接低电平后,系统会取用外部的程序代码(存于外部EPROM中)来执行程序。因此在8031及8032中,EA引脚必须接低电平,因为其内部无程序存储器空间。如果是使用 8751 内部程序空间时,此引脚要接成高电平。此外,在将程序代码烧录至8751内部EPROM时,可以利用此引脚来输入21V的烧录高压(Vpp)。
ALE/PROG:
ALE是英文"Address Latch Enable"的缩写,表示地址锁存器启用信号。STC12C5A60S2可以利用这支引脚来触发外部的8位锁存器(如74LS373),将端口0的地址总线(A0~A7)锁进锁存器中,因为STC12C5A60S2是以多工的方式送出地址及数据。平时在程序执行时ALE引脚的输出频率约是系统工作频率的1/6,因此可以用来驱动其他周边晶片的时基输入。此外在烧录8751程序代码时,此引脚会被当成程序规划的特殊功能来使用。
PSEN:
此为"Program Store Enable"的缩写,其意为程序储存启用,当8051被设成为读取外部程序代码工作模式时(EA=0),会送出此信号以便取得程序代码,通常这支脚是接到EPROM的OE脚。AT89S51可以利用PSEN及RD引脚分别启用存在外部的RAM与EPROM,使得数据存储器与程序存储器可以合并在一起而共用64K的定址范围。
PORT0(P0.0~P0.7):
端口0是一个8位宽的开路汲极(Open Drain)双向输出入端口,共有8个位,P0.0表示位0,P0.1表示位1,依此类推。其他三个I/O端口(P1、P2、P3)则不具有此电路组态,而是内部有一提升电路,P0在当做I/O用时可以推动8个LS的TTL负载。如果当EA引脚为低电平时(即取用外部程序代码或数据存储器),P0就以多工方式提供地址总线(A0~A7)及数据总线(D0~D7)。设计者必须外加一锁存器将端口0送出的地址栓锁住成为A0~A7,再配合端口2所送出的A8~A15合成一完整的16位地址总线,而定址到64K的外部存储器空间。
PORT2(P2.0~P2.7):
端口2是具有内部提升电路的双向I/O端口,每一个引脚可以推动4个LS的TTL负载,若将端口2的输出设为高电平时,此端口便能当成输入端口来使用。P2除了当做一般I/O端口使用外,若是在STC12C5A60S2扩充外接程序存储器或数据存储器时,也提供地址总线的高字节A8~A15,这个时候P2便不能当做I/O来使用了。
PORT1(P1.0~P1.7):
端口1也是具有内部提升电路的双向I/O端口,其输出缓冲器可以推动4个LS TTL负载,同样地若将端口1的输出设为高电平,便是由此端口来输入数据。如果是使用8052或是8032的话,P1.0又当做定时器2的外部脉冲输入脚,而P1.1可以有T2EX功能,可以做外部中断输入的触发脚位。
PORT3(P3.0~P3.7):
端口3也具有内部提升电路的双向I/O端口,其输出缓冲器可以推动4个TTL负载,同时还多工具有其他的额外特殊功能,包括串行通信、外部中断控制、计时计数控制及外部数据存储器内容的读取或写入控制等功能。
其引脚分配如下:
P3.0:RXD,串行通信输入。
P3.1:TXD,串行通信输出。
P3.2:INT0,外部中断0输入。
P3.3:INT1,外部中断1输入。
P3.4:T0,计时计数器0输入。
P3.5:T1,计时计数器1输入。
P3.6:WR:外部数据存储器的写入信号。
P3.7:RD,外部数据存储器的读取信号。
STC12C5A60S2实体图
1.2.2 LCD1602
简介
1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
市面上字符液晶大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
管脚功能
1602采用标准的16脚接口,其中:
第1脚:VSS为电源地
第2脚:VCC接5V电源正极
第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会 产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。
第6脚:E(或EN)端为使能(enable)端,高电平(1)时读取信息,负跳变时执行指令。
第7~14脚:D0~D7为8位双向数据端。
第15~16脚:空脚或背灯电源。15脚背光正极,16脚背光负极
LCD1602管脚图
特性
3.3V或5V工作电压,对比度可调
内含复位电路
提供各种控制命令,如:清屏、字符闪烁、光标闪烁、显示移位等多种功能
有80字节显示数据存储器DDRAM
内建有192个5X7点阵的字型的字符发生器CGROM
8个可由用户自定义的5X7的字符发生器CGRAM
1.2.3 系统原理图
图1系统原理图
1.3单片机开发板的焊接
1.3.1焊接操作要领及注意事项
焊接操作要领
1.焊件表面处理
一般在焊接前焊件需要进行表面清理工作,去除焊接面上的锈迹,油污,灰尘等影响焊接质量的杂质。手工操作中常用机械刮磨和酒精,丙酮擦洗等简单易行的方法。
2.预焊
预焊就是将要锡焊的元器件引线或导电的焊接部位预先用焊锡润湿,一般也称为镀锡,上锡,搪锡等,靠金属的扩散形成结合层后而使焊件表面“镀”上一层焊锡。
预焊并非锡焊不可缺少的操作,但对手工烙铁焊接特别是维修,调试,研制工作几乎可以说是必不可少的。
3.不要用过量的焊剂
适量的焊剂是必不可缺的,但不要认为越多越好。过量的松香不仅造成焊后焊点周围需要清洗的工作量,而且延长了加热时间(松香融化,挥发需要并带走热量),降低工作效率;而当加热时间不足时又容易夹杂到焊锡中形成“夹渣”缺陷;对开关元件的焊接,过量的焊剂容易流到触点处,从而造成接触不良。
合适的焊剂量应该是松香水仅能浸湿将要形成的焊点,不要让松香水透过印制板流到元件面或插座孔里(如IC插座)。对使用松香芯的焊丝来说,基本不需要再涂焊剂。
4. 保持烙铁头的清洁
因为焊接时烙铁头长期处于高温状态,又接触焊剂等受热分解的物质,其表面很容易氧化而形成一层黑色杂质,这些杂质几乎形成隔热层,使烙铁头失去加热作用。因此要随时在烙铁架上蹭去杂质。用一块湿布或湿海绵随时擦烙铁头,也是常用的方法。
5. 加热要靠焊锡桥
非流水线作业中,一次焊接的焊点形状使多种多样的,我们不可能不断换烙铁头。要提高烙铁头加热的效率,需要形成热量传递的焊锡桥。所谓焊锡桥,就是靠烙铁上保留少量焊锡作为加热时烙铁头与焊件之间传热的桥梁。
显然由于金属液的导热效率远高于空气,而使焊件很快被加热到焊接温度,如图四。应注意作为焊锡桥的锡保留量不可过多。
6. 焊锡量要合适
过量的焊锡不但毫无必要地消耗了较贵的锡,而且增加了焊接时间,相应降低了工作速度。更为严重的是在高密度的电路中,过量的锡很容易造成不易察觉的短路。
但是焊锡过少不能形成牢固的结合,降低焊点强度,特别是在板上焊导线时,焊锡不足往往造成导线脱落。
7. 焊件要牢固
在焊锡凝固之前不要使焊件移动或振动,特别使用镊子夹住焊件时一定要等焊锡凝固再移去镊子。这是因为焊锡凝固过程是结晶过程,根据结晶理论,在结晶期间受到外力(焊件移动)会改变结晶条件,导致晶体粗大,造成所谓“冷焊”。外观现象是表面无光泽呈豆渣状;焊点内部结构疏松,容易有气隙和裂隙,造成焊点强度降低,导电性能差。因此,在焊锡凝固前一定要保持焊件静止,实际操作时可以用各种适宜的方法将焊件固定,或使用可靠的夹持措施。
8. 烙铁撤离有讲究
烙铁处理要及时,而且撤离时的角度和方向对焊点形成有一定关系。
撤烙铁时轻轻旋转一下,可保持焊点适当的焊料,这需要在实际操作中体会。
电子元器件插装的原则
插装的顺序 :先低后高,先小后大,先轻后重。
元器件的标识 :电子元器件的标记和色码部位应朝上,以便于辩认;横向插件的数值读法应从左至右,而竖向插件的数值读法则应从下至上。
元器件的间距在印制板上的元器件之间的距离不能小于1mm;引线间距要大于2mm(必要时,引线要套上绝缘套管)。一般元器件应紧密安装,使元器件贴在印制板上,紧贴的容限在0.5mm左右。
1.3.2注意事项
锡线是手工焊接电路板,最便捷的焊料,由于大部分锡线内含松香等助焊剂,使用锡线可以减少工序,提高焊接作业的效率;锡线按其金属成分可分为无铅焊锡和有铅焊锡,成分区别的锡线具有区别的熔点,用途亦各有区别。在使用的时候,必须符合相关的安全规定;只能由合格的技术人维修;如果不这样,在使用本设备的时候,可能导致意外事故。
运作以前,用锡线测温计先测定温度很重要。使用热回复性等热性能好的锡线,在使用无铅焊锡进行焊接作业时,由于对零件的耐热性,安全作业的考虑,有必要选定最合适的锡线,根据了解电烙铁的区别焊接作业的区别,选择最合适的烙铁头是很重要的。合适的烙铁头可以降低烙铁头的温度,增加作业的效率。烙铁头的维护也非常重要。
当心焊料烫伤,当心被飞溅的溶液状态的焊料烫伤。穿防护服避免烫伤。通过戴防护罩方式来保护眼睛。在焊接或拆焊过程中使用胶粘剂的时候,尤其要注意胶粘剂生产厂家的警告信息。如果配合空气净化器使用,必须确保空气净化器连接正常并处于正常的运作状态。不整洁的运作区间会增加意外事故发生的可能性。在不使用本设备的时候,请将本设备放回安全的地方。避免所有易燃物体靠近热的焊笔,包括气体和固体。
即使在关断电源或者取下烙铁头及套筒后,烙铁头和套筒仍然需要一段时间冷却。在焊接结束后,焊点及被焊接元器件仍然非常热。防止被电击,不要用手接触接地部位,如焊笔套筒,发热体等。儿童及未受培训的人不能靠近运作区间,绝不能允许其他未受培训的人使用或触摸电源线。
第二章 开发板的调试与检测
2.1开发板硬件调试
根据完成的电路板实现程序运行前,对电路板先进行检测,先测试开发板供电是否正常,插上电源看看供电指示灯是否正常点亮。然后再在程序的调试中测试个电路模块和器件是否能正常使用,这样以便快速准确找出错误并解决错误。例如首先可以测试电阻、二极管极性是否焊反,芯片有没出现虚焊的现象,以至于板子不能正常使用。
2.2开发板软件调试
STC12C5A60S2单片机可以实现多种的实验程序,例如LED指示灯实验;跑马灯实验;中断操作;A/D转换;按键输入实验等。调试过程中我们用的是Keil uvision2软件,其操作步骤如下:
(1)建立一个文件夹用来存放项目。
(2)(2)打开Keil软件,选择Project->New Project。
(3)选择Atmel->AT89S52->同意添加8051启动代码。
(4)(4)File->New (新建源文件,编程)->保存(汇编语言以.asm结尾;C语言以.C结尾)
(5)添加源文件到Project。
(6)生成.hex文件。
2.3测试程序
2.3.1流水灯
#include<reg51.h>
typedef unsigned int uint16;
//#define time 100
/*void ms (unsigned int x)
{
unsigned char i;
while(x--)
{
for(i=0;i<200;i++);
}
}*/
main()
{
int j,a1;
uint16 x;
//for(i=0;i<2;i++)
while(1)
{
a1=0xfe;
for(j=0;j<8;j++)
{
P1=a1;
//ms(time);
for(x=0;x<50000;x++);
P1=0xff;
for(x=0;x<50000;x++);
P1=a1;
for(x=0;x<60000;x++);
a1=(a1<<1)|0x01;
}
}
}
2.3.2数码管
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
void Delay(uint del)
{
uint i,j,k;
for(i=0; i<del; i++)
for(j=0; j<1000; j++)
for(k=0; k<1000; k++)
;
}
void main (void)
{
int i;
P1=0x00;//数码管点亮控制
while(1)
{
for(i=0;i<2;i++)
{
P0 = 0xfe;
Delay(1);
P0 = 0xfd;
Delay(1);
P0 = 0xfb;
Delay(1);
P0 = 0xf7;
Delay(1);
P0 = 0xef;
Delay(1);
P0 = 0xdf;
Delay(1);
P0 = 0xbf;
Delay(1);
P0 = 0x7f;
Delay(1);
}
for(i=0;i<2;i++)
{
P0 = 0x7f;
Delay(1);
P0 = 0xbf;
Delay(1);
P0 = 0xdf;
Delay(1);
P0 = 0xef;
Delay(1);
P0 = 0xf7;
Delay(1);
P0 = 0xfb;
Delay(1);
P0 = 0xfd;
Delay(1);
P0 = 0xfe;
Delay(1);
}
for(i=0;i<2;i++)
{
P0=0x00;
Delay(1);
P0=0xff;
Delay(1);
}
}
}
2.3.3按键控制数码管
#ifndef _ANJIAN_H_
#define _ANJIAN_H_
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef char int8;
typedef int int16;
sbit K0=P1^0;
sbit K1=P1^1;
sbit K2=P1^2;
sbit K3=P1^3;
sbit K4=P1^4;
sbit K5=P1^5;
sbit K6=P1^6;
sbit K7=P1^7;
sbit WL1=P2^3;
sbit WL2=P2^2;
sbit WL3=P2^1;
sbit WL4=P2^0;
#endif
2.3.4 LCD1602显示
#include "reg51.h"
#include"absacc.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
/* 液晶1602口地址 */
#define wr_com XBYTE[0xC000] //写命令
#define wr_data XBYTE[0xC100] //写数据
#define rd_com XBYTE[0xC200] //读命令
#define rd_data XBYTE[0xC300] //读数据
void lcd_init(void); // lcd初始化
void write_cmd(BYTE cmd); // lcd写命令
//void write_string(unsigned char *s); // 写字符串
void write_data(BYTE dat) ; // 写数据
void set_display_place(BYTE line,column);
void write_string_lcd(BYTE line,column,unsigned char *string);
//void write_data_lcd(BYTE line,column,dat);
//void crti(unsigned long dat);
//void crt_r(float x,BYTE N);
void Delay(WORD n)
{
WORD x;
while(n--)
{
x=500;
while(x--);
}
}
/*
void Delay2(WORD n)
{
WORD x;
while(n--)
{
x=5000;
while(x--);
}
}
*/
/************************************************************************
Function name: write_cmd
Descriptions: 向lcd输入指令
************************************************************************/
void write_cmd(BYTE cmd)
{
BYTE dl;
do {
dl=rd_com;
} while((dl&0x80)!=0); //判忙
wr_com= cmd;
Delay(1);
}
/**********************************************************************
Function name: write_data
Descriptions: 写入数据
**********************************************************************/
void write_data(BYTE dat)
{
BYTE dl;
do {
dl=rd_com;
} while((dl&0x80)!=0); //判忙
wr_data= dat;
Delay(1);
}
/***********************************************************************
Function name: write_string
Descriptions: 写入字符串
***********************************************************************/
void write_string(BYTE *s)
{
while(*s != '\0') //'\0'为字符串结束标志
{
write_data(*s);
s++;
}
}
/**********************************************************************
Function name: set_display_place
Descriptions: 设置字符的显示位置
**********************************************************************/
void set_display_place(BYTE line,column)
{
BYTE address;
if(line == 1)
{
address = 0x80 + column;
}
else if(line == 2)
{
address = 0xc0 + column;
}
write_cmd(address);
}
/*******************************************************************
Function name: 将字符串写到指定的位置
Descriptions: 将字符串显示在lcd的特定位置
*******************************************************************/
void write_string_lcd(BYTE line,column,unsigned char *string)
{
set_display_place(line,column);
write_string(string);
Delay(1);
}
/******************************************************************
Function name: 将字符写到指定的位置
Descriptions: 将字符串显示在lcd的特定位置
*******************************************************************/
/*void write_data_lcd(BYTE line,column,dat)
{
set_display_place(line,column);
write_data(dat);
Delay(1);
}
*/
/***************************************************
************液晶模块初始化******************************
****************************************************/
void lcd_init(void)
{
write_cmd(0x38);//
write_cmd(0x38);//
write_cmd(0x06);//
write_cmd(0x0c);//
write_cmd(0x01);//
}
/*****************LED显示位置********************/
void main()
{
//SP=0x60;
lcd_init();
while(1)
{write_string_lcd(1,1," 0123456789 ");
write_string_lcd(2,1," ABCDEDGHIJ ");
}
}
2.3.5串口发送
/*串行发送*/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED1=P1^1;
sbit LED2=P1^2;
sbit K0=P1^0;
sbit K4=P1^4;
uchar Operation_No=0; //操作代码
uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //数码管代码
void delay(uint ms)
{
uchar i;
while(ms--);
for(i=0;i<120;i++);
}
//向串口发送字符
void Putc_to_SerialPort(uchar c)
{
SBUF=c;
while(TI==0); //收到时中断
TI=0; //清除中断
}
void uart_init()
{
SCON=0x50; //串口模式1,允许接收
TMOD=0x20; //T1工作模式2
PCON=0x00; //波特率不倍增
TH1=0xfd; //设置计数初值
TL1=0xfd;
TI=RI=0;
TR1=1; //启动定时器
IE=0x90; //允许串口中断
}
main()
{
uart_init();
K4=0;
LED1=LED2=1;
while(1)
{
delay(100);
if(K0==0)
{
while(K0==0)
Operation_No=(Operation_No+1)%4;
switch(Operation_No) //根据操作代码发送A/B/C或停止发送
{
case 0: Putc_to_SerialPort('X');
LED1=LED2=1;
break;
case 1: Putc_to_SerialPort('A');
LED1=~LED1;LED2=1;
break;
case 2: Putc_to_SerialPort('B');
LED2=~LED2;LED1=1;
break;
case 3: Putc_to_SerialPort('C');
LED1=~LED1;LED2=LED1;
break;
}
}
}
}
void uart_interrupt() interrupt 4
{
if(RI)
{
RI=0;
if(SBUF>=0&&SBUF<=10)
P0=DSY_CODE[SBUF];
else
P0=0x00;
}
}
2.3.6串口接收
/*串行接收*/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED1=P1^1;
sbit LED2=P1^2;
sbit K0=P1^0;
sbit K4=P1^4;
uchar numx=-1;
void delay(uint ms)
{
uchar i;
while(ms--);
for(i=0;i<120;i++);
}
void uart_init()
{
SCON=0x50; //串口模式1,允许接收
TMOD=0x20; //T1工作模式2
TH1=0xfd; //波特率9600
TL1=0xfd;
PCON=0x00; //波特率不倍增
RI=0;
TI=0;
TR1=1; //启动定时器
IE=0x90; //允许中断
}
main()
{
uart_init();
K4=0;
while(1)
{
delay(100);
if(K0==0)
{
while(K0==0);
numx=(numx+1)%11;
SBUF=numx;
while(TI==0);
TI=0;
}
}
}
void uart_interrupt() interrupt 4
{
if(RI)
{
RI=0;
switch(SBUF)
{
case 'X':LED1=LED2=1;break;
case 'A':LED1=0;LED2=1;break;
case 'B':LED2=0;LED1=1;break;
case 'C':LED1=LED2=0;
}
}
2.3.7 A/D数模转换显示
#include "reg51.h"
#include "intrins.h"
#include"absacc.h"
#include"math.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
/* AD .......... */
sfr P1ASF = 0x9D; //P1 ................
sfr ADC_CONTR = 0xBC; //AD ..........
sfr ADC_RES = 0xBD; //AD ............
sfr ADC_RESL = 0xBE; //AD ............
sfr AUXR1 = 0xA2; //AD ..............
#define ADC_POWER 0x80 //AD ............
#define ADC_FLAG 0x10 //AD ..........
#define ADC_START 0x08 //AD ..........
#define ADRJ1 0x40 //AD ............ 2 ..+.. 8 ..
#define ADC_SPEEDLL 0x00 //AD ..............540 ..........
#define ADC_SPEEDL 0x20 //AD ..............360 ..........
#define ADC_SPEEDH 0x40 //AD ..............180 ..........
#define ADC_SPEEDHH 0x60 //AD ..............90 ..........
/* .... 1602 ...... */
#define wr_com XBYTE[0xC000] //......
#define wr_data XBYTE[0xC100] //......
#define rd_com XBYTE[0xC200] //......
#define rd_data XBYTE[0xC300] //......
unsigned char ah;
unsigned char AD_val_h; //AD ............
unsigned char AD_val_l; //AD ............
unsigned long AD_val;
float AD_float;
void InitADC();
void SendData(BYTE dat);
//void GetADCResult(BYTE ch);
void Delay(WORD n);
void Delay2(WORD n);
void ShowResult(BYTE ch);
void lcd_init(void); // lcd ......
void write_cmd(BYTE cmd); // lcd ......
//void write_string(unsigned char *s); // ........
void write_data(BYTE dat) ; // ......
void set_display_place(BYTE line,column);
void write_string_lcd(BYTE line,column,unsigned char *string);
/********************************************************************
Function name: write_cmd
Descriptions: .. lcd ........
********************************************************************/
void write_cmd(BYTE cmd)
{
BYTE dl;
do {
dl=rd_com;
} while((dl&0x80)!=0); //....
wr_com= cmd;
Delay(1);
}
/*******************************************************************
Function name: write_data
Descriptions: ........
*******************************************************************/
void write_data(BYTE dat)
{
BYTE dl;
do {
dl=rd_com;
} while((dl&0x80)!=0); //....
wr_data= dat;
Delay(1);
}
/********************************************************************
Function name: write_string
Descriptions: ..........
********************************************************************/
void write_string(BYTE *s)
{
while(*s != '\0') //'\0'................
{
write_data(*s);
s++;
}
}
/***************************************************************
Function name: set_display_place
Descriptions: ..................
**************************************************************/
void set_display_place(BYTE line,column)
{
BYTE address;
if(line == 1)
{
address = 0x80 + column;
}
else if(line == 2)
{
address = 0xc0 + column;
}
write_cmd(address);
}
/*****************************************************************
Function name: ......................
Descriptions: .............. lcd ..........
*****************************************************************/
void write_string_lcd(BYTE line,column,unsigned char *string)
{
set_display_place(line,column);
write_string(string);
Delay(1);
}
/***************************************************
************..............******************************
****************************************************/
void lcd_init(void)
{
write_cmd(0x38);//
write_cmd(0x38);//
write_cmd(0x06);//
write_cmd(0x0c);//
write_cmd(0x01);//
}
void crti(unsigned long dat)
{
unsigned char dhi;
unsigned char dli;
unsigned char ddi;
unsigned char dei;
unsigned long datah;
unsigned long datal;
datah=dat;
dhi=0;
if (datah>=10)
{
do
{
datah/=10;
dhi++;
}while(datah>=10);
datah=dat;
ddi=dhi;
for (dli=0;dli<dhi;dli++)
{
datal=1;
for (dei=0;dei<ddi;dei++)
{
datal*=10;
}
datah=dat/datal;
dat=dat%datal;
datah+=0x30;
write_data(datah);
ddi--;
}
dat+=0x30;
write_data(dat);
}
else
{
dat=dat+0x30;
write_data(dat);
}
}
/*****************..........****************/
void crt_r(float x,unsigned char N)
{
unsigned char dli;
unsigned int dath;
unsigned int dat;
if (x<0.0)
{
dat=0x2d;
write_data(dat);
Delay(1);
x=fabs(x);
}
dath=(int)x;
crti(dath);
if (N>0)
{
dat=0x2e;
write_data(dat);
Delay(1);
dat=1;
for (dli=0;dli<N;dli++)
{
dat*=10;
}
dath=(int)(x*dat)-dath*dat;
crti(dath);
}
}
void crt_U()
{
write_string_lcd(2,0, "U:");
set_display_place(2,3);
crt_r(AD_float,3);
}
void GetADCResult(BYTE ch) //AD ....
{
AUXR1 &=~ADRJ1;
ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ch|ADC_START;
_nop_();
_nop_();
_nop_();
_nop_();
while(!(ADC_CONTR & ADC_FLAG));
ADC_CONTR &=~ADC_FLAG;
AD_val_h=ADC_RES;
AD_val_l=ADC_RESL;
AD_val=AD_val_h*4+AD_val_l;
}
void InitADC()
{
P1ASF=0xff;
ADC_RES=0;
ADC_CONTR=ADC_POWER|ADC_SPEEDLL;
Delay(1);
}
void Delay(WORD n)
{
WORD x;
while(n--)
{
x=500;
while(x--);
}
}
void Delay2(WORD n)
{
WORD x;
while(n--)
{
x=5000;
while(x--);
}
}
void main()
{
SP=0x60;
InitADC();
lcd_init();
AUXR1 &=~ADRJ1;
while(1)
{
write_string_lcd(1,2, "P1.7");
GetADCResult(7);
AD_float=AD_val*5.0/1024.0;
crt_U();
Delay2(10);
}
}
第三章 开发板拓展应用
3.1利用蜂鸣器弹奏音乐
3.1.1蜂鸣器音调控制原理
通过调整PWM的占宽比来实现蜂鸣器的音调控制,并通过LED灯的点亮来模拟音调的高低,高音灯亮的多,低音灯亮的少。
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
脉宽调制(PWM)基本原理:控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,即可改变逆变电路输出电压的大小,也可改变输出频率。
与占宽比对应的是占空比,占宽比是高电平的时间在整个一个周期内所占时间的比重。占宽比越高,通电时间越长,所产生的音调越高,而与之相反,占空比越高,音调越低,所以把不同的占宽比设定为特殊的音阶,就能实现音乐的播放,由于方波与蜂鸣器,所以产生的音乐不是很好,音调比较尖锐。
3.1.2蜂鸣器弹奏音乐的程序
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar Count;
sbit Speak =P1^2; //蜂鸣器器控制脚
sbit P36=P3^6;
sbit RS=P2^5;
unsigned char code LED[8]={0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00};
/*以下数组是音符编码*/
unsigned char code SONG[] ={ //祝你平安
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,
0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,
0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,
0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,
0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,
0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,
0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,
0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,
0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,
//路边的野华不要采
0x30,0x1C,0x10,0x20,0x40,0x1C,0x10,0x18,0x10,0x20,0x10,0x1C,0x10,0x18,0x40,0x1C,
0x20,0x20,0x20,0x1C,0x20,0x18,0x20,0x20,0x80,0xFF,0x20,0x30,0x1C,0x10,0x18,0x20,
0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,
0x30,0x80,0xFF,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,
0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,0x10,0x20,
0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x15,0x1F,
0x05,0x20,0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,
0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,
0x20,0x26,0x20,0x20,0x20,0x30,0x30,0x20,0x30,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20,
0x20,0x26,0x40,0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,0x80,0x00,
};
/********************************************************************
* 名称 : Time0_Init()
* 功能 : 定时器的初始化,定时时间可用光碟中软件计算,11.0592MZ晶振,10ms
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Time0_Init()
{
TMOD = 0x01;
IE = 0x82;
TH0 = 0xDC;
TL0 = 0x00;
}
/********************************************************************
* 名称 : Time0_Int()
* 功能 : 定时器中断,中断中实现 Count 加一
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Time0_Int() interrupt 1
{
TH0 = 0xDC;
TL0 = 0x00;
Count++; //长度加1
}
/********************************************************************
* 名称 : Delay_xMs()
* 功能 : 延时子程序,经过软件调试,测得延时程序大概为55us.
* 输入 : x
* 输出 : 无
***********************************************************************/
void Delay_xMs(uint x)
{
uint i,j;
for(i=0; i<x; i++)
{
for(j=0; j<3; j++);
}
}
/********************************************************************
* 名称 : Play_Song()
* 功能 : 播放蜂鸣器控制程序
* 输入 : i (选择播放哪首歌曲,0为“祝你平安”,1为“路边的野花你不要采”
* 输出 : 无
***********************************************************************/
void Play_Song(uchar i)
{
uchar Temp1,Temp2;
int a;
uint Addr;
Count = 0; //中断计数器清0
Addr = i * 217;
while(1)
{
Temp1 = SONG[Addr++]; //音符地址加一
if (Temp1 == 0xFF) //休止符
{
TR0 = 0;
Delay_xMs(100);
}
else if (Temp1 == 0x00) //歌曲结束符
{
return;
}
else
{
Temp2 = SONG[Addr++]; //街拍地址加一 注释: 音符地址始终是偶数 节拍地址是奇数
TR0 = 1;
while(1)
{
Speak = ~Speak; //音符① 这两句话是确定音符的
a=(int)(Temp1/8); // LED 一 有音符判断LED亮多少
if(a>=0&&a<8)
P0=LED[a]; // LED 二 让LED亮相应的个数
else (P0=0xfc);
Delay_xMs(Temp1); //音符② 一二组合确定音符
if(Temp2 == Count) //有Temp2 判断节拍
{
Count = 0;
break;
}
}
}
}
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main()
{
RS=1;
P36=0;
Time0_Init(); //定时器0中断初始化
while(1)
{
Play_Song(0); //Play_Song(0)为祝你平安 Play_Song(1)为路边的野花你不要裁
Play_Song(1);
}
第四章 开发过程中遇见的问题现象以及解决方法
4.1硬件问题
数码管显示少一个,四个只有3个显示,最后重新拿焊锡补了下发现虚焊,经过调试发现无误。
测试LCD1602显示的时候字体全是黑框,怎么往外拧都是黑的,然后把可变电阻往里拧了次,发现居然变暗了,显示出了字体。
4.2软件问题
最后扩展的时候,蜂鸣器音乐演奏没问题,但是LED灯显示功放大小的显示,出现了问题,后来发现,是设定音阶的时候出现了问题,更正已无误
第五章 实习体会
通过这次实习,我们通过手动的焊接,虽然以前焊接过万用表,但是这个板子明显比那个万用表复杂许多,而且,单片机的板子各种焊接都才尝试了,如底座,针脚与插板还有贴片的焊接。而软件测试则实现了许多功能,以前只能在书本上的知识得到了实现、编辑以及应用,从而带动了我们的兴趣。让我们对于本专业有了更深的理解,和对于前进的方向有了明确的认识,让我们对自己的未来有着充分的信心。
第六章 参考文献
[1] 张毅刚等.单片机原理机应用[M].高等教育出版社,2008
[2] 何立民主编.MCS-51单片机原理机应用系统设计.北京航空航天大学出版社,1990
[3] 涂时亮,单片机软件设计技术.重庆:科学文献出版社重庆分社,1987
[4]李广弟等.单片机基础[M].北京航空航天出版社,2001.
[5]王东峰等.单片机C语言应用100例[M].电子工业出版社,2009.
[6]陈海宴.51单片机原理及应用[M].北京航空航天大学出版社,2010.
[7]刘守义等.单片机技术基础[M].西安电子科技大学出版社,2007.
[8]钟富昭等.8051单片机典型模块设计与应用[M].人民邮电出版社,2007.
[9]李平等.单片机入门与开发[M].机械工业出版社,2008.