还剩59页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
S51单片机开发板设计《单片机及应用设计》实训报告S-51单片机开发板设计---------《单片机及应用设计》实训报告姓名学号班级XX级电子信息工程专业本科班学院计算机电子信息工程学院时间xx年X月X日——X月X日指导教师目录一.前言2二.单片机及各模块简介
21.总体设计方案
22.硬件模块简介
32.1S51单片机主控制模块
32.2键盘模块
42.3DS1302时钟模块
42.4串口通信模块
52.5LED数码管显示和流水灯模块
52.6下载线模块
62.7蜂鸣器模块
62.8其他模块7三.开发板(串口通信模块)设计原理介绍71.实验工程要求
71.1元器件功能介绍
71.2串口通信原理82.原理图的绘制102.1串口通信模块仿真电路设计103.程序的编写
113.1keil操作过程
113.2程序框图
123.3USB模块电路原理图的绘制12四.印刷板的焊接及流程14焊接流程14五.调试及遭遇的问题解决方法141.调试
141.1程序下载
141.2开发板调试152.问题解决15六.总结体会15附录16串口通信C语言源程序16一.前言近年来随着科技的飞速开展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构软硬件结合,加以完善本次实训的主要目的就是为了学习单片机的根本理论知识,进而进行单片机的开发、实践和扩展,以更好的运用到实际的软硬件开发中去此次单片机的实训目的如下
(1)掌握单片机的相关理论知识学习单片机相关存放器的配置,单片机内部结构及特点,存储器组织及外部接口,中断及串口功能,功能存放器的相关配置,确定软硬件设计总体方案;
(2)掌握硬件设计和软件设计的根本知识,学会使用根本的设计软件,依据总体的设计方案对单片机进行软硬件开发在Protel中对单片机的各个功能模块进行外部电路的设计,在实现各个模块的功能的前提下充分合理利用单片机的内部资源和外围接口,以求最大限度的发挥单片机的功能学会使用KeilC进行、编译及仿真调试,实现对单片机进行C语言开发以Proteus为平台,对单片机外围各个功能模块进行软件仿真验证功能
(3)开发板板上资源的硬件实现及下载器的制作对软硬件设计仿真验证功能无误后,将Protel绘制的PCB进行加工、焊接元器件,制作出S51开发板及下载器二.单片机及各模块简介
1.总体设计方案本开发板共分为十个模块,分别是S51单片机主控制器模块、键盘模块、DS1302时钟模块、数码管模块、LCDCPS364BR模块、ARK点阵模块、下载器模块、流水灯模块、蜂鸣器模块、电源模块其中以S51单片机作为核心控制器;键盘模块用来向单片机输入特定编码的信息;DS1302时钟模块用来实现实时时钟;数码管模块用来显示简单的数字、字母;LCD模块用来显示字母、数字、符号;点阵模块用来显示图像、符号、汉字;下载器模块用来实现S51单片机的ISP在线编程;流水灯模块用来显示单片机I/O口电平的变化;蜂鸣器模块用来发出声音总体硬件电路如下列图1所示图1总体硬件电路
2.硬件模块简介
2.1S51单片机主控制模块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.3DS1302时钟模块DS1302的引脚如图4所示图3按键模块图4DS1302引脚图V1为后备电源,V2为主电源在主电源关闭的情况下,也能保持时钟的连续运行DS1302由V1或V2两者中的较大者供电当V2高于V1+
0.2V时,V2给DS1302供电当V2低于V1时,DS1302由V1供电X
1、X2为振荡源,外接
32.768kHz晶振I/O为串行数据输入/输出端双向,SCLK为时钟输入端RST是复位片选线,通过把RST输入驱动置为高电平来启动所有的数据传送RST输入有两种功能RST接通控制逻辑,允许地址/命令序列送入移位存放器;RST提供了终止单字节或多字节数据的传送手段当RST为高电平时,所有的数据传送被初始化,允许DS1302进行操作如果在传送过程中置RST为低电平,那么会终止此次数据传送,并且I/O引脚变为高阻态上电运行时,在V高于
2.5V之前,RST必须保持低电平只有在SCLK为低电平时,才能将RST置为高电平DS1302时钟模块的原理图如图5所示图5DS1302时钟原理图单片机与DS1302通过P
1.
1、P
1.
2、P
1.3相连,分别为时钟信号线、输入输出线、复位信号线DS1302的晶振引脚连接32768HZ的晶振
2.4串口通信模块串口通信模块的原理图如图6所示图6串口通信模块的原理图单片机与MAX232通过P
3.
0、P
3.1相连,分别为发送线、接收线,另外单片机要与MAX232共地
2.5LED数码管显示和流水灯模块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图8LCD数码管和流水灯模块
2.6下载线模块下载器模块实现将USB信号转换为能通过SPI协议传输的信号,从而实现对单片机的编程下载模块原理图如图9所示图9下载线接口模块图10蜂鸣器模块
2.7蜂鸣器模块单片机的P
1.4与Q1的基极通过1K欧姆电阻连接,当P
1.4为高电平时,Q1导通,Q1的发射极与集电极导通,将发射极下拉为低电平,蜂鸣器两端出现电位差,蜂鸣器发声;当P
1.4为低电平时,Q1不导通,蜂鸣器两端没有电流流过,蜂鸣器不发声
2.8其他模块I2CEEPROM模块用于程序或数据存储器的扩展功能,片外可最大扩展到64KB地址为0000~FFFFH此存储芯片支持电科擦除,即可写电源模块通过整流电桥实现交直流的转换功能,直接供单片机使用原理图如图11图12所示图11电源模块图12I2CEEPROM模块三.开发板(串口通信模块)设计原理介绍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字节在系统可编程FlashAT89S51RS232RS232是由电子工业协会ElectronicIndustriesAssociation,EIA所制定的异步传输标准接口对于一般双工通信,仅需几条信号线就可实现,如一条发送线、一条接收线及一条地线RS232与TTL电路之间需要进行电平和逻辑关系的变换实现这种变换的方法可用分立元件,也可用集成电路芯片MAX232芯片可完成TTL←→RS232双向电平转换MAX232MAX232芯片是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)图13RS232芯片引脚图图14MAX232芯片引脚图
1.2串口通信原理S-51单片机内部有一个全双工的串行接收和发射缓冲器(SBUFF),这两个在物理上独立的接收发射器,即可以接收也可以发射数据,但接收缓冲器只可以读出不能写入,而发送缓冲器只能写入不能读出,它们的地址是99H这个通信口即可以用于网络通信,亦可以实现串行异步通信,还可以构成同步移位存放器使用如果在串行口的输入输出引脚上加上电平转换器,就可以方便的构成标准的RS-232接口S-51单片机串行口专用存放器SBUF为串行口的收发缓冲器,它是一个可寻址的专用存放器,其中包含了接收器和发射器存放器,可以实现全双工通信但这两个存放器具有同一地址(99H)S-51的串行数据传输很简单,只要向缓冲器写入数据就可发送数据而从接收缓冲器读出数据既可接收数据串行通信存放器SCON控制存放器,它是一个可寻址的专用存放器,用于串行数据通信的控制数据通信的传输方式常用于数据通信的传输方式有单工、半双工、全双工和工方式串行通信的两种通信形式,包括异步通信和同步通信SCON控制存放器是一个可寻址的专用存放器,用于串行数据通信的控制,其结构格式如下表1存放器SCON结构SCOND7D6D5D4D3D2D1D0SM0SM1SM2RENTB8RB8TIRI位地址9FH9EH8DH9CH9BH9AH99H98H下面我们对个控制位功能介绍如下
(1)SM
0、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中,不使用RB8TI发送中断标志由硬件在方式0发送完第8位时置“1”,或在其它方式中串行发送停止位的开始时置“1”必须由软件清“0”RI接收中断标志由硬件在方式0串行发射第8位结束时置“1”B:特殊功能存放器PCONPCON主要是是CHMOS型单片机的电源控制而设置的专用存放器2.原理图的绘制2.1串口通信模块仿真电路设计
(1)翻开ISIS7professional窗口,执行菜单命令Filenewdesign,新建一个DEFAULT命名为“单片机串口通信自发自收.DSN”
(2)在器件选择按钮单击“P”按钮,添加如表所示的原件单片机AT89S51电容CAP-ELECCAP-POLMAX232PIM按钮BUTTON数码管7SEG-MPX4-CA74LS244排阻RX8三极管NPN晶振CRYSTAL
(3)在ISIS原理图窗口中,放置电源和地布好线,设置好相应原件的参数完成电骡图的设计
(4)调试与仿真加载生成的.HEX文件,进行调试,观察是否符合预期效果仿真效果图如图15所示图15仿真效果图3.程序的编写
3.1keil操作过程1).翻开桌面上的keil软件,下面新建一个工程,选择project-new新建一个名字叫“单片机串口通信”的工程,保存在事先创立的文件夹下,点击保存按钮出现选择器件型号对话框选择实验板上的所用芯片的型号atmel-at89s51点击确定就建立完毕工程了2).添加代码文件到工程中,首先新建一个后缀为.C的源文件,点击开发环境中的file-new新建c文件,然后点击保存按钮,注意一定要保存为后缀为.C的格式,在开发环境中左边栏找到在sourcegroup1上右击选中,弹出添加文件对话框,如图把单片机串口通信.c选中,点击ADD添加源文件到工程中3).点击按钮,编译你的代码,如果下面有错误提示,修改好后再次编译直到顺利通过编译为止如图16所示图16keil编译图4).在target1上右击选择,出现如下对话框.选择output栏,将一栏打上勾,这样编译通过之后就可以生成可以执行的下载文件(可执行文件后缀为hex),再次点击编译,生成可执行的代码串口通信.hex
3.2程序框图单片机通过MAX232与单片机通讯程序流程图17所示图17单片机通过MAX232与PC机或单片机通讯程序流程图单片机通过P
3.
0.和P
3.1发送数据到单片机,单片机接收到数据后发送给单片机,并通过LED数码管显示出
3.3USB模块电路原理图的绘制
(1)在D盘建立名为Protel的文件夹,在Protel的文件夹中建立名为USB.ddb设计数据库文件,新建原理图文件,命名为USB.sch
(2)根据提供的usb原理图,自己画出原理图电路中所有的元器件都可在MiscellaneousDevices.ddb、ProtelDOSSchematicLibraries.ddb这两个元器件数据库中找
(3)画完电路后,要按照图中元件参数逐个设置元件属性,元件要自动编号,并进行电气规那么检查设置某个元器件的属性的方法是双击该元器件出现对话框设置即可原理图如图18所示图18usb原理图
(4)最后形成该电路的网络表,为设计电路板做准备
(5)根据仿真好的电路图,画出印刷电路板图新建PCB文件,设置PCB设计环境和绘制印刷电路的版框
(6)、翻开所有要用到的PCB库文件后,调入网络表文件和修改零件封装布置零件封装的位置,进行自动布局
(7)对所有过孔和焊盘补泪滴,放置覆铜区敷铜后的效果如图18所示图18PCB原理图四.印刷板的焊接及流程焊接流程
1、焊前准备首先要熟悉所焊印制电路板的装配图,并按图纸配料,检查元器件型号、规格及数量是否符合图纸要求,并做好装配前元器件引线成型等准备工作
2、焊接顺序元器件装焊顺序依次为电阻器、电容器、二极管、三极管、集成电路、大功率管,其它元器件为先小后大
3、对元器件焊接要求1)电阻器焊接按图将电阻器准确装人规定位置尽量使电阻器的上下一致焊完后将露在印制电路板外表多余引脚齐根剪去2)电容器焊接将电容器按图装人规定位置,并注意有极性电容器其“+”与“-”极不能接错3)二极管的焊接二极管焊接要注意阳极阴极的极性,不能装错;发光二极管要与印刷版保持
0.5cm距离4)三极管焊接注意e、b、c三引线位置插接正确;焊接时间尽可能短,焊接时用镊子夹住引线脚,以利散热5)集成电路焊接首先按图纸要求,检查型号、引脚位置是否符合要求焊接时先焊边沿的二只引脚,以使其定位,然后再从左到右自上而下逐个焊接6)usb接口和电源接口找到正确位置,注意将其与印刷版焊接牢固,不松动五.调试及遭遇的问题解决方法1.调试
1.1程序下载开发板和PC机通过下载器连接,使用+5V电源给开发板供电在PC机上安装ISP在线下载器驱动,翻开烧写器软件,选择烧写单片机类型,加载FLASH,点击编程,即可把程序烧录到单片机中使用USBisp下载请安装并翻开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)数码管显示的是乱码,并非完整数字分析应该是数码管编码与实际所用的编码或引脚不相同对程序中的数码管显示代码重新编译之后就通过了六.总结体会在老师的指导下,自己找资料、看书,完成了老师布置的任务通过这次的实训设计,使我对单片机以及智能仪器的结构和功能都有了更深的认识,从理论和实践上都得到了很大的提高,这次的实训真的给我很大的提高总结经验来说,首先,我丰富了自己的知识面,将以前没能学通的东西深入透彻的学会学懂,具体了解了怎样去完成一个电路的设计从流程图、电路图、焊接电路板、检查电路板、仿真到烧片一整套东西没有浪费珍贵的时间,学习到了难得的经验自己找资料,了解单片机89S
51、数码显示管的有关知识,学习时钟电路、控制电路的设计原理,看不懂的时候就去问老师、同学和同学们一起探讨不懂得难点之时我仿佛感觉到了真正的大学应该有的学习气氛在这些都搞得比拟明白后就开始画设计流程图和电路图,最后用了很长时间才画出自己的电路图,同学老师都帮我检查,改正了几处有问题的地方电路的焊接比拟难要细心稳重,应为这是一件很要求技术的工作但是我克服困难终于完成了但接下来的检测可就费了不少劲,发现并解决了很多问题在解决完所有问题后,自己又一种成功感,还在想,要是没有这些错误,就不会学会这么多检测电路的方法,而且对自己所做的电路有了进一步的了解做到这一步满以为不会再有什么错误了,但是仿真的时候却又遇到了马麻烦,先是数码管不亮,在后来就是全亮,按键后没反响,刚有的一点成功感马上就没了,又一次陷入了反复的检测检测发现了不少问题,解决后仿真成功在后来就开始烧片,烧片的过程还算顺利烧好后插上电路板,显示成功了接下来的工作一切还算顺利,在老师还有同学的帮助下,都一一完成这次的实训设计总的来说还是很成功的,自己从中学到很多,也发现了不少问题,为自己以后的学习、进步打下了不错的根底从实训设计中,学到了单片机AT89C51的内部结构及其工作原理,了解了串口通信的工作原理,还有共阳极数码管的工作原理,稳固了C语言的使用能力,提高了自己动手的能力,学到了很多经验,并且提高了自己分析问题的能力和创新能力,得到了理论联系实际的时机,做出了成果使自己在硬件设计方面树立了信心,为以后从事这方面的工作打好了根底,这也是这次实训设计的最大收获附录串口通信C语言源程序/********单片机自发自收程序**********/#include#defineucharunsignedchar#defineuintunsignedintsbitP20=P2^0;sbitP21=P2^1;sbitP22=P2^2;sbitP23=P2^3;sbitP24=P2^4;sbitP25=P2^5;sbitP26=P2^6;sbitP27=P2^7;ucharcodedsy
[16]={0xc00xf90xa40xb00x990x920x820xf80x800x900x880x830xc60xa10x860x8e};/***实验板数码管的编码***/signedinta;voiddelayuintn//延时程序{uintj;uchark;forj=0;j10000;j++fork=0;k0a=a-1;elsea=15;break;}//按键2,减一个数default:break;}}《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例《单片机C语言程序设计实训100例—基于8051+Proteus仿真》案例第01篇根底程序设计01闪烁的LED/*名称闪烁的LED*/#include#defineucharunsignedchar#defineuintunsignedintsbitLED=P1^0;//延时voidDelayMSuintx{uchari;whilex--{说明LED按设定的时间间隔闪烁fori=0;i}while1{}LED=~LED;DelayMS150;02从左到右的流水灯/*名称从左到右的流水灯说明接在P0口的8个LED从左到右循环依次点亮,产生走马灯效果*/#include#include#defineucharunsignedchar#defineuintunsignedint1上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例//延时voidDelayMSuintx{uchari;whilex--{fori=0;i}038只LED左右来回点亮/*名称8只LED左右来回点亮说明程序利用循环移位函数crol和cror形成来回滚动的效果*/#include#include#defineucharunsignedchar#defineuintunsignedint//延时voidDelayMSuintx{uchari;whilex--{}fori=0;iDelayMS150;}}//主程序voidmain{uchari;P2=0x01;while1{2上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}}fori=0;i}DelayMS150;04把戏流水灯/*名称把戏流水灯说明16只LED分两组按预设的多种把戏变换显示*/#include#defineucharunsignedchar#defineuintunsignedintucharcodePatternP0[]={0xfc0xf90xf30xe70xcf0x9f0x3f0x7f0xff0xff0xff0xff0xff0xff0xff0xff0xe70xdb0xbd0x7e0xbd0xdb0xe70xff0xe70xc30x810x000x810xc30xe70xff0xaa0x550x180xff0xf00x0f0x000xff0xf80xf10xe30xc70x8f0x1f0x3f0x7f0x7f0x3f0x1f0x8f0xc70xe30xf10xf80xff0x000x000xff0xff0x0f0xf00xff0xfe0xfd0xfb0xf70xef0xdf0xbf0x7f0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0x7f0xbf0xdf0xef0xf70xfb0xfd0xfe0xfe0xfc0xf80xf00xe00xc00x800x000x000x000x000x000x000x000x000x000x000x000x000x000x000x000x000x000x000x800xc00xe00xf00xf80xfc0xfe0x000xff0x000xff0x000xff0x000xff};ucharcodePatternP2[]={0xff0xff0xff0xff0xff0xff0xff0xfe0xfc0xf90xf30xe70xcf0x9f0x3f0xff0xe70xdb0xbd0x7e0xbd0xdb0xe70xff0xe70xc30x810x000x810xc30xe70xff0xaa0x550x180xff0xf00x0f0x000xff0xf80xf10xe30xc70x8f0x1f0x3f0x7f0x7f0x3f0x1f0x8f0xc70xe30xf10xf80xff0x000x000xff0xff0x0f0xf00xff0xff0xff0xff0xff0xff0xff0xff0xff0xfe0xfd0xfb0xf70xef0xdf0xbf0x7f0x7f0xbf0xdf0xef0xf70xfb0xfd0xfe0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xff0xfe0xfc0xf80xf00xe00xc00x800x000x000x800xc00xe00xf00xf80xfc0xfe0xff0xff0xff0xff0xff0xff0xff0xff3上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例0x000xff0x000xff0x000xff0x000xff};//延时voidDelayMSuintx{uchari;whilex--{}fori=0;iuchari;while1{//从数组中读取数据送至P0和P2口显示}fori=0;i}P0=PatternP0[i];P2=PatternP2[i];DelayMS100;}05LED模拟交通灯/*名称LED模拟交通灯说明东西向绿灯亮假设干秒,黄灯闪烁5次后红灯亮,红灯亮后,南北向由红灯变为绿灯,假设干秒后南北向黄灯闪烁5此后变红灯,东西向变绿灯,如此重复*/#include#defineucharunsignedchar#defineuintunsignedintsbitREDA=P0^0;//东西向灯sbitYELLOWA=P0^1;sbitGREENA=P0^2;sbitREDB=P0^3;//南北向灯sbitYELLOWB=P0^4;sbitGREENB=P0^5;ucharFlashCount=0OperationType=1;//闪烁次数,操作类型变量4上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例//延时voidDelayMSuintx{uchari;whilex--fori=0;icase1://东西向绿灯与南北向红灯亮REDA=1;YELLOWA=1;GREENA=0;REDB=0;YELLOWB=1;GREENB=1;DelayMS2000;OperationType=2;break;case2://东西向黄灯闪烁,绿灯关闭DelayMS300;YELLOWA=~YELLOWA;GREENA=1;if++FlashCount!=10return;//闪烁5次FlashCount=0;OperationType=3;break;case3://东西向红灯,南北向绿灯亮REDA=0;YELLOWA=1;GREENA=1;REDB=1;YELLOWB=1;GREENB=0;DelayMS2000;OperationType=4;break;case4://南北向黄灯闪烁5次DelayMS300;YELLOWB=~YELLOWB;GREENB=1;if++FlashCount!=10return;FlashCount=0;OperationType=1;}}//主程序voidmain{while1TrafficLight;}06单只数码管循环显示0~9上海师范大学信息与机电工程学院—倪继锋5《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例/*名称单只数码管循环显示0~9*/#include#include#defineucharunsignedchar#defineuintunsignedintucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x900xff};//延时voidDelayMSuintx{uchart;whilex--fort=0;t}uchari=0;P0=0x00;while1{}P0=~DSYCODE[i];i=i+1%10;DelayMS300;说明主程序中的循环语句反复将0~9的段码送至P0口,使数字0~9循环显示078只数码管滚动显示单个数字/*名称8只数码管滚动显示单个数字说明数码管从左到右依次滚动显示0~7,程序通过每次仅循环选通一只数码管*/#include#include#defineucharunsignedchar#defineuintunsignedintucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x90};//延时voidDelayMSuintx{uchart;whilex--fort=0;t6上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}//主程序voidmain{uchariwei=0x80;while1{fori=0;i{P2=0xff;//关闭显示wei=crolwei1;P0=DSYCODE[i];//发送数字段码P2=wei;//发送位码DelayMS300;}}}088只数码管动态显示多个不同字符电路如上图/*名称8只数码管动态显示多个不同字符说明数码管动态扫描显示0~7*/#include#include#defineucharunsignedchar#defineuintunsignedintucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x90};//延时voidDelayMSuintx{uchart;whilex--fort=0;tfori=0;i{P0=0xff;P0=DSYCODE[i];//发送段码wei=crolwei1;上海师范大学信息与机电工程学院—倪继锋7《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例P2=wei;//发送位码DelayMS2;}}}098只数码管闪烁显示数字串电路如上图/*名称8只数码管闪烁显示数字串说明数码管闪烁显示由0~7构成的一串数字本例用动态刷新法显示一串数字,在停止刷新时所有数字显示消失*/#include#defineucharunsignedchar#defineuintunsignedint//段码表ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x90};//位码表ucharcodeDSYIDX[]={0x010x020x040x080x100x200x400x80};//延时voidDelayMSuintx{uchart;whilex--fort=0;tfori=0;i{forj=0;j{P0=0xff;P0=DSYCODE[j];//发送段码P2=DSYIDX[j];//发送位码DelayMS2;}}P2=0x00;//关闭所有数码管并延时DelayMS1000;}}上海师范大学信息与机电工程学院—倪继锋8《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例108只数码管滚动显示数字串电路如上图/*名称8只数码管滚动显示数字串说明数码管向左滚动显示3个字符构成的数字串*/#include#include#defineucharunsignedchar#defineuintunsignedint//段码表ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x900xff};//下面数组看作环形队列,显示从某个数开始的8个数(10表示黑屏)ucharNum[]={1010101010101010298};//延时voidDelayMSuintx{uchart;whilex--fort=0;tfori=0;i{forj=0;j{//发送段码,采用环形取法,从第k个开始取第j个P0=0xff;P0=DSYCODE[Num[k+j%11]];m=crolm1;P2=m;//发送位码DelayMS2;}}k=k+1%11;//环形队列首支针k递增,Num下标范围0~10,故对11取余}}11K1-K4控制LED移位/*名称K1-K4控制LED移位说明按下K1时,P0口LED上移一位;上海师范大学信息与机电工程学院—倪继锋9《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例*/按下K2时,P0口LED下移一位;按下K3时,P2口LED上移一位;按下K4时,P2口LED下移一位;#include#include#defineucharunsignedchar#defineuintunsignedint//延时voidDelayMSuintx{uchari;whilex--fori=0;i//根据P1口的按键移动LEDvoidMoveLED{ifP10x10==0P0=crorP01;//K1elseifP10x20==0P0=crolP01;//K2elseifP10x40==0P2=crorP21;//K3//K4elseifP10x80==0P2=crolP21;}//主程序voidmain{ucharRecentKey;//最近按键}P0=0xfe;P2=0xfe;P1=0xff;RecentKey=0xff;while1{}ifRecentKey!=P1{}RecentKey=P1;//保存最近按键MoveLED;DelayMS10;12K1-K4按键状态显示10上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例/*名称K1-K4按键状态显示说明K
1、K2按下时LED点亮,松开时熄灭,*/#include#defineucharunsignedchar#defineuintunsignedintsbitLED1=P0^0;sbitLED2=P0^1;sbitLED3=P0^2;sbitLED4=P0^3;sbitK1=P1^0;sbitK2=P1^1;sbitK3=P1^2;sbitK4=P1^3;//延时voidDelayMSuintx{uchari;whilex--fori=0;iK
3、K4按下并释放时LED点亮,再次按下并释放时熄灭;}//主程序voidmain{}13K1-K4分组控制LED11上海师范大学信息与机电工程学院—倪继锋P0=0xff;P1=0xff;while1{}LED1=K1;LED2=K2;ifK3==0{whileK3==0;}LED3=~LED3;ifK4==0{}whileK4==0;LED4=~LED4;DelayMS10;《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例/*名称K1-K4分组控制LED说明每次按下K1时递增点亮一只LED,全亮时再次按下那么再次循环开始,K2按下后点亮上面4只LED,K3按下后点亮下面4只LED,K4按下后关闭所有LED*/#include#defineucharunsignedchar#defineuintunsignedint//延时voidDelayMSuintx{uchari;whilex--fori=0;iucharktKeyState;P0=0xff;P1=0xff;while1{t=P1;ift!=0xff{DelayMS10;ift!=P1continue;//取得4位按键值,由模式XXXX1111X中有一位为0,其他均为1//变为模式0000XXXXX中有一位为1,其他均为0KeyState=~t4;k=0;//检查1所在位置,累加获取按键号kwhileKeyState!=0{k++;KeyState=1;}//根据按键号k进行4种处理switchk{case1:ifP0==0x00P0=0xff;P012case2:上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}}}}case3:case4:P0=0x0f;break;P0=0xff;14K1-K4控制数码管移位显示/*名称K1-K4控制数码管移位显示说明按下K1时加1计数并增加显示位,按下K2时减1计数并减少显示位,按下K3时清零*/#include#defineucharunsignedchar#defineuintunsignedint//段码ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x900xff};//位码ucharcodeDSYIndex[]={0x800x400x200x100x080x040x020x01};//待显示到各数码管的数字缓冲(开始仅在0位显示0,其他黑屏)ucharDisplayBuffer[]={010101010101010};//延时voidDelayMSuintx{uchari;whilex--fori=0;ivoidShowCountONDSY{uchari;fori=0;i{P0=0xff;P0=DSYCODE[DisplayBuffer[i]];}P2=DSYIndex[i];DelayMS2;}//主程序voidmain{uchariKeyNOKeyCounts=0;13上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例P0=0xff;P1=0xff;P2=0x00;while1{}ShowCountONDSY;P1=0xff;KeyNO=P1;//P1口按键状态分别为K1-0xfe,K2-0xfdK3-0xfbswitchKeyNO{case0xfe:KeyCounts++;ifKeyCounts8KeyCounts=8;DisplayBuffer[KeyCounts-1]=KeyCounts;break;ifKeyCounts0DisplayBuffer[--KeyCounts]=10;break;DisplayBuffer
[0]=0;fori=1;icase0xfb:}//假设键未释放那么仅刷新显示,不进行键扫描whileP1!=0xffShowCountONDSY;}15K1-K4控制数码管加减演示/*名称K1-K4控制数码管加减演示说明按下K1后加1计数,按下K2后减1计数,按下K3后清零*/#include#include#defineucharunsignedchar#defineuintunsignedint//段码ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x900xff};//待显示的3位缓冲ucharNumBuffer[]={000};//按键代码,按键计数ucharKeyCodeKeyCounts=0;//延时voidDelayMSuintx{14上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例uchari;whilex--fori=0;i//显示函数voidShowCountsONDSY{ucharij=0x01;NumBuffer
[2]=KeyCounts/100;NumBuffer
[1]=KeyCounts/10%10;NumBuffer
[0]=KeyCounts%10;fori=0;ij=crorj1;P0=0xff;P0=DSYCODE[NumBuffer[i]];P2=j;DelayMS1;}}//主程序voidmain{uchari;P0=0xff;P1=0xff;P2=0x00;KeyCode=0xff;while1{ShowCountsONDSY;P1=0xff;KeyCode=P1;//有键按下时,数码管刷新显示30次,该行代码同时起到延时作用ifKeyCode!=0xfffori=0;iswitchKeyCode{case0xfe:ifKeyCountsbreak;case0xfd:ifKeyCounts0KeyCounts--;break;case0xfb:KeyCounts=0;}KeyCode=0xff;}上海师范大学信息与机电工程学院—倪继锋15《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}164X4矩阵键盘控制条形LED显示/*名称4X4矩阵键盘控制条形LED显示说明运行本例时,按下的按键值越大点亮的LED越多*/#include#include#defineucharunsignedchar#defineuintunsignedint//矩阵键盘按键特征码表ucharcodeKeyCodeTable[]={0x110x120x140x180x210x220x240x280x410x420x440x480x810x820x840x88};//延时voidDelayMSuintx{uchari;whilex--fori=0;i//键盘扫描ucharKeysScan{ucharsCodekCodeik;//低4位置0,放入4行P1=0xf0;//假设高4位出现0,那么有键按下ifP10xf0!=0xf0{DelayMS2;ifP10xf0!=0xf0{sCode=0xfe;{//行扫描码初值fork=0;kP1=sCode;ifP10xf0!=0xf0{kCode=~P1;fori=0;i16上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}}returni;elsesCode=crolsCode1;}}return-1;}//主程序voidmain{uchariP2LEDP3LED;ucharKeyNo=-1;//按键序号,-1表示无按键}while1{KeyNo=KeysScan;//扫描键盘获取按键序号KeyNoifKeyNo!=-1{}}P2LED=0xff;P3LED=0xff;fori=0;i=1;elseP2LED=1;}P3=P3LED;//点亮条形LEDP2=P2LED;17数码管显示4X4矩阵键盘按键号/*名称数码管显示4X4矩阵键盘按键号说明按下任意键时,数码管都会显示其键的序号,扫描程序首先判断按键发生在哪一列,然后根据所发生的行附加不同的值,从而得到按键的序号*/17上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例#include#defineucharunsignedchar#defineuintunsignedint//段码ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x900x880x830xc60xa10x860x8e0x00};sbitBEEP=P3^7;//上次按键和当前按键的序号,该矩阵中序号范围0~15,16表示无按键ucharPreKeyNo=16KeyNo=16;//延时voidDelayMSuintx{uchari;whilex--fori=0;i//矩阵键盘扫描voidKeysScan{ucharTmp;P1=0x0f;//高4位置0,放入4行DelayMS1;Tmp=P1^0x0f;//按键后0f变成0000XXXX,X中一个为0,3个仍为1,通过异或把3个1变为0,唯一的0变为1switchTmp//判断按键发生于0~3列的哪一列{case1:KeyNo=0;break;case2:KeyNo=1;break;case4:KeyNo=2;break;case8:KeyNo=3;break;default:KeyNo=16;//无键按下}P1=0xf0;//低4位置0,放入4列DelayMS1;Tmp=P14^0x0f;//按键后f0变成XXXX0000,X中有1个为0,三个仍为1;高4位转移到低4位并异或得到改变的值switchTmp//对0~3行分别附加起始值0,4,8,12{}case1:case2:case4:case8:KeyNo+=0;break;KeyNo+=4;break;KeyNo+=8;break;KeyNo+=12;}//蜂鸣器voidBeep18上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例{uchari;fori=0;i}DelayMS1;BEEP=~BEEP;BEEP=0;}//主程序voidmain{P0=0x00;}BEEP=0;while1{}P1=0xf0;ifP1!=0xf0KeysScan;//获取键序号ifPreKeyNo!=KeyNo{}P0=~DSYCODE[KeyNo];Beep;PreKeyNo=KeyNo;DelayMS100;18开关控制LED/*名称开关控制LED说明开关S1和S2分别控制LED1和LED2*/#includesbitS1=P1^0;sbitS2=P1^1;sbitLED1=P0^0;sbitLED2=P0^1;//主程序voidmain{while1{LED1=S1;19上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}}LED2=S2;19继电器控制照明设备/*名称继电器控制照明设备说明按下K1灯点亮,再次按下时灯熄灭*/#include#defineucharunsignedchar#defineuintunsignedintsbitK1=P1^0;sbitRELAY=P2^4;//延时voidDelayMSuintms{uchart;whilems--fort=0;t}20数码管显示拨码开关编码/*名称数码管显示拨码开关编码*/#include#include#defineucharunsignedchar20上海师范大学信息与机电工程学院—倪继锋P1=0xff;RELAY=1;while1{}ifK1==0{}whileK1==0;RELAY=~RELAY;DelayMS20;说明系统显示拨码开关所设置的编码000~255《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例#defineuintunsignedint//各数字的数码管段码(共阴)ucharcodeDSYCODE[]={0x3f0x060x5b0x4f0x660x6d0x7d0x070x7f0x6f};//显示缓冲ucharDSYBuffer
[3]={000};//延时voidDelayMSuintms{uchart;whilems--fort=0;t}ucharimNum;P0=0xff;P2=0xff;while1{}m=0xfe;Num=P1;//读取拨码开关的值DSYBuffer
[0]=Num/100;DSYBuffer
[1]=Num/10%10;DSYBuffer
[2]=Num%10;fori=0;i}m=crolm1;P2=m;P0=DSYCODE[DSYBuffer[i]];DelayMS10;21开关控制报警器/*名称开关控制报警器说明用K1开关控制报警器,程序控制P
1.0输出两种不同频率的声音,模拟很逼真的报警效果*/#include#defineucharunsignedchar#defineuintunsignedintsbitSPK=P1^0;sbitK1=P1^7;//发声函数21上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例voidAlarmuchart{}voidmain{}22按键发音/*名称按键发音说明按下不同的按键会是SOUNDER发出不同频率的声音本例使用延时函数实现不同频率的声音输出,以后也可使用定时器*/#include#defineucharunsignedchar#defineuintunsignedintsbitBEEP=P3^7;sbitK1=P1^4;sbitK2=P1^5;sbitK3=P1^6;sbitK4=P1^7;//延时voidDelayMSuintx{uchart;SPK=0;while1{}ifK1==1{}Alarm90;Alarm120;ucharij;fori=0;i}SPK=~SPK;forj=0;jwhilex--fort=0;t22上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例uchari;fori=0;iDelayMSt;}BEEP=0;}voidmain{P1=0xff;BEEP=0;while1{ifK1==0Play1;ifK2==0Play2;ifK3==0Play3;ifK4==0Play4;}}23播放音乐/*名称播放音乐说明程序运行时播放生日快乐歌,未使用定时器中断,所有频率完全用延时实现*/#include#defineucharunsignedchar#defineuintunsignedintsbitBEEP=P3^7;//生日快乐歌的音符频率表,不同频率由不同的延时来决定ucharcodeSONGTONE[]={2122121902121591692122121902121421592122121061261591691901191191261591421590};//生日快乐歌节拍表,节拍决定每个音符的演奏长短ucharcodeSONGLONG[]={9312121224931212122493121212121293121212240};//延时voidDelayMSuintx{uchart;whilex--fort=0;t23《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}uinti=0jk;whileSONGLONG[i]!=0||SONGTONE[i]!=0{//播放各个音符,SONGLONG为拍子长度}forj=0;j}DelayMS10;i++;BEEP=~BEEP;//SONGTONE延时表决定了每个音符的频率fork=0;k}BEEP=0;while1{}PlayMusic;//播放生日快乐DelayMS500;//播放完后暂停一段时间24INT0中断计数/*名称INT0中断计数说明每次按下计数键时触发INT0中断,中断程序累加计数,计数值显示在3只数码管上,按下清零键时数码管清零*/#include#defineucharunsignedchar#defineuintunsignedint//0~9的段码ucharcodeDSYCODE[]={0x3f0x060x5b0x4f0x660x6d0x7d0x070x7f0x6f0x00};//计数值分解后各个待显示的数位ucharDSYBuffer[]={000};ucharCount=0;sbitClearKey=P3^6;//数码管上显示计数值voidShowCountONDSY{DSYBuffer
[2]=Count/100;//获取3个数24上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例DSYBuffer
[1]=Count%100/10;DSYBuffer
[0]=Count%10;ifDSYBuffer
[2]==0//高位为0时不显示{}P0=DSYCODE[DSYBuffer
[0]];P1=DSYCODE[DSYBuffer
[1]];DSYBuffer
[2]=0x0a;ifDSYBuffer
[1]==0//高位为0,假设第二位为0同样不显示DSYBuffer
[1]=0x0a;P2=DSYCODE[DSYBuffer
[2]];}//主程序voidmain{P0=0x00;P1=0x00;P2=0x00;IE=0x81;//允许INT0中断IT0=1;//下降沿触发while1{ifClearKey==0Count=0;//清0ShowCountONDSY;}}//INT0中断函数voidEXINT0interrupt0{Count++;//计数值递增}25外部INT0中断控制LED/*名称外部INT0中断控制LED说明每次按键都会触发INT0中断,中断发生时将LED状态取反,产生LED状态由按键控制的效果*/#include#defineucharunsignedchar#defineuintunsignedintsbitLED=P0^0;//主程序voidmain25上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例{LED=1;EA=1;EX0=1;IT0=1;while1;}//INT0中断函数voidEXINT0interrupt0{}26INT0及INT1中断计数/*名称INT0及INT1中断计数说明每次按下第1个计数键时,第1组计数值累加并显示在右边3只数码管上,每次按下第2个计数键时,第2组计数值累加并显示在左边3只数码管上,后两个按键分别清零*/#include#defineucharunsignedchar#defineuintunsignedintsbitK3=P3^4;//2个清零键sbitK4=P3^5;//数码管段码与位码ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x900xff};ucharcodeDSYScanBits[]={0x200x100x080x040x020x01};//2组计数的显示缓冲,前3位一组,后3位一组uchardataBufferCounts[]={000000};uintCountACountB=0;//延时voidDelayMSuintx{uchart;whilex--fort=0;t}//数据显示voidShowCounts{uchari;BufferCounts
[2]=CountA/100;BufferCounts
[1]=CountA%100/10;BufferCounts
[0]=CountA%10;26上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例ifBufferCounts
[2]==0{BufferCounts
[2]=0x0a;ifBufferCounts
[1]==0BufferCounts
[1]=0x0a;}BufferCounts
[5]=CountB/100;BufferCounts
[4]=CountB%100/10;BufferCounts
[3]=CountB%10;ifBufferCounts
[5]==0{BufferCounts
[5]=0x0a;ifBufferCounts
[4]==0BufferCounts
[4]=0x0a;}fori=0;iP2=DSYScanBits[i];P1=DSYCODE[BufferCounts[i]];DelayMS1;}}//主程序voidmain{IE=0x85;PX0=1;//中断优先IT0=1;IT1=1;while1{ifK3==0CountA=0;ifK4==0CountB=0;ShowCounts;}}//INT0中断函数voidEXINT0interrupt0{CountA++;}//INT1中断函数voidEXINT1interrupt2{CountB++;上海师范大学信息与机电工程学院—倪继锋27《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}27定时器控制单只LED/*名称定时器控制单只LED说明LED在定时器的中断例程控制下不断闪烁*/#include#defineucharunsignedchar#defineuintunsignedintsbitLED=P0^0;ucharTCount=0;//主程序voidmain{TMOD=0x00;//定时器0工作方式0TH0=8192-5000/32;//5ms定时TL0=8192-5000%32;IE=0x82;//允许T0中断TR0=1;while1;}//T0中断函数voidLEDFlashinterrupt1{}TH0=8192-5000/32;//恢复初值TL0=8192-5000%32;if++TCount==100//
0.5s开关一次LED{}LED=~LED;TCount=0;28TIMER0控制流水灯/*名称TIMER0控制流水灯说明定时器控制P
0、P2口的LED滚动显示,本例未使用中断函数*/#include#include#defineucharunsignedchar#defineuintunsignedint28上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例//主程序voidmain{ucharTCount=0;P0=0xfe;P2=0xfe;TMOD=0x01;//定时器0工作方式1//40ms定时//启动定时器while1{ifTF0==1{}P0=crolP01;P2=crolP21;TCount=0;}}29定时器控制4个LED滚动闪烁/*名称定时器控制4个LED滚动闪烁说明4只LED在定时器控制下滚动闪烁*/#include#defineucharunsignedchar#defineuintunsignedintsbitB1=P0^0;sbitG1=P0^1;sbitR1=P0^2;sbitY1=P0^3;uintijk;//主程序voidmain{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定时//启动定时器while1;}//T0中断函数voidLEDFlashandScrollinterrupt1{if++kcase0:case1:case2:B1=~B1;break;G1=~G1;break;R1=~R1;break;return;//定时中断假设干次后执行闪烁case3:Y1=~Y1;break;default:i=0;}if++ji++;//切换到下一个LED}30T0控制LED实现二进制计数/*名称T0控制LED实现二进制计数说明本例对按键的计数没有使用查询法,没有使用外部中断函数,没有使用定时或计数中断函数而是启用了计数器,连接在T0引脚的按键每次按下时,会使计数存放器的值递增,其值通过LED以二进制形式显示*/#include//主程序voidmain{TMOD=0x05;//定时器0为计数器,工作方式1,最大计数值65535TH0=0;//初值为0TL0=0;TR0=1;while130上海师范大学信息与机电工程学院—倪继锋//启动定时器《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例{}P1=TH0;P2=TL0;}31TIMER0与TIMER1控制条形LED/*名称TIMER0与TIMER1控制条形LED说明定时器T0定时控制上一组条形LED,滚动速度较快定时器T1定时控制下一组条形LED,滚动速度较慢*/#include#include#defineucharunsignedchar#defineuintunsignedintuchartc0=0tc1=0;//主程序voidmain{P0=0xfe;P2=0xfe;TMOD=0x11;//定时器
0、定时器1均工作于方式1TH0=65536-15000/256;//定时器015ms//定时器150msTL0=65536-15000%256;TH1=65536-50000/256;TL1=65536-50000%256;IE=0x8a;TR0=1;//启动定时器TR1=1;while1;}//T0中断函数voidTime0interrupt1{TH0=65536-15000/256;//恢复定时器0初值TL0=65536-15000%256;if++tc0==10//150ms转换状态{tc0=0;P0=crolP01;}}//T1中断函数31上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例voidTime1interrupt3{TH0=65536-50000/256;}3210s的秒表//恢复定时器1初值TL0=65536-50000%256;if++tc1==10//500ms转换状态{}tc1=0;P2=crolP21;/*名称10s的秒表说明首次按键计时开始,再次按键暂停,第三次按键清零*/#include#defineucharunsignedchar#defineuintunsignedintsbitK1=P3^7;uchariSecondCountsKeyFlagIdx;bitKeyState;ucharDSYCODE[]={0x3f0x060x5b0x4f0x660x6d0x7d0x070x7f0x6f};//延时voidDelayMSuintms{uchart;whilems--fort=0;tvoidKeyEventHandle{ifKeyState==0{KeyFlagIdx=KeyFlagIdx+1%3;switchKeyFlagIdx{}case1:case2:case0:EA=1;ET0=1;TR0=1;break;EA=0;ET0=0;TR0=0;break;P0=0x3f;P2=0x3f;i=0;SecondCounts=0;32上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}}//主程序voidmain{P0=0x3f;//显示00P2=0x3f;i=0;SecondCounts=0;KeyFlagIdx=0;//按键次数(取值0,1,2,3)KeyState=1;//按键状态TMOD=0x01;//定时器0方式1TH0=65536-50000/256;//定时器015msTL0=65536-50000%256;while1{ifKeyState!=K1{DelayMS10;KeyState=K1;KeyEventHandle;}}}//T0中断函数voidDSYRefreshinterrupt1{TH0=65536-50000/256;//恢复定时器0初值TL0=65536-50000%256;if++i==2//50ms*2=
0.1s转换状态{i=0;SecondCounts++;P0=DSYCODE[SecondCounts/10];P2=DSYCODE[SecondCounts%10];ifSecondCounts==100SecondCounts=0;//满100(10s)后显示00}}33用计数器中断实现100以内的按键计数/*名称用计数器中断实现100以内的按键计数说明本例用T0计数器中断实现按键技术,由于计数存放器初值为1,因此P
3.4引脚的每次负跳变都会触发T0中断,实现计数值累加计数器的清零用外部中断0控制上海师范大学信息与机电工程学院—倪继锋33《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例*/#include#defineucharunsignedchar#defineuintunsignedint//段码ucharcodeDSYCODE[]={0x3f0x060x5b0x4f0x660x6d0x7d0x070x7f0x6f0x00};ucharCount=0;//主程序voidmain{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;while1{//设置优先级,T0高于INT0//INT0中断触发方式为下降沿触发//启动T0P0=DSYCODE[Count/10];P2=DSYCODE[Count%10];}}//T0计数器中断函数voidKeyCounterinterrupt1{Count=Count+1%100;//因为只有两位数码管,计数控制在100以内(00~99)}//INT0中断函数voidClearCounterinterrupt0{}Count=0;34上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例34100000s以内的计时程序/*名称100000s以内的计时程序说明在6只数码管上完成0~
99999.9s*/#include#include#defineucharunsignedchar#defineuintunsignedint//段码ucharcodeDSYCODE[]={0x3f0x060x5b0x4f0x660x6d0x7d0x070x7f0x6f};//6只数码管上显示的数字ucharDigitsof6DSY[]={000000};ucharCount;sbitDot=P0^7;//延时voidDelayMSuintms{uchart;whilems--fort=0;tucharij;P0=0x00;P3=0xff;Count=0;TMOD=0x01;TH0=65536-50000/256;//计数器T0方式1//50ms定时TL0=65536-50000%256;IE=0x82;TR0=1;//启动T0while1{j=0x7f;//显示Digitsof6DSY
[5]~Digitsof6DSY
[0]的内容//前面高位,后面低位,循环中i!=-1亦可写成i!=0xfffori=5;i!=-1;i--{j=crolj1;35上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例P3=j;P0=DSYCODE[Digitsof6DSY[i]];ifi==1Dot=1;//加小数点DelayMS2;}}}//T0中断函数voidTimer0interrupt1{uchari;TH0=65536-50000/256;TL0=65536-50000%256;if++Count!=2return;Count=0;Digitsof6DSY
[0]++;//
0.1s位累加fori=0;iifDigitsof6DSY[i]==10{Digitsof6DSY[i]=0;ifi!=5Digitsof6DSY[i+1]++;//如果0~4位那么分别向高一位进位//假设某低位没有进位,怎循环提前结束//恢复初值}elsebreak;}}35定时器控制数码管动态显示/*名称定时器控制数码管动态显示说明8个数码管上分两组动态显示年月日与时分秒,本例的位显示延时用定时器实现*/#include#include#defineucharunsignedchar#defineuintunsignedint//段码最后一位是“-”的段码ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x900xbf};//待显示的数据09-12-25与23-59-58(分两组显示)ucharcodeTableofDigits[]
[8]={{0910121025}{2310591058}};ucharij=0;36上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例uintt=0;//主程序voidmain{P3=0x80;//位码初值TMOD=0x00;//启动T0while1;}//T0中断函数控制数码管刷新显示//输出位码和段码P0=DSYCODE[TableofDigits[i][j]];P3=crolP31;j=j+1%8;//数组第i行的下一字节索引if++t!=350return;//保持刷新一段时间t=0;i=i+1%2;//数组行i=0时显示年月日,i=1时显示时分秒}368X8LED点阵显示数字/*名称8X8LED点阵显示数字说明8X8LED点阵屏循环显示数字0~9,刷新过程由定时器中断完成*/#include#include#defineucharunsignedchar#defineuintunsignedintucharcodeTableofDigits[]={0x000x3e0x410x410x410x3e0x000x000x000x000x000x210x7f0x010x000x000x000x270x450x450x450x390x000x000x000x220x490x490x490x360x000x000x000x0c0x140x240x7f0x040x000x00//0//1//2//3//437上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例0x000x720x510x510x510x4e0x000x000x000x3e0x490x490x490x260x000x000x000x400x400x400x4f0x700x000x000x000x360x490x490x490x360x000x00//5//6//7//8//90x000x320x490x490x490x3e0x000x00};uchari=0t=0NumIndex;//主程序voidmain{P3=0x80;NumIndex=0;TMOD=0x00;//从0开始显示//T0方式0//2ms定时TH0=8192-2000/32;TL0=8192-2000%32;IE=0x82;TR0=1;//启动T0while1;}//T0中断函数voidLEDScreenDisplayinterrupt1{TH0=8192-2000/32;//恢复初值}37按键控制8X8LED点阵屏显示图形/*名称按键控制8X8LED点阵屏显示图形说明每次按下K1时,会使8X8LED点阵屏循环显示不同图形本例同时使用外部中断和定时中断*/#include38上海师范大学信息与机电工程学院—倪继锋TL0=8192-2000%32;P0=0xff;//输出位码和段码P0=~TableofDigits[NumIndex*8+i];P3=crolP31;if++i==8i=0;//每屏一个数字由8个字节构成if++t==250{}//每个数字刷新显示一段时间t=0;if++NumIndex==10NumIndex=0;//显示下一个数字《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例#include#defineucharunsignedchar#defineuintunsignedint//待显示图形编码ucharcodeM[]
[8]={{0x000x7e0x7e0x7e0x7e0x7e0x7e0x00}//图1{0x000x380x440x540x440x380x000x00}//图2{0x000x200x300x380x3c0x3e0x000x00}//图3};ucharij;//主程序voidmain{P0=0xff;P1=0xff;TMOD=0x01;//T0方式1TH0=65536-2000/256;//2ms定时TL0=65536-2000%256;IT0=1;//下降沿触发IE=0x83;//允许定时器
0、外部0中断i=0xff;//i的初值设为0xff,加1后将从0开始while1;}//T0中断控制点阵屏显示voidShowDotMatrixinterrupt1{TH0=65536-2000/256;//恢复初值TL0=65536-2000%256;P0=0xff;//输出位码和段码P0=~M[i][j];P1=crolP11;j=j+1%8;}//INT0中断(定时器由键盘中断启动)voidKeyDowninterrupt0{P0=0xff;P1=0x80;j=0;i=i+1%3;//i在0,1,2中取值,因为只要3个图形TR0=1;}38用定时器设计的门铃上海师范大学信息与机电工程学院—倪继锋39《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例/*名称用定时器设计的门铃*/#include#defineucharunsignedchar#defineuintunsignedintsbitKey=P1^7;sbitDoorBell=P3^0;uintp=0;//主程序voidmain{DoorBell=0;TMOD=0x00;//T0方式0说明按下按键时蜂鸣器发出叮咚的门铃声TH0=8192-700/32;//700us定时TL0=8192-700%32;IE=0x82;while1{ifKey==0{//按下按键启动定时器TR0=1;whileKey==0;}}}//T0中断控制点阵屏显示voidTimer0interrupt1{DoorBell=~DoorBell;p++;ifp}{}else{TR0=0;40上海师范大学信息与机电工程学院—倪继锋TH0=8192-700/32;//700us定时TL0=8192-700%32;elseifp}}p=0;39演奏音阶/*名称演奏音阶说明本例使用定时器演奏一段音阶,播放由K1控制*/#include#defineucharunsignedchar#defineuintunsignedintsbitK1=P1^0;sbitSPK=P3^4;uinti=0;//音符索引//14个音符放在方式2下的定时存放器(TH0TL0)ucharcodeHILIST[]={0226229232233236238240241242244245246247248};ucharcodeLOLIST[]={04131020386223526143};//定时器0中断函数voidT0INTinterrupt1{TL0=LOLIST[i];TH0=HILIST[i];SPK=~SPK;}//延时voidDelayMSuintms{uchart;whilems--fort=0;tTMOD=0x00;IE=0x82;SPK=0;while1{//T0方式0whileK1==1;whileK1==0;fori=1;i//未按键等待//等待释放41上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}}}TR0=1;DelayMS500;TR0=0;DelayMS50;//播放一个音符//播放延时40按键控制定时器选播多段音乐/*名称按键控制定时器选播多段音乐说明本例内置3段音乐,K1可启动停止音乐播放,K2用于选择音乐段*/#include#include#defineucharunsignedchar#defineuintunsignedintsbitK1=P1^0;sbitSPK=P3^7;//播放和停止键//蜂鸣器//当前音乐段索引,音符索引ucharSongIndex=0ToneIndex=0;//数码管段码表ucharcodeDSYCODE[]={0xc00xf90xa40xb00x990x920x820xf80x800x90};//标准音符频率对应的延时表ucharcodeHILIST[]={0226229232233236238240241242244245246247248};ucharcodeLOLIST[]={04131020386223526143};//三段音乐的音符ucharcodeSong[]
[50]={{1231123134534556535653532121-1}{33345555653532156533211-1}{32132112311231345345565353213211-1}};//三段音乐的节拍ucharcodeLen[]
[50]={{1111111111211211111111111212-1}{11111121111111211111122-1}{11211211111111112112111111121122-1}};//外部中断0voidEX0INTinterrupt0{TR0=0;//播放结束或者播放中途切换歌曲时停止播放SongIndex=SongIndex+1%3;//跳到下一首的开头42上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例ToneIndex=0;P2=DSYCODE[SongIndex];//数码管显示当前音乐段号}//定时器0中断函数voidT0INTinterrupt1{TL0=LOLIST[Song[SongIndex][ToneIndex]];TH0=HILIST[Song[SongIndex][ToneIndex]];SPK=~SPK;}//延时voidDelayMSuintms{uchart;whilems--fort=0;t//T0方式0IE=0x83;IT0=1;IP=0x02;while1{whileK1==1;//未按键等待whileK1==0;//等待释放TR0=1;//开始播放ToneIndex=0;//从第0个音符开始//播放过程中按下K1可提前停止播放(K1=0)//假设切换音乐段会触发外部中断,导致TR0=0,播放也会停止whileSong[SongIndex][ToneIndex]!=-1K1==1TR0==1{DelayMS300*Len[SongIndex][ToneIndex];//播放延时(节拍)ToneIndex++;//当前音乐段的下一音符索引}TR0=0;//停止播放whileK1==0;//假设提前停止播放,按键未释放时等待}}41定时器控制交通指示灯上海师范大学信息与机电工程学院—倪继锋43《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例/*名称定时器控制交通指示灯说明东西向绿灯亮5s后,黄灯闪烁,闪烁5次亮红灯,红灯亮后,南北向由红灯变成绿灯,5s后南北向黄灯闪烁,闪烁5次后亮红灯,东西向绿灯亮,如此往复*/#include#defineucharunsignedchar#defineuintunsignedintsbitREDA=P0^0;//东西向指示灯sbitYELLOWA=P0^1;sbitGREENA=P0^2;sbitREDB=P0^3;//南北向指示灯sbitYELLOWB=P0^4;sbitGREENB=P0^5;//延时倍数,闪烁次数,操作类型变量ucharTimeCount=0FlashCount=0OperationType=1;//定时器0中断函数voidT0INTinterrupt1{TL0=-50000/256;TH0=-50000%256;switchOperationType{case1://东西向绿灯与南北向红灯亮5sREDA=0;YELLOWA=0;GREENA=1;REDB=1;YELLOWB=0;GREENB=0;if++TimeCount!=100return;//5s(100*50ms)切换TimeCount=0;OperationType=2;break;//东西向黄灯开始闪烁,绿灯关闭if++TimeCount!=8return;TimeCount=0;YELLOWA=~YELLOWA;GREENA=0;if++FlashCount!=10return;//闪烁FlashCount=0;OperationType=3;break;//东西向红灯与南北向绿灯亮5sREDA=1;YELLOWA=0;GREENA=0;REDB=0;YELLOWB=0;GREENB=1;if++TimeCount!=100return;//5s(100*50ms)切换TimeCount=0;OperationType=4;44上海师范大学信息与机电工程学院—倪继锋case2:case3:《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}case4:break;//南北向黄灯开始闪烁,绿灯关闭if++TimeCount!=8return;TimeCount=0;YELLOWB=~YELLOWB;GREENA=0;if++FlashCount!=10return;//闪烁FlashCount=0;OperationType=1;break;}//主程序voidmain{}42报警与旋转灯/*名称报警与旋转灯说明定时器控制报警灯旋转显示,并发出仿真警报声*/#include#include#defineucharunsignedchar#defineuintunsignedintsbitSPK=P3^7;ucharFRQ=0x00;//延时voidDelayMSuintms{}//INT0中断函数voidEX0INTinterrupt0{TR0=~TR0;//开启或停止两定时器,分别控制报警器的声音和LED旋转TR1=~TR1;ifP2==0x0045上海师范大学信息与机电工程学院—倪继锋TMOD=0x01;IE=0x82;TR0=1;while1;//T0方式1uchari;whilems--fori=0;iP2=0xe0;//开3个旋转灯elseP2=0x00;//关闭所有LED}//定时器0中断voidT0INTinterrupt1{TH0=0xfe;TL0=FRQ;SPK=~SPK;}//定时器1中断voidT1INTinterrupt3{TH1=-45000/256;TL1=-45000%256;P2=crolP21;}//主程序voidmain{}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;while1{}FRQ++;DelayMS1;//T
0、T1方式1//开启0,1,3号中断//INT0设为最高优先//定时器启停由INT0控制,初始关闭《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例#include#include#defineucharunsignedchar#defineuintunsignedintsbitSPK=P3^7;ucharFRQ=0x00;//延时voidDelayMSuintms{uchari;whilems--fori=0;i}ucharc=0x80;SCON=0x00;TI=1;while1{}c=crolc1;SBUF=c;whileTI==0;TI=0;//等待发送结束//TI软件置位44并行数据转换为串行数据/*名称并行数据转换为串行数据说明切换连接到并串转换芯片74LS165的拨码开关,该芯片将并行数据以串行方式发送到8051的RXD引脚,移位脉冲由TXD提供,显示在P0口*/#include#include#include#defineucharunsignedchar#defineuintunsignedintsbitSPL=P2^5;//shift/load//延时voidDelayMSuintms{47上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例uchari;whilems--fori=0;ivoidmain{SCON=0x10;}while1{}SPL=0;//置数load,读入并行输入口的8位数据//串口模式0,允许串口接收SPL=1;//移位shift,并口输入被封锁,串行转换开始whileRI==0;//未接收1字节时等待RI=0;//RI软件置位//接收到的数据显示在P0口,显示拨码开关的值P0=SBUF;DelayMS20;45甲机通过串口控制乙机LED/*名称甲机发送控制命令字符说明甲单片机负责向外发送控制命令字符“A”、“B”、“C”,或者停止发送,乙机根据所接收到的字符完成LED1闪烁、LED2闪烁、双闪烁、或停止闪烁*/#include#defineucharunsignedchar#defineuintunsignedintsbitLED1=P0^0;sbitLED2=P0^3;sbitK1=P1^0;//延时voidDelayMSuintms{uchari;whilems--fori=0;ivoidPutctoSerialPortucharc{SBUF=c;whileTI==0;TI=0;48上海师范大学信息与机电工程学院—倪继锋《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例}//主程序voidmain{ucharOperationNo=0;SCON=0x40;//串口模式1TMOD=0x20;//T1工作模式2PCON=0x00;//波特率不倍增TH1=0xfd;TL1=0xfd;TI=0;TR1=1;while1{ifK1==0//按下K1时选择操作代码0,1,2,3{whileK1==0;OperationNo=OperationNo+1%4;}switchOperationNo//根据操作代码发送A/B/C或停止发送{case0:LED1=LED2=1;break;case1:PutctoSerialPort\\A\\;LED1=~LED1;LED2=1;break;case2:PutctoSerialPort\\B\\;LED2=~LED2;LED1=1;break;case3:PutctoSerialPort\\C\\;LED1=~LED1;LED2=LED1;break;}DelayMS100;}}/*名称乙机程序接收甲机发送字符并完成相应动作说明乙机接收到甲机发送的信号后,根据相应信号控制LED完成不同闪烁动作*/#include#defineucharunsignedchar#defineuintunsignedintsbitLED1=P0^0;sbitLED2=P0^3;上海师范大学信息与机电工程学院—倪继锋49《单片机C语言程序设计实训100例---基于8051和PROTEUS仿真》案例//延时voidDelayMSuintms{uchari;whilems--fori=0;i}SCON=0x50;TMOD=0x20;PCON=0x00;TH1=0xfd;TL1=0xfd;RI=0;TR1=1;LED1=LED2=1;while1{ifRI}{//串口模式1,允许接收//T1工作模式2//波特率不倍增//波特率9600//如收到那么LED闪烁RI=0;switchSBUF//根据所收到的不同命令字符完成不同动作{}//关闭LEDcase\\A\\:LED1=~LED1;LED2=1;break;case\\B\\:LED2=~LED2;LED1=1;break;case\\C\\:LED1=~LED1;LED2=LED1;//LED1闪烁//LED2闪烁//双闪烁}elseLED1=LED2=1;DelayMS100;46单片机之间双向通信/*名称甲机串口程序说明甲机向乙机发送控制命令字符,甲机同时接收乙机发送的数字,并显示在数码管上*/#include#defineucharunsignedchar#defineuintunsignedintsbitLED1=P1^0;50上海师范大学信息与机电工程学院—倪继锋模板内容仅供参考 。