【www.scfx8.com--专业技术个人总结】

S-51单片机开发板设计 ---------《单片机及应用设计》实训报告 姓 名:

学 号:

班 级:

XX级电子信息工程专业本科班 学 院:

计算机电子信息工程学院 时 间:

2010年X月X日——X月X日 指导教师:

目录 一.前言 2 二.单片机及各模块简介 2 1.总体设计方案 2 2.硬件模块简介 3 2.1 S51单片机主控制模块 3 2.2 键盘模块 4 2.3 DS1302时钟模块 4 2.4 串口通信模块 5 2.5 LED数码管显示和流水灯模块 5 2.6下载线模块 6 2.7 蜂鸣器模块 6 2.8 其他模块 7 三.开发板(串口通信模块)设计原理介绍 7 1.实验项目要求 7 1.1元器件功能介绍 7 1.2串口通信原理 8 2.原理图的绘制 10 2.1串口通信模块仿真电路设计 10 3.程序的编写 11 3.1 keil操作过程 11 3.2程序框图 12 3.3USB模块电路原理图的绘制 12 四.印刷板的焊接及流程 14 焊接流程 14 五.调试及遭遇的问题解决方法 14 1.调试 14 1.1程序下载 14 1.2开发板调试 15 2.问题解决 15 六.体会 15 附录:

16 串口通信C语言源程序 16 一.前言 近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构软硬件结合,加以完善。

本次实训的主要目的就是为了学习单片机的基本理论知识,进而进行单片机的开发、实践和扩展,以更好的运用到实际的软硬件开发中去。此次单片机的实训目的如下:

(1)掌握单片机的相关理论知识。

学习单片机相关寄存器的配置,单片机内部结构及特点,存储器组织及外部接口,中断及串口功能,功能寄存器的相关配置,确定软硬件设计总体方案;

(2)掌握硬件设计和软件设计的基本知识,学会使用基本的设计软件,依据总体的设计方案对单片机进行软硬件开发。

在Protel中对单片机的各个功能模块进行外部电路的设计,在实现各个模块的功能的前提下充分合理利用单片机的内部资源和外围接口,以求最大限度的发挥单片机的功能。

学会使用Keil C进行编辑、编译及仿真调试,实现对单片机进行C语言开发。

以Proteus为平台,对单片机外围各个功能模块进行软件仿真验证功能。

(3)开发板板上资源的硬件实现及下载器的制作。

对软硬件设计仿真验证功能无误后,将Protel绘制的PCB进行加工、焊接元器件,制作出S51开发板及下载器。

二.单片机及各模块简介 1.总体设计方案 本开发板共分为十个模块,分别是:S51单片机主控制器模块、键盘模块、DS1302时钟模块、数码管模块、LCDCPS364BR模块、ARK点阵模块、下载器模块、流水灯模块、蜂鸣器模块、电源模块。其中以S51单片机作为核心控制器;

键盘模块用来向单片机输入特定编码的信息;

DS1302时钟模块用来实现实时时钟;

数码管模块用来显示简单的数字、字母;

LCD模块用来显示字母、数字、符号;

点阵模块用来显示图像、符号、汉字;

下载器模块用来实现S51单片机的ISP在线编程;

流水灯模块用来显示单片机I/O口电平的变化;

蜂鸣器模块用来发出声音。总体硬件电路如下图1所示:

图1 总体硬件电路 2.硬件模块简介 2.1 S51单片机主控制模块 S51单片机最小系统包括:MCU、复位电路、晶振电路。S51系列单片机内部具有128字节RAM、5个中断源、32条I/O口线、2个16位定时器、4KB的程序存储器、一个全双工异步串行口,具有ISP在线编程功能,该单片机不需要烧写器,可在开发板上ISP在线编程, S51单片机除兼容C51单片机外,还具有工作频率0至33MHz的高工作频率。

原理图如图2所示:

图2 主控制模块 2.2 键盘模块 按键模块,通过外部中断INT1实现按键功能,并通过软件编程识别按键K0---K3四个按键,进而实现相关功能,例如数码管显示字符数字的加减,LED灯速度的变换等。原理图如图3所示:

2.3 DS1302时钟模块 DS1302 的引脚如图4所示:

图3 按键模块 图4 DS1302引脚图 Vcc1为后备电源,Vcc2为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2高于Vcc1 + 0.2V时,Vcc2给DS1302供电。当Vcc2低于Vcc1时,DS1302由Vcc1 供电。X1、X2为振荡源,外接32.768 kHz晶振。I/O为串行数据输入/输出端(双向),SCL K为时钟输入端。RST是复位片选线,通过把RST输入驱动置为高电平来启动所有的数据传送。RST输入有两种功能:RST接通控制逻辑,允许地址/命令序列送入移位寄存器;

RST提供了终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许DS1302进行操作。如果在传送过程中置RST为低电平,则会终止此次数据传送,并且I/ O引脚变为高阻态。上电运行时,在Vcc高于2.5V之前,RST必须保持低电平。只有在SCL K为低电平时,才能将RST置为高电平。DS1302时钟模块的原理图如图5所示:

图5 DS1302时钟原理图 单片机与DS1302通过P1.1、P1.2、P1.3相连,分别为时钟信号线、输入输出线、复位信号线。DS1302的晶振引脚连接32768HZ的晶振。

2.4 串口通信模块 串口通信模块的原理图如图6所示:

图6 串口通信模块的原理图 单片机与MAX232通过P3.0、P3.1相连,分别为发送线、接收线,另外单片机要与MAX232共地。

2.5 LED数码管显示和流水灯模块 LED显示器有静态显示和动态显示两种显示方式。

LED静态显示方式:LED显示器工作于静态显示方式时,各位的共阴极(或共阳极)连接在一起并接地(或+5V);

每位的段选线(a~dp)分别与一个8位的锁存器输出相连。各个LED的显示字符一经确定,相应锁存器的输出将维持不变,直到显示另一个字符为止。

LED动态显示方式:在多位LED显示时,将所有位的段选线相应的并联在一起,有一个8位I/O口控制,形成段选线的多路复用。而各位的共阳极或共阴极分别由相应的I/O线控制,实现各位的分时选通。要各位LED能够显示出与本位相应的显示字符,就必须采用扫描显示方式,段选线上输出相应位要显示字节的段码。

流水灯模块包含8个LED灯,单片机的P0口接10K上拉电阻,八个LED的负极依次连接单片机P0口的8个引脚,八个LED的正极依次与510欧姆的排阻的八个端子相连。

LED数码管和流水灯模块原理图如图7:

图8 LCD数码管和流水灯模块 2.6下载线模块 下载器模块实现将USB信号转换为能通过SPI协议传输的信号,从而实现对单片机的编程。下载模块原理图如图9所示:

图9 下载线接口模块 图10 蜂鸣器模块 2.7 蜂鸣器模块 单片机的P1.4与Q1的基极通过1K欧姆电阻连接,当P1.4为高电平时,Q1导通,Q1的发射极与集电极导通,将发射极下拉为低电平,蜂鸣器两端出现电位差,蜂鸣器发声;

当P1.4为低电平时,Q1不导通,蜂鸣器两端没有电流流过,蜂鸣器不发声。

2.8 其他模块 I2C EEPROM模块用于程序或数据存储器的扩展功能,片外可最大扩展到64KB,地址为0000~FFFFH。此存储芯片支持电科擦除,即可写。

电源模块通过整流电桥实现交直流的转换功能,直接供单片机使用。

原理图如图11图12所示:

图11 电源模块 图12 I2C EEPROM模块 三.开发板(串口通信模块)设计原理介绍 1.实验项目要求 实验任务是通过串口通信实现单片机数据的自发自收以及双机通信功能,并且通过数码管循环显示0~F来表现其实现过程。

1.1元器件功能介绍 AT89S51: At89s51 是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。使用Atmel 公司高密度非 易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU和在系统可编程Flash,使得AT89S51为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。AT89S51具有以下标准功能:8k字节Flash,256字节RAM,32 位I/O口线,看门狗定时器,2个数据指针,三16位定时器/计数器,一个6向量2级中断结构,全双工串行口, 片内晶振及时钟电路。另外AT89S51 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工 作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。8位微控制器 8K 字节在系统可编程 Flash AT89S51。

RS232:RS232是由电子工业协会(Electronic Industries Association,EIA) 所制定的异步传输标准接口。对于一般双工通信,仅需几条信号线就可实现,如一条发送线、一条接收线及一条地线。

RS232与TTL电路之间需要进行电平和逻辑关系的变换。实现这种变换的方法可用分立元件,也可用集成电路芯片。MAX232芯片可完成TTL←→RS232双向电平转换。

MAX232:MAX232芯片是RS232标准接口芯片,使用+5v单电源供电。是PC机与单片机串口进行通讯的电平转换芯片。内部结构基本可分三个部分:

第一部分是电荷泵电路。由1、2、3、4、5、6脚和4只电容构成。功能是产生+12v和-12v两个电源,提供给RS232串口电平的需要。

第二部分是数据转换通道。由7、8、9、10、11、12、13、14脚构成两个数据通道。其中13脚(R1IN)、12脚(R1OUT)、11脚(T1IN)、14脚(T1OUT)为第一数据通道。8脚(R2IN)、9脚(R2OUT)、10脚(T2IN)、7脚(T2OUT)为第二数据通道。TTL/CMOS数据从T1IN、T2IN输入转换成RS232数据从T1OUT、T2OUT送到电脑DP9插头;

DP9插头的RS232数据从R1IN、R2IN输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。

第三部分是供电。15脚DNG、16脚VCC(+5V)。

图13 RS232芯片引脚图 图14 MAX232芯片引脚图 1.2串口通信原理 S-51单片机内部有一个全双工的串行接收和发射缓冲器(SBUFF),这两个在物理上独立的接收发射器,即可以接收也可以发射数据,但接收缓冲器只可以读出不能写入,而发送缓冲器只能写入不能读出,它们的地址是99H。这个通信口即可以用于网络通信,亦可以实现串行异步通信,还可以构成同步移位寄存器使用。如果在串行口的输入输出引脚上加上电平转换器,就可以方便的构成标准的RS-232接口。

S-51单片机串行口专用寄存器。SBUF为串行口的收发缓冲器,它是一个可寻址的专用寄存器,其中包含了接收器和发射器寄存器,可以实现全双工通信。但这两个寄存器具有同一地址(99H)。S-51的串行数据传输很简单,只要向缓冲器写入数据就可发送数据。而从接收缓冲器读出数据既可接收数据。串行通信寄存器SCON控制寄存器,它是一个可寻址的专用寄存器,用于串行数据通信的控制。

数据通信的传输方式:常用于数据通信的传输方式有单工、半双工、全双工和工方式。串行通信的两种通信形式,包括异步通信和同步通信。SCON控制寄存器是一个可寻址的专用寄存器,用于串行数据通信的控制,其结构格式如下:

表1 寄存器SCON结构 SCON D7 D6 D5 D4 D3 D2 D1 D0 SM0 SM1 SM2 REN TB8 RB8 TI RI 位地址 9FH 9EH 8DH 9CH 9BH 9AH 99H 98H 下面我们对个控制位功能介绍如下:

(1)SM0、SM1:串行口工作方式控制位 (2)SM2:多机通信控制位 多机通信是工作方式2和方式3,SM2位主要用于方式2和方式3。接收状态,当串行口工作方式2或3,以及SM2=1时,只有当接收到第9位数据(RB8)为1时,才把接收的前8位数据送入SBUF,且置位RI发出中断申请,否则会将收到的数据放弃。当SM2=0时,只有在接收到有效停止位时才启动RI,若没接收到有效停止位,则RI清“0”。在方式0中SM2应该为“0”。

REN:允许接收控制位。由软件置“1”时,允许接收;

软件置“0”时,不许接收。

TB8:在方式3和方式3中要发送的第9位数据,需要时用软件置位和清零。

TB8:在方式2和方式3中是接收到的第9位数据。在方式1时,如SM2=0,RB8接收到的停止位。在方式0中,不使用RB8。

TI:发送中断标志。由硬件在方式0发送完第8位时置“1”,或在其它方式中串行发送停止位的开始时置“1”。必须由软件清“0”。

RI:接收中断标志。由硬件在方式0串行发射第8位结束时置“1” B:特殊功能寄存器PCON PCON:主要是是CHMOS型单片机的电源控制而设置的专用寄存器 2.原理图的绘制 2.1串口通信模块仿真电路设计 (1)打开ISIS7professional窗口,执行菜单命令File new design,新建一个DEFAULT命名为“单片机串口通信自发自收.DSN”。

(2)在器件选择按钮单击“P”按钮,添加如表所示的原件:

单片机 AT89S51 电容CAP-ELEC CAP-POL MAX232 COMPIM 按钮 BUTTON 数码管 7SEG-MPX4-CA 74LS244 排阻 RX8 三极管 NPN 晶振 CRYSTAL (3)在ISIS原理图编辑窗口中,放置电源和地。布好线,设置好相应原件的参数。完成电骡图的设计。

(4)调试与仿真:加载生成的.HEX文件,进行调试,观察是否符合预期效果。

仿真效果图如图15所示:

图15 仿真效果图 3.程序的编写 3.1 keil操作过程 1).打开桌面上的keil软件:,下面新建一个工程,选择project->new新建一个名字叫“单片机串口通信”的工程,保存在事先创建的文件夹下,点击保存按钮。出现选择器件型号对话框:选择实验板上的所用芯片的型号atmel->at89s51 点击确定就建立完毕工程了。

2).添加代码文件到工程中,首先新建一个后缀为.C的源文件,点击开发环境中的file->new,新建c文件,然后点击保存按钮,注意一定要保存为后缀为.C的格式, 在开发环境中左边栏找到在source group1上右击选中,弹出添加文件对话框,如图:把单片机串口通信.c选中,点击ADD添加源文件到工程中。

3).点击按钮,编译你的代码,如果下面有错误提示,修改好后再次编译直到顺利通过编译为止。如图16所示:

图16 keil编译图 4).在target1上右击选择,出现如下对话框:.选择output栏,将一栏打上勾,这样编译通过之后就可以生成可以执行的下载文件(可执行文件后缀为hex),再次点击编译,生成可执行的代码串口通信.hex。

3.2程序框图 单片机通过MAX232与单片机通讯程序流程图17所示:

图17 单片机通过MAX232与PC机或单片机通讯程序流程图 单片机通过P3.0.和P3.1发送数据到单片机,单片机接收到数据后发送给单片机,并通过LED数码管显示出。

3.3USB模块电路原理图的绘制 (1)在D盘建立名为Protel的文件夹,在Protel的文件夹中建立名为USB.ddb设计数据库文件,新建原理图文件,命名为USB.sch。

(2)根据提供的usb原理图,自己画出原理图。电路中所有的元器件都可在Miscellaneous Devices.ddb、Protel DOS Schematic Libraries.ddb这两个元器件数据库中找。

(3)画完电路后,要按照图中元件参数逐个设置元件属性,元件要自动编号,并进行电气规则检查。设置某个元器件的属性的方法是双击该元器件出现对话框设置即可。原理图如图18所示:

图18 usb原理图 (4)最后形成该电路的网络表,为设计电路板做准备。

(5)根据仿真好的电路图,画出印刷电路板图。新建PCB文件,设置PCB设计环境和绘制印刷电路的版框。

(6)、打开所有要用到的PCB 库文件后,调入网络表文件和修改零件封装。布置零件封装的位置,进行自动布局。

(7)对所有过孔和焊盘补泪滴,放置覆铜区。

敷铜后的效果如图18所示:

图18 PCB原理图 四.印刷板的焊接及流程 焊接流程 1 、焊前准备 首先要熟悉所焊印制电路板的装配图,并按图纸配料,检查元器件型号、规格及数量是否符合图纸要求,并做好装配前元器件引线成型等准备工作。

2 、焊接顺序 元器件装焊顺序依次为:电阻器、电容器、二极管、三极管、集成电路、大功率管,其它元器件为先小后大。

3 、对元器件焊接要求 1 )电阻器焊接 按图将电阻器准确装人规定位置。尽量使电阻器的高低一致。焊完后将露在印制电路板表面多余引脚齐根剪去。

2 )电容器焊接 将电容器按图装人规定位置,并注意有极性电容器其 “ + ” 与 “ - ” 极不能接错。

3 )二极管的焊接 二极管焊接要注意阳极阴极的极性,不能装错;

发光二极管要与印刷版保持0.5cm距离。

4 )三极管焊接 注意 e 、 b 、 c 三引线位置插接正确;

焊接时间尽可能短,焊接时用镊子夹住引线脚,以利散热。

5 )集成电路焊接 首先按图纸要求,检查型号、引脚位置是否符合要求。焊接时先焊边沿的二只引脚,以使其定位,然后再从左到右自上而下逐个焊接。

6)usb接口和电源接口 找到正确位置,注意将其与印刷版焊接牢固,不松动。

五.调试及遭遇的问题解决方法 1.调试 1.1程序下载:开发板和PC机通过下载器连接,使用+5V电源给开发板供电。在PC机上安装ISP在线下载器驱动,打开烧写器软件,选择烧写单片机类型,加载FLASH,点击编程,即可把程序烧录到单片机中。

使用USB isp下载:请安装并打开progisp167\软件, 编程器及接口选择USBasp,usb默认,选择器件类型AT89S52,点击调入FLASH按钮,找到你刚才生成的LED.hex文件 将usb下载线一头连接电脑U口,另外一头连接实验板左上方的ISP下载口,(注意方向),点击自动,可以看到,编程成功, 1.2开发板调试:

(1)键盘模块实验效果:烧写.HEX文件到单片机,将JP7插上短路帽,按下键盘上的某一个键,LCD1602上显示该键对应的键值;

(2)DS1302时钟模块实验效果:烧写.HEX文件到单片机,插上LCD1602,液晶上显示秒、分、时;

(3)数码管模块实验效果:烧写LED动态显示.HEX文件到单片机,将J3上端插上短路帽,数码管显示从0开始计数 ;

(4)流水灯模块实验效果:烧写流水灯.HEX文件到单片机,流水灯显示几种不同的花型;

(5)蜂鸣器模块实验效果:烧写.HEX文件到单片机,蜂鸣器以一定的声音频率鸣叫。

2.问题解决 (1)印刷版焊完之后,无法烧入程序,总是出错。

经过分析后判断可能是单片机有的接口焊点虚焊所致,回去后,用电烙铁把单片机的管口查询焊接了一遍。问题就解决了,能够烧入程序了。

(2)数码管显示的是乱码,并非完整数字。

分析应该是数码管编码与实际所用的编码或引脚不相同。对程序中的数码管显示代码重新编译之后就通过了。

六.总结体会 在老师的指导下,自己找资料、看书,完成了老师布置的任务。通过这次的实训设计,使我对单片机以及智能仪器的结构和功能都有了更深的认识,从理论和实践上都得到了很大的提高,这次的实训真的给我很大的提高。总结经验来说,首先,我丰富了自己的知识面,将以前没能学通的东西深入透彻的学会学懂,具体了解了怎样去完成一个电路的设计:从流程图、电路图、焊接电路板、检查电路板、仿真到烧片一整套东西。没有浪费宝贵的时间,学习到了难得的经验。

自己找资料,了解单片机89S51、数码显示管的有关知识,学习时钟电路、控制电路的设计原理,看不懂的时候就去问老师、同学。和同学们一起探讨不懂得难点之时我仿佛感觉到了真正的大学应该有的学习氛围。在这些都搞得比较明白后就开始画设计流程图和电路图,最后用了很长时间才画出自己的电路图,同学老师都帮我检查,改正了几处有问题的地方。电路的焊接比较难。要细心稳重,应为这是一件很要求技术的工作。但是我克服困难终于完成了但接下来的检测可就费了不少劲,发现并解决了很多问题。在解决完所有问题后,自己又一种成功感,还在想,要是没有这些错误,就不会学会这么多检测电路的方法,而且对自己所做的电路有了进一步的了解。做到这一步满以为不会再有什么错误了,但是仿真的时候却又遇到了马麻烦,先是数码管不亮,在后来就是全亮,按键后没反应,刚有的一点成功感马上就没了,又一次陷入了反复的检测。检测发现了不少问题,解决后仿真成功。在后来就开始烧片,烧片的过程还算顺利。烧好后插上电路板,显示成功了。接下来的工作一切还算顺利,在老师还有同学的帮助下,都一一完成。

这次的实训设计总的来说还是很成功的,自己从中学到很多,也发现了不少问题,为自己以后的学习、进步打下了不错的基础。从实训设计中,学到了单片机AT89C51的内部结构及其工作原理,了解了串口通信的工作原理,还有共阳极数码管的工作原理,巩固了C语言的使用能力,提高了自己动手的能力,学到了很多经验,并且提高了自己分析问题的能力和创新能力,得到了理论联系实际的机会,做出了成果。使自己在硬件设计方面树立了信心,为以后从事这方面的工作打好了基础,这也是这次实训设计的最大收获。

附录:

串口通信C语言源程序 /********单片机自发自收程序**********/ #include #define uchar unsigned char #define uint unsigned int sbit P2_0=P2^0; sbit P2_1=P2^1; sbit P2_2=P2^2; sbit P2_3=P2^3; sbit P2_4=P2^4; sbit P2_5=P2^5; sbit P2_6=P2^6; sbit P2_7=P2^7; uchar code dsy[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x88,0x83,0xc6,0xa1,0x86,0x8e,}; /*** 实验板数码管的编码 ***/ signed int a; void delay(uint n) //延时程序 {uint j; uchar k; for(j=0;j0) a=a-1; else a=15; break; } //按键2 ,减一个数 default:break; } }

《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

《单片机C语言程序设计实训100例—基于8051+Proteus仿真》案例

第 01 篇 基础程序设计

01 闪烁的LED

/* 名称:闪烁的LED */ #include #define uchar unsigned char #define uint unsigned int sbit LED=P1^0; //延时

void DelayMS(uint x) { uchar i; while(x--) { 说明:LED按设定的时间间隔闪烁

for(i=0;i

} while(1) {

} LED=~LED; DelayMS(150);

02 从左到右的流水灯

/* 名称:从左到右的流水灯

说明:接在P0口的8个LED从左到右循环依次点亮,产生走马灯效果 */ #include #include #define uchar unsigned char #define uint unsigned int

1 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

//延时

void DelayMS(uint x) {

uchar i; while(x--) { for(i=0;i

}

03 8只LED左右来回点亮

/* 名称:8只LED左右来回点亮

说明:程序利用循环移位函数_crol_和_cror_形成来回滚动的效果 */ #include #include #define uchar unsigned char #define uint unsigned int //延时

void DelayMS(uint x) { uchar i;

while(x--) { } for(i=0;i

DelayMS(150); } } //主程序 void main() {

uchar i; P2=0x01; while(1) {

2 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

}

} for(i=0;i

} DelayMS(150); 04 花样流水灯

/* 名称:花样流水灯

说明:16只LED分两组按预设的多种花样变换显示 */ #include #define uchar unsigned char #define uint unsigned int uchar code Pattern_P0[]= {

0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xe7,0xdb,0xbd,0x7e,0xbd,0xdb,0xe7,0xff,0xe7,0xc3,0x81,0x00,0x81,0xc3,0xe7,0xff, 0xaa,0x55,0x18,0xff,0xf0,0x0f,0x00,0xff,0xf8,0xf1,0xe3,0xc7,0x8f,0x1f,0x3f,0x7f, 0x7f,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xf8,0xff,0x00,0x00,0xff,0xff,0x0f,0xf0,0xff,

0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe, 0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe, 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff }; uchar code Pattern_P2[]= { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0xff, 0xe7,0xdb,0xbd,0x7e,0xbd,0xdb,0xe7,0xff,0xe7,0xc3,0x81,0x00,0x81,0xc3,0xe7,0xff, 0xaa,0x55,0x18,0xff,0xf0,0x0f,0x00,0xff,0xf8,0xf1,0xe3,0xc7,0x8f,0x1f,0x3f,0x7f, 0x7f,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xf8,0xff,0x00,0x00,0xff,0xff,0x0f,0xf0,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f, 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00, 0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

3 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff }; //延时

void DelayMS(uint x) {

uchar i; while(x--) { } for(i=0;i

uchar i; while(1) { //从数组中读取数据送至P0和P2口显示

} for(i=0;i

} P0=Pattern_P0[i]; P2=Pattern_P2[i]; DelayMS(100); }

05 LED模拟交通灯

/* 名称:LED模拟交通灯

说明:东西向绿灯亮若干秒,黄灯闪烁5次后红灯亮, 红灯亮后,南北向由红灯变为绿灯,若干秒后南北向黄灯闪烁5此后变红灯,东西向变绿灯,如此重复。

*/ #include #define uchar unsigned char #define uint unsigned int sbit RED_A=P0^0;

//东西向灯 sbit YELLOW_A=P0^1; sbit GREEN_A=P0^2; sbit RED_B=P0^3;

//南北向灯

sbit YELLOW_B=P0^4; sbit GREEN_B=P0^5; uchar Flash_Count=0,Operation_Type=1; //闪烁次数,操作类型变量

4 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

//延时

void DelayMS(uint x) { uchar i; while(x--) for(i=0;i

case 1: //东西向绿灯与南北向红灯亮

RED_A=1;YELLOW_A=1;GREEN_A=0;

RED_B=0;YELLOW_B=1;GREEN_B=1;

DelayMS(2000);

Operation_Type=2;

break;

case 2: //东西向黄灯闪烁,绿灯关闭

DelayMS(300);

YELLOW_A=~YELLOW_A;GREEN_A=1;

if(++Flash_Count!=10) return; //闪烁5次

Flash_Count=0;

Operation_Type=3;

break;

case 3: //东西向红灯,南北向绿灯亮

RED_A=0;YELLOW_A=1;GREEN_A=1;

RED_B=1;YELLOW_B=1;GREEN_B=0;

DelayMS(2000);

Operation_Type=4;

break;

case 4: //南北向黄灯闪烁5次

DelayMS(300);

YELLOW_B=~YELLOW_B;GREEN_B=1;

if(++Flash_Count!=10) return;

Flash_Count=0;

Operation_Type=1; } } //主程序 void main() { while(1) Traffic_Light(); }

06 单只数码管循环显示0~9 上海师范大学信息与机电工程学院—倪继锋

5 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

/* 名称:单只数码管循环显示0~9 */ #include #include #define uchar unsigned char #define uint unsigned int uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //延时

void DelayMS(uint x) { uchar t; while(x--) for(t=0;t

} uchar i=0; P0=0x00; while(1) {

} P0=~DSY_CODE[i]; i=(i+1)%10; DelayMS(300); 说明:主程序中的循环语句反复将0~9的段码送至P0口,使数字0~9循环显示

07 8只数码管滚动显示单个数字

/* 名称:8只数码管滚动显示单个数字

说明:数码管从左到右依次滚动显示0~7,程序通过每次仅循环选通一只数码管 */ #include #include #define uchar unsigned char #define uint unsigned int uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //延时

void DelayMS(uint x) { uchar t; while(x--) for(t=0;t

6 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

} //主程序 void main() { uchar i,wei=0x80; while(1) {

for(i=0;i

{

P2=0xff;

//关闭显示

wei=_crol_(wei,1);

P0=DSY_CODE[i]; //发送数字段码

P2=wei;

//发送位码

DelayMS(300);

} } }

08 8只数码管动态显示多个不同字符

电路如上图

/* 名称:8只数码管动态显示多个不同字符

说明:数码管动态扫描显示0~7。

*/ #include #include #define uchar unsigned char #define uint unsigned int uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //延时

void DelayMS(uint x) { uchar t; while(x--) for(t=0;t

for(i=0;i

{

P0=0xff;

P0=DSY_CODE[i]; //发送段码 wei=_crol_(wei,1); 上海师范大学信息与机电工程学院—倪继锋

7 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

P2=wei;

//发送位码

DelayMS(2);

} } }

09 8只数码管闪烁显示数字串

电路如上图

/* 名称:8只数码管闪烁显示数字串

说明:数码管闪烁显示由0~7构成的一串数字

本例用动态刷新法显示一串数字,在停止刷新时所有数字显示消失。

*/ #include #define uchar unsigned char #define uint unsigned int //段码表

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //位码表

uchar code DSY_IDX[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //延时

void DelayMS(uint x) { uchar t; while(x--) for(t=0;t

for(i=0;i

{

for(j=0;j

{

P0=0xff;

P0=DSY_CODE[j]; //发送段码

P2=DSY_IDX[j]; //发送位码

DelayMS(2);

}

}

P2=0x00;

//关闭所有数码管并延时

DelayMS(1000); } } 上海师范大学信息与机电工程学院—倪继锋

8 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

10 8只数码管滚动显示数字串

电路如上图

/* 名称:8只数码管滚动显示数字串 说明:数码管向左滚动显示3个字符构成的数字串 */ #include #include #define uchar unsigned char #define uint unsigned int //段码表

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //下面数组看作环形队列,显示从某个数开始的8个数(10表示黑屏) uchar Num[]={10,10,10,10,10,10,10,10,2,9,8}; //延时

void DelayMS(uint x) { uchar t; while(x--) for(t=0;t

for(i=0;i

{

for(j=0;j

{ //发送段码,采用环形取法,从第k个开始取第j个

P0=0xff;

P0=DSY_CODE[Num[(k+j)%11]];

m=_crol_(m,1);

P2=m; //发送位码

DelayMS(2);

}

}

k=(k+1)%11; //环形队列首支针k递增,Num下标范围0~10,故对11取余

} }

11 K1-K4 控制LED移位

/* 名称:K1-K4 控制LED移位 说明:按下K1时,P0口LED上移一位;

上海师范大学信息与机电工程学院—倪继锋

9 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

*/

按下K2时,P0口LED下移一位;

按下K3时,P2口LED上移一位;

按下K4时,P2口LED下移一位;

#include #include #define uchar unsigned char #define uint unsigned int //延时

void DelayMS(uint x) { uchar i; while(x--) for(i=0;i

//根据P1口的按键移动LED void Move_LED() {

if

((P1&0x10)==0) P0=_cror_(P0,1); //K1 else if((P1&0x20)==0) P0=_crol_(P0,1); //K2 else if((P1&0x40)==0) P2=_cror_(P2,1); //K3

//K4 else if((P1&0x80)==0) P2=_crol_(P2,1); } //主程序

void main() { uchar Recent_Key; //最近按键

} P0=0xfe; P2=0xfe; P1=0xff; Recent_Key=0xff; while(1) {

} if(Recent_Key!=P1) {

} Recent_Key=P1;

//保存最近按键 Move_LED(); DelayMS(10);

12 K1-K4 按键状态显示

10 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

/* 名称:K1-K4 按键状态显示

说明:K

1、K2按下时LED点亮,松开时熄灭,

*/ #include #define uchar unsigned char #define uint unsigned int sbit LED1=P0^0; sbit LED2=P0^1; sbit LED3=P0^2; sbit LED4=P0^3; sbit K1=P1^0; sbit K2=P1^1; sbit K3=P1^2; sbit K4=P1^3; //延时

void DelayMS(uint x) { uchar i; while(x--) for(i=0;i

K

3、K4按下并释放时LED点亮,再次按下并释放时熄灭;

} //主程序 void main() {

}

13 K1-K4 分组控制LED

11 上海师范大学信息与机电工程学院—倪继锋 P0=0xff; P1=0xff; while(1) {

} LED1=K1; LED2=K2; if(K3==0) { while(K3==0); } LED3=~LED3; if(K4==0) {

} while(K4==0); LED4=~LED4; DelayMS(10); 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

/* 名称:K1-K4 分组控制LED 说明:每次按下K1时递增点亮一只LED,全亮时再次按下则再次循环开始,

K2按下后点亮上面4只LED,K3按下后点亮下面4只LED,K4按下后关闭所有LED */ #include #define uchar unsigned char #define uint unsigned int //延时

void DelayMS(uint x) { uchar i; while(x--) for(i=0;i

uchar k,t,Key_State; P0=0xff; P1=0xff; while(1) {

t=P1; if(t!=0xff) {

DelayMS(10); if(t!=P1) continue; //取得4位按键值,由模式XXXX1111(X中有一位为0,其他均为1) //变为模式0000XXXX(X中有一位为1,其他均为0) Key_State=~t>>4; k=0; //检查1所在位置,累加获取按键号k while(Key_State!=0) { k++; Key_State>>=1; } //根据按键号k进行4种处理 switch(k) {

case 1:

if(P0==0x00) P0=0xff; P0

12 case 2:

上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

}

}

}

} case 3: case 4: P0=0x0f;break; P0=0xff; 14 K1-K4 控制数码管移位显示

/* 名称:K1-K4 控制数码管移位显示

说明:按下K1时加1计数并增加显示位,

按下K2时减1计数并减少显示位,

按下K3时清零。

*/ #include #define uchar unsigned char #define uint unsigned int //段码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //位码

uchar code DSY_Index[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //待显示到各数码管的数字缓冲(开始仅在0位显示0,其他黑屏) uchar Display_Buffer[]={0,10,10,10,10,10,10,10}; //延时

void DelayMS(uint x) { uchar i; while(x--) for(i=0;i

void Show_Count_ON_DSY() { uchar i; for(i=0;i

{ P0=0xff; P0=DSY_CODE[Display_Buffer[i]];

} P2=DSY_Index[i]; DelayMS(2); } //主程序 void main() { uchar i,Key_NO,Key_Counts=0;

13 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

P0=0xff; P1=0xff; P2=0x00; while(1) {

} Show_Count_ON_DSY(); P1=0xff; Key_NO=P1; //P1口按键状态分别为K1-0xfe,K2-0xfd,K3-0xfb switch(Key_NO) {

case 0xfe:

Key_Counts++; if(Key_Counts>8) Key_Counts=8; Display_Buffer[Key_Counts-1]=Key_Counts; break; if(Key_Counts>0)Display_Buffer[--Key_Counts]=10; break; Display_Buffer[0]=0; for(i=1;i

case 0xfb:

} //若键未释放则仅刷新显示,不进行键扫描 while(P1!=0xff) Show_Count_ON_DSY(); }

15 K1-K4 控制数码管加减演示

/* 名称:K1-K4 控制数码管加减演示

说明:按下K1后加1计数,按下K2后减1计数,按下K3后清零。

*/ #include #include #define uchar unsigned char #define uint unsigned int //段码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //待显示的3位缓冲 uchar Num_Buffer[]={0,0,0}; //按键代码,按键计数 uchar Key_Code,Key_Counts=0; //延时

void DelayMS(uint x) {

14 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

uchar i; while(x--) for(i=0;i

//显示函数

void Show_Counts_ON_DSY() { uchar i,j=0x01; Num_Buffer[2]=Key_Counts/100; Num_Buffer[1]=Key_Counts/10%10; Num_Buffer[0]=Key_Counts%10; for(i=0;i

j=_cror_(j,1);

P0=0xff;

P0=DSY_CODE[Num_Buffer[i]];

P2=j; DelayMS(1); } } //主程序 void main() { uchar i; P0=0xff; P1=0xff; P2=0x00; Key_Code=0xff; while(1) {

Show_Counts_ON_DSY();

P1=0xff;

Key_Code=P1;

//有键按下时,数码管刷新显示30次,该行代码同时起到延时作用

if(Key_Code!=0xff)

for(i=0;i

switch(Key_Code)

{

case 0xfe: if(Key_Counts

break;

case 0xfd: if(Key_Counts>0) Key_Counts--;

break;

case 0xfb: Key_Counts=0;

}

Key_Code=0xff; } 上海师范大学信息与机电工程学院—倪继锋

15 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

}

16 4X4矩阵键盘控制条形LED显示

/* 名称:4X4矩阵键盘控制条形LED显示

说明:运行本例时,按下的按键值越大点亮的LED越多。

*/ #include #include #define uchar unsigned char #define uint unsigned int //矩阵键盘按键特征码表

uchar code KeyCodeTable[]={0x11,0x12,0x14,0x18,0x21, 0x22,0x24,0x28,0x41,0x42,0x44,0x48,0x81,0x82,0x84,0x88}; //延时

void DelayMS(uint x) { uchar i; while(x--) for(i=0;i

//键盘扫描

uchar Keys_Scan() { uchar sCode,kCode,i,k; //低4位置0,放入4行

P1=0xf0; //若高4位出现0,则有键按下 if((P1&0xf0)!=0xf0) {

DelayMS(2); if((P1&0xf0)!=0xf0) {

sCode=0xfe; {

//行扫描码初值

for(k=0;k

P1=sCode; if((P1&0xf0)!=0xf0) {

kCode=~P1; for(i=0;i

16 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

}

}

return(i); else sCode=_crol_(sCode,1); } }

return(-1); } //主程序

void main() { uchar i,P2_LED,P3_LED; uchar KeyNo=-1; //按键序号,-1表示无按键

} while(1) { KeyNo=Keys_Scan(); //扫描键盘获取按键序号KeyNo

if(KeyNo!=-1) {

}

} P2_LED=0xff; P3_LED=0xff; for(i=0;i>=1; else P2_LED>>=1; } P3=P3_LED; //点亮条形LED P2=P2_LED;

17 数码管显示4X4矩阵键盘按键号

/* 名称:数码管显示4X4矩阵键盘按键号

说明:按下任意键时,数码管都会显示其键的序号,扫描程序首先判断按键发生在哪一列,然后根据所发生的行附加不同的值,从而得到按键的序号。

*/

17 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

#include #define uchar unsigned char #define uint unsigned int //段码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00}; sbit BEEP=P3^7; //上次按键和当前按键的序号,该矩阵中序号范围0~15,16表示无按键 uchar Pre_KeyNo=16,KeyNo=16; //延时

void DelayMS(uint x) { uchar i; while(x--) for(i=0;i

//矩阵键盘扫描 void Keys_Scan() {

uchar Tmp; P1=0x0f; //高4位置0,放入4行

DelayMS(1); Tmp=P1^0x0f;//按键后0f变成0000XXXX,X中一个为0,3个仍为1,通过异或把3个1变为0,唯一的0变为1 switch(Tmp) //判断按键发生于0~3列的哪一列

{

case 1: KeyNo=0;break; case 2: KeyNo=1;break; case 4: KeyNo=2;break; case 8: KeyNo=3;break; default:KeyNo=16; //无键按下

} P1=0xf0;

//低4位置0,放入4列

DelayMS(1); Tmp=P1>>4^0x0f;//按键后f0变成XXXX0000,X中有1个为0,三个仍为1;

高4位转移到低4位并异或得到改变的值

switch(Tmp) //对0~3行分别附加起始值0,4,8,12 {

} case 1: case 2: case 4: case 8: KeyNo+=0;break; KeyNo+=4;break; KeyNo+=8;break; KeyNo+=12; } //蜂鸣器 void Beep()

18 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

{

uchar i; for(i=0;i

} DelayMS(1); BEEP=~BEEP; BEEP=0; } //主程序 void main() { P0=0x00;

} BEEP=0; while(1) {

} P1=0xf0; if(P1!=0xf0) Keys_Scan(); //获取键序号 if(Pre_KeyNo!=KeyNo) {

} P0=~DSY_CODE[KeyNo]; Beep(); Pre_KeyNo=KeyNo; DelayMS(100); 18 开关控制LED

/* 名称:开关控制LED 说明:开关S1和S2分别控制LED1和LED2。

*/ #include sbit S1=P1^0; sbit S2=P1^1; sbit LED1=P0^0; sbit LED2=P0^1; //主程序 void main() {

while(1) { LED1=S1;

19 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

} } LED2=S2; 19 继电器控制照明设备

/* 名称:继电器控制照明设备

说明:按下K1灯点亮,再次按下时灯熄灭 */ #include #define uchar unsigned char #define uint unsigned int sbit K1=P1^0; sbit RELAY=P2^4; //延时

void DelayMS(uint ms) { uchar t; while(ms--)for(t=0;t

}

20 数码管显示拨码开关编码

/* 名称:数码管显示拨码开关编码

*/ #include #include #define uchar unsigned char

20 上海师范大学信息与机电工程学院—倪继锋 P1=0xff; RELAY=1; while(1) {

} if(K1==0) {

} while(K1==0); RELAY=~RELAY; DelayMS(20); 说明:系统显示拨码开关所设置的编码000~255 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

#define uint unsigned int //各数字的数码管段码(共阴)

uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //显示缓冲

uchar DSY_Buffer[3]={0,0,0}; //延时

void DelayMS(uint ms) { uchar t; while(ms--)for(t=0;t

} uchar i,m,Num; P0=0xff; P2=0xff; while(1) {

} m=0xfe; Num=P1; //读取拨码开关的值 DSY_Buffer[0]=Num/100; DSY_Buffer[1]=Num/10%10; DSY_Buffer[2]=Num%10; for(i=0;i

} m=_crol_(m,1); P2=m; P0=DSY_CODE[DSY_Buffer[i]]; DelayMS(10);

21 开关控制报警器

/* 名称:开关控制报警器 说明:用K1开关控制报警器,程序控制P1.0输出两种不同频率的声音,模拟很逼真的报警效果 */ #include #define uchar unsigned char #define uint unsigned int sbit SPK=P1^0; sbit K1=P1^7; //发声函数

21 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

void Alarm(uchar t) {

} void main() {

}

22 按键发音

/* 名称:按键发音

说明:按下不同的按键会是SOUNDER发出不同频率的声音。本例使用延时函数实现不同频率的声音输出,以后也可使用定时器 */ #include #define uchar unsigned char #define uint unsigned int sbit BEEP=P3^7; sbit K1=P1^4; sbit K2=P1^5; sbit K3=P1^6; sbit K4=P1^7; //延时

void DelayMS(uint x) { uchar t; SPK=0; while(1) {

} if(K1==1) {

} Alarm(90); Alarm(120); uchar i,j; for(i=0;i

} SPK=~SPK; for(j=0;j

while(x--) for(t=0;t

22 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

uchar i; for(i=0;i

DelayMS(t); } BEEP=0; } void main() { P1=0xff; BEEP=0; while(1) {

if(K1==0) Play(1);

if(K2==0) Play(2);

if(K3==0) Play(3);

if(K4==0) Play(4); } }

23 播放音乐

/* 名称:播放音乐

说明:程序运行时播放生日快乐歌, 未使用定时器中断,所有频率完全用延时实现

*/ #include #define uchar unsigned char #define uint unsigned int sbit BEEP=P3^7; //生日快乐歌的音符频率表,不同频率由不同的延时来决定

uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159,

212,212,106,126,159,169,190,119,119,126,159,142,159,0}; //生日快乐歌节拍表,节拍决定每个音符的演奏长短 uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,

9,3,12,12,12,12,12,9,3,12,12,12,24,0}; //延时

void DelayMS(uint x) { uchar t; while(x--) for(t=0;t

23 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

} uint i=0,j,k; while(SONG_LONG[i]!=0||SONG_TONE[i]!=0) { //播放各个音符,SONG_LONG为拍子长度

} for(j=0;j

} DelayMS(10); i++; BEEP=~BEEP; //SONG_TONE延时表决定了每个音符的频率 for(k=0;k

} BEEP=0; while(1) {

} PlayMusic(); //播放生日快乐 DelayMS(500); //播放完后暂停一段时间

24 INT0中断计数

/* 名称:INT0中断计数

说明:每次按下计数键时触发INT0中断,中断程序累加计数,

计数值显示在3只数码管上,按下清零键时数码管清零 */ #include #define uchar unsigned char #define uint unsigned int //0~9的段码

uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00}; //计数值分解后各个待显示的数位 uchar DSY_Buffer[]={0,0,0}; uchar Count=0; sbit Clear_Key=P3^6; //数码管上显示计数值

void Show_Count_ON_DSY() { DSY_Buffer[2]=Count/100; //获取3个数

24 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

DSY_Buffer[1]=Count%100/10; DSY_Buffer[0]=Count%10; if(DSY_Buffer[2]==0)

//高位为0时不显示 {

} P0=DSY_CODE[DSY_Buffer[0]]; P1=DSY_CODE[DSY_Buffer[1]]; DSY_Buffer[2]=0x0a; if(DSY_Buffer[1]==0)

//高位为0,若第二位为0同样不显示 DSY_Buffer[1]=0x0a; P2=DSY_CODE[DSY_Buffer[2]]; } //主程序 void main() {

P0=0x00; P1=0x00; P2=0x00; IE=0x81; //允许INT0中断 IT0=1; //下降沿触发

while(1) { if(Clear_Key==0) Count=0; //清0 Show_Count_ON_DSY(); } } //INT0中断函数

void EX_INT0() interrupt 0 { Count++; //计数值递增

}

25 外部INT0中断控制LED

/* 名称:外部INT0中断控制LED 说明:每次按键都会触发INT0中断,中断发生时将LED状态取反,产生LED状态由按键控制的效果 */ #include #define uchar unsigned char #define uint unsigned int sbit LED=P0^0; //主程序 void main()

25 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

{

LED=1; EA=1; EX0=1; IT0=1; while(1); } //INT0中断函数

void EX_INT0() interrupt 0 { }

26 INT0及INT1中断计数

/* 名称:INT0及INT1中断计数

说明:每次按下个计数键时,第1组计数值累加并显示在右边3只数码管上, 每次按下第2个计数键时,第2组计数值累加并显示在左边3只数码管上,后两个按键分别清零。

*/ #include #define uchar unsigned char #define uint unsigned int sbit K3=P3^4; //2个清零键 sbit K4=P3^5; //数码管段码与位码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; uchar code DSY_Scan_Bits[]={0x20,0x10,0x08,0x04,0x02,0x01}; //2组计数的显示缓冲,前3位一组,后3位一组 uchar data Buffer_Counts[]={0,0,0,0,0,0}; uint Count_A,Count_B=0; //延时

void DelayMS(uint x) { uchar t; while(x--) for(t=0;t

} //数据显示 void Show_Counts() {

uchar i; Buffer_Counts[2]=Count_A/100; Buffer_Counts[1]=Count_A%100/10; Buffer_Counts[0]=Count_A%10;

26 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

if( Buffer_Counts[2]==0) {

Buffer_Counts[2]=0x0a; if( Buffer_Counts[1]==0)

Buffer_Counts[1]=0x0a; } Buffer_Counts[5]=Count_B/100; Buffer_Counts[4]=Count_B%100/10; Buffer_Counts[3]=Count_B%10; if( Buffer_Counts[5]==0) {

Buffer_Counts[5]=0x0a;

if( Buffer_Counts[4]==0)

Buffer_Counts[4]=0x0a; } for(i=0;i

P2=DSY_Scan_Bits[i];

P1=DSY_CODE[Buffer_Counts[i]]; DelayMS(1); } } //主程序 void main() { IE=0x85; PX0=1; //中断优先

IT0=1; IT1=1; while(1) {

if(K3==0) Count_A=0;

if(K4==0) Count_B=0;

Show_Counts(); } } //INT0中断函数

void EX_INT0() interrupt 0 { Count_A++;

} //INT1中断函数

void EX_INT1() interrupt 2 { Count_B++;

上海师范大学信息与机电工程学院—倪继锋

27 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

}

27 定时器控制单只LED

/* 名称:定时器控制单只LED

说明:LED在定时器的中断例程控制下不断闪烁。

*/ #include #define uchar unsigned char #define uint unsigned int sbit LED=P0^0; uchar T_Count=0; //主程序

void main() { TMOD=0x00;

//定时器0工作方式0 TH0=(8192-5000)/32; //5ms定时

TL0=(8192-5000)%32; IE=0x82; //允许T0中断 TR0=1; while(1); } //T0中断函数

void LED_Flash() interrupt 1 {

} TH0=(8192-5000)/32; //恢复初值

TL0=(8192-5000)%32; if(++T_Count==100) //0.5s开关一次LED {

} LED=~LED; T_Count=0;

28 TIMER0控制流水灯

/* 名称:TIMER0控制流水灯 说明:定时器控制P0、P2口的LED滚动显示,本例未使用中断函数。

*/ #include #include #define uchar unsigned char #define uint unsigned int

28 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

//主程序 void main() {

uchar T_Count=0; P0=0xfe; P2=0xfe; TMOD=0x01;

TH0=(65536-40000)/256;

//定时器0工作方式1 //40ms定时

TL0=(65536-40000)%256; TR0=1;

//启动定时器 while(1) { if(TF0==1)

{

} TF0=0; TH0=(65536-40000)/256; //恢复初值 TL0=(65536-40000)%256; if(++T_Count==5) {

} P0=_crol_(P0,1); P2=_crol_(P2,1); T_Count=0; } }

29 定时器控制4个LED滚动闪烁

/* 名称:定时器控制4个LED滚动闪烁

说明:4只LED在定时器控制下滚动闪烁。

*/ #include #define uchar unsigned char #define uint unsigned int sbit B1=P0^0; sbit G1=P0^1; sbit R1=P0^2; sbit Y1=P0^3; uint i,j,k; //主程序 void main() { i=j=k=0; P0=0xff;

29 上海师范大学信息与机电工程学院—倪继锋

《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

TMOD=0x02;

TH0=256-200; TL0=256-200; IE=0x82; TR0=1; //定时器0工作方式2 //200us定时

//启动定时器

while(1); } //T0中断函数

void LED_Flash_and_Scroll() interrupt 1 {

if(++k

case 0: case 1: case 2: B1=~B1;break; G1=~G1;break; R1=~R1;break; return;

//定时中断若干次后执行闪烁

case 3: Y1=~Y1;break; default:i=0; } if(++j

i++; //切换到下一个LED }

30 T0控制LED实现二进制计数

/* 名称:T0控制LED实现二进制计数

说明:本例对按键的计数没有使用查询法,没有使用外部中断函数,没有使用定时或计数中断函数。而是启用了计数器,连接在T0引脚的按键每次按下时,会使计数寄存器的值递增,其值通过LED以二进制形式显示 */ #include //主程序

void main() { TMOD=0x05; //定时器0为计数器,工作方式1,最大计数值65535 TH0=0; //初值为0

TL0=0; TR0=1; while(1)

30 上海师范大学信息与机电工程学院—倪继锋

//启动定时器 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

{

} P1=TH0; P2=TL0; }

31 TIMER0与TIMER1控制条形LED

/* 名称:TIMER0与TIMER1控制条形LED

说明:定时器T0定时控制上一组条形LED,滚动速度较快

定时器T1定时控制下一组条形LED,滚动速度较慢

*/ #include #include #define uchar unsigned char #define uint unsigned int uchar tc0=0,tc1=0; //主程序 void main() { P0=0xfe; P2=0xfe; TMOD=0x11; //定时器0、定时器1均工作于方式1

TH0=(65536-15000)/256;

//定时器0:15ms //定时器1:50ms TL0=(65536-15000)%256; TH1=(65536-50000)/256; TL1=(65536-50000)%256; IE=0x8a; TR0=1; //启动定时器

TR1=1; while(1); } //T0中断函数 void Time0() interrupt 1 {

TH0=(65536-15000)/256;

//恢复定时器0初值

TL0=(65536-15000)%256; if(++tc0==10)

//150ms转换状态 { tc0=0; P0=_crol_(P0,1); } } //T1中断函数

31 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

void Time1() interrupt 3 { TH0=(65536-50000)/256;

}

32 10s的秒表

//恢复定时器1初值

TL0=(65536-50000)%256; if(++tc1==10)

//500ms转换状态 {

} tc1=0; P2=_crol_(P2,1);

/* 名称:10s的秒表

说明:首次按键计时开始,再次按键暂停,第三次按键清零。

*/ #include #define uchar unsigned char #define uint unsigned int sbit K1=P3^7; uchar i,Second_Counts,Key_Flag_Idx; bit Key_State; uchar DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //延时

void DelayMS(uint ms) { uchar t; while(ms--) for(t=0;t

void Key_Event_Handle() {

if(Key_State==0) {

Key_Flag_Idx=(Key_Flag_Idx+1)%3; switch(Key_Flag_Idx) {

} case 1: case 2: case 0: EA=1;ET0=1;TR0=1;break; EA=0;ET0=0;TR0=0;break; P0=0x3f;P2=0x3f;i=0;Second_Counts=0;

32 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

} } //主程序 void main() { P0=0x3f; //显示00 P2=0x3f; i=0; Second_Counts=0;

Key_Flag_Idx=0;

//按键次数(取值0,1,2,3)

Key_State=1;

//按键状态

TMOD=0x01; //定时器0方式1 TH0=(65536-50000)/256;

//定时器0:15ms TL0=(65536-50000)%256; while(1) {

if(Key_State!=K1)

{

DelayMS(10);

Key_State=K1;

Key_Event_Handle(); } } } //T0中断函数

void DSY_Refresh() interrupt 1 { TH0=(65536-50000)/256; //恢复定时器0初值

TL0=(65536-50000)%256; if(++i==2)

//50ms*2=0.1s转换状态

{

i=0;

Second_Counts++;

P0=DSY_CODE[Second_Counts/10];

P2=DSY_CODE[Second_Counts%10];

if(Second_Counts==100) Second_Counts=0;

//满100(10s)后显示00 } }

33 用计数器中断实现100以内的按键计数

/* 名称:用计数器中断实现100以内的按键计数

说明:本例用T0计数器中断实现按键技术,由于计数寄存器初值为1,因此

P3.4引脚的每次负跳变都会触发T0中断,实现计数值累加。

计数器的清零用外部中断0控制。

上海师范大学信息与机电工程学院—倪继锋

33 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

*/ #include #define uchar unsigned char #define uint unsigned int //段码 uchar

code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00}; uchar Count=0; //主程序 void main() { P0=0x00;

//计数器T0方式2 //计数值为1 //允许T0中断 //允许INT0中断 //允许CPU中断 P2=0x00; TMOD=0x06; TH0=TL0=256-1; ET0=1;

EX0=1;

EA=1;

IP=0x02; IT0=1; TR0=1; while(1) {

//设置优先级,T0高于INT0 //INT0中断触发方式为下降沿触发

//启动T0 P0=DSY_CODE[Count/10]; P2=DSY_CODE[Count%10]; } } //T0计数器中断函数 void Key_Counter() interrupt 1 { Count=(Count+1)%100; //因为只有两位数码管,计数控制在100以内(00~99) } //INT0中断函数

void Clear_Counter() interrupt 0 { } Count=0;

34 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

34 100 000s以内的计时程序

/* 名称:100 000s以内的计时程序 说明:在6只数码管上完成0~99 999.9s。

*/ #include #include #define uchar unsigned char #define uint unsigned int //段码 uchar

code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //6只数码管上显示的数字

uchar Digits_of_6DSY[]={0,0,0,0,0,0}; uchar Count; sbit Dot=P0^7; //延时

void DelayMS(uint ms) { uchar t; while(ms--) for(t=0;t

uchar i,j; P0=0x00; P3=0xff;

Count=0; TMOD=0x01;

TH0=(65536-50000)/256;

//计数器T0方式1 //50ms定时

TL0=(65536-50000)%256; IE=0x82; TR0=1;

//启动T0 while(1) {

j=0x7f; //显示Digits_of_6DSY[5]~Digits_of_6DSY[0]的内容 //前面高位,后面低位,循环中i!=-1亦可写成i!=0xff for(i=5;i!=-1;i--) { j=_crol_(j,1);

35 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

P3=j; P0=DSY_CODE[Digits_of_6DSY[i]]; if(i==1) Dot=1; //加小数点 DelayMS(2);

} } } //T0中断函数

void Timer0() interrupt 1 {

uchar i; TH0=(65536-50000)/256; TL0=(65536-50000)%256; if(++Count!=2) return; Count=0; Digits_of_6DSY[0]++; //0.1s位累加 for(i=0;i

if(Digits_of_6DSY[i]==10) { Digits_of_6DSY[i]=0; if(i!=5) Digits_of_6DSY[i+1]++;

//如果0~4位则分别向高一位进位

//若某低位没有进位,怎循环提前结束

//恢复初值

} else break; } }

35 定时器控制数码管动态显示

/* 名称:定时器控制数码管动态显示

说明:8个数码管上分两组动态显示年月日与时分秒,本例的

位显示延时用定时器实现。

*/ #include #include #define uchar unsigned char #define uint unsigned int //段码,最后一位是“-”的段码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf}; //待显示的数据:09-12-25与23-59-58(分两组显示)

uchar code Table_of_Digits[][8]={{0,9,10,1,2,10,2,5},{2,3,10,5,9,10,5,8}}; uchar i,j=0;

36 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

uint t=0; //主程序

void main() { P3=0x80;

//位码初值

TMOD=0x00;

//计数器T0方式0 TH0=(8192-4000)/32; //4ms定时

TL0=(8192-4000)%32; IE=0x82; TR0=1;

//启动T0 while(1); } //T0中断函数控制数码管刷新显示

void DSY_Show() interrupt 1 { TH0=(8192-4000)/32; //恢复初值

TL0=(8192-4000)%32; P0=0xff;

//输出位码和段码

P0=DSY_CODE[Table_of_Digits[i][j]]; P3=_crol_(P3,1);

j=(j+1)%8;

//数组第i行的下一字节索引 if(++t!=350) return;//保持刷新一段时间 t=0; i=(i+1)%2;

//数组行i=0时显示年月日,i=1时显示时分秒

}

36 8X8LED点阵显示数字

/* 名称:8X8LED点阵显示数字

说明:8X8LED点阵屏循环显示数字0~9,刷新过程由定时器中断完成。

*/ #include #include #define uchar unsigned char #define uint unsigned int uchar code Table_of_Digits[]= {

0x00,0x3e,0x41,0x41,0x41,0x3e,0x00,0x00, 0x00,0x00,0x00,0x21,0x7f,0x01,0x00,0x00, 0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00, 0x00,0x22,0x49,0x49,0x49,0x36,0x00,0x00, 0x00,0x0c,0x14,0x24,0x7f,0x04,0x00,0x00,

//0 //1 //2 //3 //4

37 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

0x00,0x72,0x51,0x51,0x51,0x4e,0x00,0x00, 0x00,0x3e,0x49,0x49,0x49,0x26,0x00,0x00, 0x00,0x40,0x40,0x40,0x4f,0x70,0x00,0x00, 0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00,

//5 //6 //7 //8 //9 0x00,0x32,0x49,0x49,0x49,0x3e,0x00,0x00 }; uchar i=0,t=0,Num_Index; //主程序 void main() {

P3=0x80;

Num_Index=0; TMOD=0x00;

//从0开始显示 //T0方式0 //2ms定时 TH0=(8192-2000)/32; TL0=(8192-2000)%32; IE=0x82; TR0=1;

//启动T0 while(1); } //T0中断函数

void LED_Screen_Display() interrupt 1 { TH0=(8192-2000)/32; //恢复初值

}

37 按键控制8X8LED点阵屏显示图形

/* 名称:按键控制8X8LED点阵屏显示图形

说明:每次按下K1时,会使8X8LED点阵屏循环显示不同图形。

本例同时使用外部中断和定时中断。

*/ #include

38 上海师范大学信息与机电工程学院—倪继锋 TL0=(8192-2000)%32; P0=0xff;

//输出位码和段码

P0=~Table_of_Digits[Num_Index*8+i]; P3=_crol_(P3,1);

if(++i==8) i=0;

//每屏一个数字由8个字节构成 if(++t==250) {

} //每个数字刷新显示一段时间

t=0; if(++Num_Index==10) Num_Index=0; //显示下一个数字 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

#include #define uchar unsigned char #define uint unsigned int //待显示图形编码

uchar code M[][8]= { {0x00,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x00}, //图1 {0x00,0x38,0x44,0x54,0x44,0x38,0x00,0x00}, //图2 {0x00,0x20,0x30,0x38,0x3c,0x3e,0x00,0x00}

//图3 }; uchar i,j; //主程序 void main() { P0=0xff; P1=0xff;

TMOD=0x01;

//T0方式1 TH0=(65536-2000)/256; //2ms定时

TL0=(65536-2000)%256; IT0=1;

//下降沿触发

IE=0x83;

//允许定时器0、外部0中断 i=0xff; //i的初值设为0xff,加1后将从0开始

while(1); } //T0中断控制点阵屏显示

void Show_Dot_Matrix() interrupt 1 { TH0=(65536-2000)/256; //恢复初值

TL0=(65536-2000)%256; P0=0xff;

//输出位码和段码

P0=~M[i][j]; P1=_crol_(P1,1);

j=(j+1)%8; } //INT0中断(定时器由键盘中断启动) void Key_Down() interrupt 0 { P0=0xff; P1=0x80; j=0; i=(i+1)%3;

//i在0,1,2中取值,因为只要3个图形

TR0=1; }

38 用定时器设计的门铃

上海师范大学信息与机电工程学院—倪继锋

39 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

/* 名称:用定时器设计的门铃

*/ #include #define uchar unsigned char #define uint unsigned int sbit Key=P1^7; sbit DoorBell=P3^0; uint p=0; //主程序 void main() {

DoorBell=0; TMOD=0x00; //T0方式0 说明:按下按键时蜂鸣器发出叮咚的门铃声。

TH0=(8192-700)/32; //700us定时 TL0=(8192-700)%32; IE=0x82; while(1) {

if(Key==0) { //按下按键启动定时器

TR0=1; while(Key==0);

} } } //T0中断控制点阵屏显示 void Timer0() interrupt 1 {

DoorBell=~DoorBell; p++; if(p

//若需要拖长声音,可以调整400和800 {

} {

} else { TR0=0;

40 上海师范大学信息与机电工程学院—倪继锋 TH0=(8192-700)/32; //700us定时

TL0=(8192-700)%32;

else if(p

} } p=0; 39 演奏音阶

/* 名称:演奏音阶

说明:本例使用定时器演奏一段音阶,播放由K1控制。

*/ #include #define uchar unsigned char #define uint unsigned int sbit K1=P1^0; sbit SPK=P3^4; uint i=0;

//音符索引

//14个音符放在方式2下的定时寄存器(TH0,TL0)

uchar code HI_LIST[]={0,226,229,232,233,236,238,240,241,242,244,245,246,247,248}; uchar code LO_LIST[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3}; //定时器0中断函数 void T0_INT() interrupt 1 { TL0=LO_LIST[i]; TH0=HI_LIST[i]; SPK=~SPK; } //延时

void DelayMS(uint ms) { uchar t; while(ms--) for(t=0;t

TMOD=0x00; IE=0x82; SPK=0; while(1) {

//T0方式0 while(K1==1); while(K1==0); for(i=1;i

//未按键等待 //等待释放

41 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

}

}

} TR0=1;

DelayMS(500); TR0=0; DelayMS(50);

//播放一个音符 //播放延时

40 按键控制定时器选播多段音乐

/* 名称:按键控制定时器选播多段音乐

说明:本例内置3段音乐,K1可启动停止音乐播放,K2用于选择音乐段。

*/ #include #include #define uchar unsigned char #define uint unsigned int sbit K1=P1^0;

sbit SPK=P3^7; //播放和停止键 //蜂鸣器

//当前音乐段索引,音符索引 uchar Song_Index=0,Tone_Index=0; //数码管段码表

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //标准音符频率对应的延时表

uchar code HI_LIST[]={0,226,229,232,233,236,238,240,241,242,244,245,246,247,248}; uchar code LO_LIST[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3}; //三段音乐的音符 uchar code Song[][50]= { {1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,6,5,3,5,3,2,1,2,1,-1}, {3,3,3,4,5,5,5,5,6,5,3,5,3,2,1,5,6,53,3,2,1,1,-1}, {3,2,1,3,2,1,1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,3,2,1,3,2,1,1,-1} }; //三段音乐的节拍 uchar code Len[][50]= { {1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,2,-1}, {1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,2,-1}, {1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,2,1,1,2,2,-1} }; //外部中断0 void EX0_INT() interrupt 0 { TR0=0; //播放结束或者播放中途切换歌曲时停止播放 Song_Index=(Song_Index+1)%3; //跳到下一首的开头

42 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

Tone_Index=0; P2=DSY_CODE[Song_Index];

//数码管显示当前音乐段号

} //定时器0中断函数

void T0_INT() interrupt 1 { TL0=LO_LIST[Song[Song_Index][Tone_Index]]; TH0=HI_LIST[Song[Song_Index][Tone_Index]]; SPK=~SPK; } //延时

void DelayMS(uint ms) { uchar t; while(ms--) for(t=0;t

//T0方式0 IE=0x83; IT0=1; IP=0x02; while(1) {

while(K1==1); //未按键等待

while(K1==0);

//等待释放

TR0=1;

//开始播放

Tone_Index=0; //从第0个音符开始

//播放过程中按下K1可提前停止播放(K1=0)。

//若切换音乐段会触发外部中断,导致TR0=0,播放也会停止

while(Song[Song_Index][Tone_Index]!=-1&&K1==1&&TR0==1)

{

DelayMS(300*Len[Song_Index][Tone_Index]); //播放延时(节拍)

Tone_Index++; //当前音乐段的下一音符索引

}

TR0=0;

//停止播放

while(K1==0); //若提前停止播放,按键未释放时等待

} }

41 定时器控制交通指示灯

上海师范大学信息与机电工程学院—倪继锋

43 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

/* 名称:定时器控制交通指示灯

说明:东西向绿灯亮5s后,黄灯闪烁,闪烁5次亮红灯,

红灯亮后,南北向由红灯变成绿灯,5s后南北向黄灯闪烁,

闪烁5次后亮红灯,东西向绿灯亮,如此往复。

*/ #include #define uchar unsigned char #define uint unsigned int sbit RED_A=P0^0; //东西向指示灯 sbit YELLOW_A=P0^1; sbit GREEN_A=P0^2; sbit RED_B=P0^3; //南北向指示灯 sbit YELLOW_B=P0^4; sbit GREEN_B=P0^5; //延时倍数,闪烁次数,操作类型变量

uchar Time_Count=0,Flash_Count=0,Operation_Type=1; //定时器0中断函数 void T0_INT() interrupt 1 {

TL0=-50000/256; TH0=-50000%256; switch(Operation_Type) { case 1: //东西向绿灯与南北向红灯亮5s

RED_A=0;YELLOW_A=0;GREEN_A=1; RED_B=1;YELLOW_B=0;GREEN_B=0; if(++Time_Count!=100) return; //5s(100*50ms)切换 Time_Count=0; Operation_Type=2; break; //东西向黄灯开始闪烁,绿灯关闭 if(++Time_Count!=8) return; Time_Count=0; YELLOW_A=~YELLOW_A;GREEN_A=0; if(++Flash_Count!=10) return; //闪烁 Flash_Count=0; Operation_Type=3; break;

//东西向红灯与南北向绿灯亮5s RED_A=1;YELLOW_A=0;GREEN_A=0; RED_B=0;YELLOW_B=0;GREEN_B=1; if(++Time_Count!=100) return; //5s(100*50ms)切换 Time_Count=0; Operation_Type=4;

44 上海师范大学信息与机电工程学院—倪继锋

case 2:

case 3:

《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

}

case 4:

break; //南北向黄灯开始闪烁,绿灯关闭 if(++Time_Count!=8) return; Time_Count=0; YELLOW_B=~YELLOW_B;GREEN_A=0; if(++Flash_Count!=10) return; //闪烁 Flash_Count=0; Operation_Type=1; break;

} //主程序 void main() {

}

42 报警与旋转灯

/* 名称:报警与旋转灯

说明:定时器控制报警灯旋转显示,并发出仿真警报声。

*/ #include #include #define uchar unsigned char #define uint unsigned int sbit SPK=P3^7; uchar FRQ=0x00; //延时

void DelayMS(uint ms) {

}

//INT0中断函数

void EX0_INT() interrupt 0 { TR0=~TR0; //开启或停止两定时器,分别控制报警器的声音和LED旋转

TR1=~TR1; if(P2==0x00)

45 上海师范大学信息与机电工程学院—倪继锋 TMOD=0x01; IE=0x82; TR0=1; while(1);

//T0方式1 uchar i; while(ms--) for(i=0;i

P2=0xe0; //开3个旋转灯

else P2=0x00; //关闭所有LED

} //定时器0中断 void T0_INT() interrupt 1 {

TH0=0xfe; TL0=FRQ; SPK=~SPK; } //定时器1中断 void T1_INT() interrupt 3 {

TH1=-45000/256; TL1=-45000%256; P2=_crol_(P2,1); } //主程序 void main() {

}

43 串行数据转换为并行数据

/* 名称:串行数据转换为并行数据

说明:串行数据由RXD发送给串并转换芯片74164,TXD则用于输出移位时钟脉冲,74164将串行输入的1字节转换为并行数据,并将转换的数据通过8只LED显示出来。本例串口工作模式0,即移位寄存器I/O模式。

*/

46 上海师范大学信息与机电工程学院—倪继锋 P2=0x00; SPK=0x00; TMOD=0x11; TH0=0x00; TL0=0xff; IT0=1; IE=0x8b; IP=0x01; TR0=0; TR1=0; while(1) {

} FRQ++; DelayMS(1); //T0、T1方式1

//开启0,1,3号中断 //INT0设为最高优先 //定时器启停由INT0控制,初始关闭 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

#include #include #define uchar unsigned char #define uint unsigned int sbit SPK=P3^7; uchar FRQ=0x00; //延时

void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i

} uchar c=0x80; SCON=0x00; TI=1; while(1) {

} c=_crol_(c,1); SBUF=c; while(TI==0); TI=0;

DelayMS(400); //串口模式0,即移位寄存器输入/输出方式

//等待发送结束

//TI软件置位

44 并行数据转换为串行数据

/* 名称:并行数据转换为串行数据

说明:切换连接到并串转换芯片74LS165的拨码开关,该芯片将并行数据以串行方式发送到8051的RXD引脚,移位脉冲由TXD提供,显示在P0口。

*/ #include #include #include #define uchar unsigned char #define uint unsigned int sbit SPL=P2^5; //shift/load //延时

void DelayMS(uint ms) {

47 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

uchar i; while(ms--) for(i=0;i

void main() { SCON=0x10;

} while(1) {

} SPL=0; //置数(load),读入并行输入口的8位数据 //串口模式0,允许串口接收

SPL=1; //移位(shift),并口输入被封锁,串行转换开始 while(RI==0); //未接收1字节时等待 RI=0;

//RI软件置位

//接收到的数据显示在P0口,显示拨码开关的值 P0=SBUF; DelayMS(20);

45 甲机通过串口控制乙机LED

/* 名称:甲机发送控制命令字符

说明:甲单片机负责向外发送控制命令字符“A”、“B”、“C”,或者停止发送,乙机根据所接收到的字符完成LED1闪烁、LED2闪烁、双闪烁、或停止闪烁。

*/ #include #define uchar unsigned char #define uint unsigned int sbit LED1=P0^0;

sbit LED2=P0^3; sbit K1=P1^0; //延时

void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i

void Putc_to_SerialPort(uchar c) {

SBUF=c; while(TI==0); TI=0;

48 上海师范大学信息与机电工程学院—倪继锋 《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

} //主程序 void main() { uchar Operation_No=0; SCON=0x40; //串口模式1 TMOD=0x20; //T1工作模式2 PCON=0x00; //波特率不倍增

TH1=0xfd; TL1=0xfd; TI=0; TR1=1; while(1) {

if(K1==0) //按下K1时选择操作代码0,1,2,3

{

while(K1==0);

Operation_No=(Operation_No+1)%4;

}

switch(Operation_No) //根据操作代码发送A/B/C或停止发送

{

case 0: 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;

}

DelayMS(100); } }

/* 名称:乙机程序接收甲机发送字符并完成相应动作

说明:乙机接收到甲机发送的信号后,根据相应信号控制LED完成不同闪烁动作。*/ #include #define uchar unsigned char #define uint unsigned int sbit LED1=P0^0;

sbit LED2=P0^3; 上海师范大学信息与机电工程学院—倪继锋

49

《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例

//延时

void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i

} SCON=0x50; TMOD=0x20; PCON=0x00; TH1=0xfd; TL1=0xfd; RI=0; TR1=1; LED1=LED2=1; while(1) { if(RI)

} {

//串口模式1,允许接收 //T1工作模式2 //波特率不倍增 //波特率9600 //如收到则LED闪烁

RI=0; switch(SBUF) //根据所收到的不同命令字符完成不同动作 {

}

//关闭LED case \\"A\\": LED1=~LED1;LED2=1;break; case \\"B\\": LED2=~LED2;LED1=1;break; case \\"C\\": LED1=~LED1;LED2=LED1;

//LED1闪烁 //LED2闪烁

//双闪烁

} else LED1=LED2=1; DelayMS(100);

46 单片机之间双向通信

/* 名称:甲机串口程序 说明:甲机向乙机发送控制命令字符,甲机同时接收乙机发送的数字,并显示在数码管上。

*/ #include #define uchar unsigned char #define uint unsigned int sbit LED1=P1^0;

50 上海师范大学信息与机电工程学院—倪继锋

本文来源:http://www.scfx8.com/gerengongzuozongjie/70965.html