从零开始学51单片机C语言(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-07 09:48:20

点击下载

作者:刘建清

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

从零开始学51单片机C语言

从零开始学51单片机C语言试读:

前言

我们所处的时代是一个知识爆发的时代,新产品、新技术层出不穷,电子技术发展更是日新月异。当你对妙趣横生的电子世界发生兴趣时,首先要找一套适合自己学习的电子类图书阅读,“从零开始学电子”丛书正是为了满足零起点入门的电子爱好者而写的,全套丛书共有如下6册:

从零开始学电工电路

从零开始学电动机、变频器和PLC

从零开始学电子元器件识别与检测

从零开始学模拟电路

从零开始学数字电路

从零开始学51单片机C语言

和其他电子技术类图书相比,本丛书具有以下特点。

内容全面,体系完备。本丛书给出了电子爱好者学习电子技术的全方位解决方案,既有初学者必须掌握的电工电路、模拟电路和数字电路等基础理论,又有电子元器件检测、电动机等操作性较强的内容,还有变频器、PLC、51单片机、C语言等软硬件结合的综合知识。内容翔实,覆盖面广。掌握好本系列内容,读者就能熟练读懂有关电子科普类杂志,再稍加实践,必定能成为本行业的行家里手。

通俗易懂,重点突出。传统的图书在介绍电路基础和模拟电子等内容时,大都借助高等数学这一工具进行分析,电子爱好者自学电子技术时,必须先学高等数学,再学电路基础,门槛很高,使大多数电子爱好者被拒之门外,失去了学习的热情和兴趣。为此,本丛书在编写时,完全考虑到了初学者的需要,既不讲难懂的理论,也不涉及高等数学方面的公式,尽可能地把复杂的理论通俗化,将烦琐的公式简易化,再辅以简明的分析、典型的实例。这构成了本丛书的一大亮点。

实例典型,实践性强。本丛书最大限度地强调了实践性,书中给出的例子大都经过了验证,可以实现,并且具有代表性,本丛书中的单片机实例均提供有源程序,并给出实验方法,以方便读者学习和使用。

内容新颖,风格活泼。丛书所介绍的都是电子爱好者关心的、并且在业界获得普遍认同的内容。丛书的每一本都各有侧重,又互相补充,论述时疏密结合,重点突出,不拘一格。对于重点、难点和容易混淆的知识,书中用专用标识进行了标注和提示。

把握新知,结合实际。电子技术发展日新月异,为适应时代的发展,丛书还对电子技术的新知识做了详细的介绍。丛书中涉及的应用实例都是作者开发经验的提炼和总结,相信会对读者带来很大的帮助。在讲述电路基础、模拟和数字电子技术时,还专门安排了软件仿真实验,实验过程非常接近实际操作的效果。仿真软件不但提供了各种丰富的分立元件和集成电路等元器件,还提供了各种丰富的调试测量工具:电压表、电流表、示波器、指示器、分析仪等。仿真软件是一个全开放性的仿真实验平台,给我们提供了一个完备的综合性实验室,可以任意组合实验环境,搭建实验。电子爱好者通过实验,将使学习变得生动有趣,加深对电路理论知识的认识,一步一步走向电子制作和电路设计的殿堂。

总之,对于需要学习电子技术的电子爱好者而言,选择“从零开始学电子”丛书不失为一个良好选择。该丛书一定能给你耳目一新的感觉,当你认真阅读完本丛书后将会发现,无论是你所读的书,还是读完书的你,都有所不同。

为方便读者获取本书配套的开发软件及实例程序源代码,请购书后扫码加入专属QQ群(群号:781011353)。我们将提供与本书相关的资源,以供读者下载。前言

单片机就是把一个计算机系统集成到一个芯片上,概括地讲,一块芯片就成了一台计算机。目前市面上流行的单片机,其价格便宜,对于广大爱好者来说,购买的性价比很高。单片机再结合适当的硬件接口电路,还有什么事情做不到呢?作者对它的评价是八个字:软硬兼施,老少皆宜。

单片机虽然好玩,但是很多人经过一番探索之后却深感学好单片机并非易事,甚至连入门都感到困难。作者本人也是从一位电子爱好者成长为工程师的,此过程自然少不了学习、探索、实践、再学习、再实践这样一条规律,因此深切地知道单片机难学,主要是不得要领,难以入门。一旦找到学习的捷径,入了门,掌握简单程序的编写方法并观察到实际演示效果,必然会信心大增。接下来再向深度、广度进军时,心里就比较坦然了,最终能够一步一个脚印地去扩展自己的知识面,成为单片机的编程高手。

在与众多的单片机爱好者交流中得知,单纯讲单片机内部结构、指令太枯燥,且不易理解,他们感兴趣的是单片机编程的应用实例,而且主要喜欢简单、实用、有趣的初级实例。因此,编写本书的思路是以实战演练为主线贯穿全书,且提供了源程序的详细解读,这样初学者能够看得清、看得懂、学得快,从而达到一体化的学习效果。

在内容安排上,本书通过51单片机内部资源(中断系统、定时/计数器、串口通信)、键盘接口、LED数码管显示、LCD液晶显示、DS1302时钟芯片、I2C总线接口芯片AT24C04、DS18B20温度传感器、红外遥控、A/D和D/A转换、步进电机、LED点阵屏、语音电路等大量具体的实际例子以及几个综合实例,系统演练了51单片机中最为常用、最为典型的接口应用。另外,本书也包括了一些作者在学习和实际设计过程中总结的一些经验及方法,希望能够帮助大家更好地学习51单片机。

本书安排的例子大部分是由作者编写的,有一些是参考相关资料改写的,全部程序都经过作者调试并通过。对于例子的使用说明也描述得非常详细,力争让读者“看则能用,用则能成”,保证读者在动手的过程中体会到成功的乐趣。本书提供的所有实验都有完整的源程序和工具软件。从这个角度来讲,你拿到手上的不仅仅是一本书,更是我们过去几年实践经验的积累。

本书编写过程中,参阅了《无线电》《单片机与嵌入式系统应用》等杂志,并从互联网上搜索了一些有价值的资料,由于其中的很多资料经过多次转载,已经很难查到原始出处,谨在此向资料提供者表示感谢。

参加本书编写工作的还有宗军宁、刘水潺、宗艳丽等同志。由于作者水平有限,书中难免有疏漏之处,诚恳希望各位同行、读者批评指正。作者2019年4月第1章 51单片机基本组成

单片机的内部结构比较复杂,而且还非常不易懂,如果你用汇编语言编程,就必须对单片机的内部结构有一个详细的理解,否则,编程时就会有云里雾里的感觉。好在目前单片机编程一般采用C语言,采用C语言编程时,不必对单片机的硬件结构有深入的理解,只需对单片机的基本组成和常用寄存器用法作一了解即可,这大大降低了单片机入门的门槛和开发周期,为单片机爱好者提供了极大的方便。1.1 单片机内部结构与引脚1.1.1 单片机的内部结构组成

单片机虽然型号众多,但它们结构却基本相同,主要包括中央处理器(CPU)、存储器(程序存储器和数据存储器)、定时/计数器、并行接口、串行接口和中断系统等几大单元,图1-1所示的是51单片机内部结构框图。图1-1 51单片机内部结构框图

可以看出,51单片机虽然只是一个芯片,但“麻雀虽小,五脏俱全”,作为计算机应该具有的基本部件在单片机内部几乎都包括,因此,51单片机实际上就是一个简单的微型计算机系统。1. 中央处理器(CPU)

中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统的工作,完成运算和控制输入输出等操作。2. 存储器

存储器分为程序存储器(ROM)和数据存储器(RAM)两种。前者存放调试好的固定程序和常数,它是只读的,掉电数据不会丢失;后者存放一些随时有可能变动的数据,它是可读可写的,掉电后数据会消失。3. 定时/计数器

单片机除了具有运算功能外,还具有控制功能,所以离不开计数和定时。因此,在单片机中就设置有定时器兼计数器。4. 并行输入/输出(I/O)口

51单片机一般共有4组8位I/O口(P0、P2、P1和P3),用于与外部进行数据并行传输。5. 全双工串行口

51单片机内置一个全双工串行通信口,用于与其他设备间的串行数据传输。6. 中断系统

51 单片机具备较完善的中断功能,一般包括外部中断、定时/计数器中断和串行中断,以满足不同的控制要求。

现在,我们已经知道了单片机的组成,实际上,单片机内部有一条将它们连接起来的“纽带”,即所谓的“内部总线”。而CPU、ROM、RAM、I/O口、中断系统等就分布在此“总线”的两旁,并和它连通。一切指令、数据都可经“内部总线”传输。

以上介绍的是51单片机的基本组成部分,各种型号的51单片机包括STC89C5X、AT89S5X等,都是在51单片机内核的基础上进行功能的增强和改装而成。1.1.2 单片机的引脚

51单片机虽然型号众多,同一封装的51单片机其管脚配置基本一致。图1-2所示的是采用PDIP40(40脚双列直插式)封装的51单片机引脚配置图。图1-2 51单片机引脚配置图

40个引脚中,正电源和地线2个,外置石英振荡器的时钟线2个,复位引脚1个,控制引脚3个,4组8位I/O口线32个。1. 电源和接地引脚(2个)

GND(20脚):接地脚。

VCC(40脚):正电源脚,接+5V电源。2. 外接晶体引脚(2个)

XTAL1(19脚):时钟XTAL1脚,片内振荡电路的输入端。

XTAL2(18脚):时钟XTAL2脚,片内振荡电路的输出端。

时钟电路为单片机产生时序脉冲,单片机所有运算与控制过程都是在统一时序脉冲的驱动下进行的。时钟电路就好比人的心脏,如果人的心跳停止了,生命就会停止;如果单片机的时钟电路停止工作,那么单片机也就停止运行了。

51单片机的时钟有两种方式,一种是片内时钟振荡方式,但需在18和19脚外接石英晶体和振荡电容;另外一种是外部时钟方式,即将外引脉冲信号从XTAL1引脚注入,而XTAL2引脚悬空。3. 复位电路

RST(9脚):复位信号引脚。

当振荡器运行时,在此引脚上出现2个机器周期以上的高电平将使单片机复位。一般在此引脚与GND之间连接一个下拉电阻,与VCC引脚之间连接一个电容。单片机复位后,从程序存储器的0000H单元开始执行程序,并初始化一些专用寄存器为复位状态值。4. 控制引脚(3个)(29脚):外部程序存储器的读选通信号。在读外部程序存储器时,产生负脉冲,以实现对外部程序存储器的读操作。

ALE/(30脚):地址锁存允许信号。当访问外部存储器时,ALE用来锁存P0扩展地址低8位的地址信号;在不访问外部存储器时,ALE端以固定频率(时钟振荡频率的l/6)输出,可用于外部定时或其他需要。另外,该脚还是一个复用脚,在编程期间,将用于输入编程脉冲。/VPP(31脚):内外程序存储器选择控制引脚。当接高电平时,单片机先从内部程序存储器取指令,当程序长度超过内部Flash ROM的容量时,自动转向外部程序存储器;当为低电位时,单片机则直接从外部程序存储器取指令。例如,AT89S51/52单片机内部有4KB/8KB的程序存储器,因此,一般将接到+5V高电平,让单片机运行内部的程序。而对于内部无程序存储器的8031(现在已很难见到),端必须接地。另外,/VPP还是一个复用脚,在用通用编程器编程时,VPP脚需加上12V的编程电压。5. 输入/输出引脚(32个)(1)P0口P0.0~P0.7(39~32脚)

P0口是一个8位漏极开路的“双向I/O口”,需外接上拉电阻,每根I/O口线可以独立定义为输入或输出,输入时须先将其置“1”。P0口还具有第二功能,即作为地址/数据总线;当作数据总线用时,输入8位数据;而当作地址总线用时,则输出8位地址。(2)P1口P1.0~P1.7(1~8脚)

P1口是一个带有内部上拉电阻的8位“准双向I/O口”,每根I/O口线可以独立定义为输入或输出,输入时须先将其置“1”。由于它的内部有一个上拉电阻,所以连接外围负载时不需要外接上拉电阻,这一点与下面将要介绍的P2、P3口都一样,与上面介绍的P0口不同,请大家务必注意!

对于AT89S51/52单片机,P1口的部分引脚还具有第二功能,如表1-1所示。表1-1 AT89S51/52单片机P1口部分引脚的第二功能

顺便说一下,STC89C51/C52与AT89S51/52有所不同,其P1.5、P1.6、P1.7脚没有第二功能,STC89C51/C52的ISP下载编程是通过串口进行的。(3)P2口P2.0~P2.7(21~28脚)

P2口是一个带有内部上拉电阻的8位“准双向I/O口”,每根I/O口线可以独立定义为输入或输出,输入时须先将其置“1”。由于它的内部有一个上拉电阻,所以连接外围负载时不需要外接上拉电阻。同时,P2口还具有第二功能,在访问外部存储器时,它送出地址的高8位,并与P0口输出的低地址一起构成16位的地址线,从而可以寻址64KB的存储器(程序存储器或数据存储器),P2口的第二功能很少使用,请大家不必过深研究。(4)P3口P3.0~P3.7(10~17脚)

P3口是一个带有内部上拉电阻的8位“准双向I/O口”,每根I/O口线可以独立定义为输入或输出,输入时须先将其置“1”。由于它的内部有一个上拉电阻,所以连接外围负载时不需要外接上拉电阻。同时,P3口还具有第二功能,第二功能如表1-2所示。这里要说明的是,当P3口的某些I/O口线作为第二功能使用时,不能再把它当作通用I/O口使用,但其他未使用的I/O口线可作为通用I/O口线。

P3口的第二功能应用十分广泛,我们会在后续章节中进行详细说明。表1-2 P3口的第二功能1.2 单片机的存储器

我们知道,存储器分为程序存储器和数据存储器两部分,顾名思义,程序存储器用来存放程序,数据存储器用来存放数据。那么,什么是程序?什么是数据呢?它们又是怎样存放的呢?

程序就是我们“费九牛二虎之力”编写的代码,需要用通用编程器、下载线等写到单片机的程序存储器中,写好后,单片机就可以按照我们的要求进行工作了。由于断电后要求程序不能丢失,因此,程序存储器必须采用ROM、EPROM、Flash ROM等类型。

程序写到单片机后,需要通电运行,程序运行过程中,需要产生大量中间数据和运行结果,这些数据放在什么地方呢?就放在数据存储器中,由于这些数据一般不要求进行断电保存,因此,数据存储器大都采用RAM类型。

重点提示:有些单片机如STC89C51/52等,内部还有EEPROM数据存储器,这类存储器主要用来存储一些表格、常数、密码等,存储后,即使掉电,数据也不会丢失。但是,由于EEPROM的写入速度相对较慢,须用几个ms才能完成1字节数据的写操作,如果使用EEPROM存储器替代RAM来存储变量,就会大幅度降低处理器的速度,同时,EEPROM只能经受有限次数(一般在10万次左右)的写操作,所以,EEPROM通常只是为那些在掉电的情况下需要保存的数据预留的,不能用EEPROM代替RAM。另外,我们平时一提到数据存储器,一般指的也是RAM,而不是EEPROM。

不同的单片机,其存储器的类型及大小有所不同,如AT89S51的程序存储器采用的是4KB的Flash ROM,数据存储器采用的是128B的RAM;AT89S52的程序存储器采用的是8KB的Flash ROM,数据存储器采用的是256B的RAM。STC89C51/52内部Flash ROM分别为4KB和8KB,RAM要大一些,均为512B。一般情况下,单片机内部的存储器足够使用,如果内部存储器不够时,则可进行扩展,扩展后的单片机系统就具有内部程序存储器、内部数据存储器、外部程序存储器和外部数据存储器四个存储空间。图1-3给出了AT89S51/52存储器的配置图。图1-3 AT89S51/52存储器配置图1.3 单片机的最小系统电路

单片机的正常工作,离不开工作电源、振荡电路和复位电路三个基本条件。能让单片机运行起来的最小硬件连接就是单片机的最小系统电路,如图1-4所示。图1-4 单片机最小系统电路1.3.1 单片机的工作电源

51单片机的40脚接5V电源,20脚接地,为单片机提供工作电源,由于目前的单片机均内含程序存储器,因此,在使用时,一般需要将31脚接电源(高电平)。1.3.2 单片机的复位电路

复位是单片机的初始化操作,其主要功能是把程序存储器初始化为0000H,使单片机从0000H单元开始执行程序。除了进入系统的正常初始化之外,当由于程序运行出错或操作错误使系统处于死锁状态时,也需按复位键以重新启动。

51单片机的RST引脚是复位信号的输入端,复位信号是高电平有效,其有效时间应持续24个振荡脉冲周期(即2个机器周期)以上。通常为了保证应用系统可靠地复位,复位电路应使引脚RST脚保持10ms以上的高电平。只要引脚RST保持高电平,单片机就循环复位。当引脚RST从高电平变为低电平时,单片机退出复位状态,从程序存储器的0000H地址开始执行用户程序。

复位操作有上电自动复位和按键手动复位两种方式。

上电复位的过程是在加电时,复位电路通过电容加给RST端一个短暂的高电平信号,此高电平信号随着VCC对电容的充电过程而逐渐回落,即RST端的高电平持续时间取决于电容的充电时间。

手动复位需要人为在复位输入端RST上加入高电平。一般采用的办法是在RST端和正电源VCC之间接一个按钮,当按下按钮时,则VCC的+5V电平就会直接加到RST端。即使按下按钮的动作较快,也会使按钮保持接通达数十毫秒,保证能满足复位的时间要求。1.3.3 单片机的时钟电路

时钟电路用于产生时钟信号,单片机本身是一个复杂的同步时序电路,为了保证同步工作方式的实现,单片机应设有时钟电路。

在单片机芯片内部有一个高增益反相放大器,其输入端为芯片引脚XTAL1,输出端为引脚XTAL2,在芯片的外部通过这两个引脚跨接晶体振荡器和微调电容,形成反馈电路,就构成了一个稳定的自激振荡器,如图1-5所示。图1-5 单片机的振荡电路

电路中对电容C1和C2的要求不是很严格,如使用高质的晶振,则不管频率多少,C1、C2一般都选择30pF。对于AT89S51/52单片机,晶体的振荡频率范围是0~33MHz,晶体振荡频率越高,则系统的时钟频率越高,单片机运行速度也越快。第2章 走进单片机开发的世界

本章以一个LED流水灯为例,教你在低成本实验开发板上,一步一步学习单片机开发。只要按照本章所述内容进行学习和操作,即可很快编写出自己的第一个单片机程序,并通过实验开发板看到程序的实际运行结果,从而熟悉单片机实验开发的全过程。通过本章的学习,你将会发现,单片机并不神秘,也不高深,它好玩、有趣,老少皆宜。2.1 单片机C语言入门

51单片机的编程语言主要有两种,一种是汇编语言,另一种是C语言。汇编语言的机器代码执行效率很高,但可读性却不强,复杂一点的程序就更难读懂,而C语言虽然在机器代码生成效率上不如汇编语言,但可读性和可移植性却远远超过汇编语言,而且C语言还可以嵌入汇编来解决高时效性的代码编写问题。因此,在掌握一定汇编语言的基础上,就需要进一步学习C语言编程了。2.1.1 C语言的特点

C语言是一种结构化语言。它层次清晰,便于按模块化方式组织程序,易于调试和维护。C语言的表现能力和处理能力极强,它不仅具有丰富的运算符和数据类型,便于实现各类复杂的数据结构。它还可以直接访问内存的物理地址,进行位(bit)一级的操作。由于C语言实现了对硬件的编程操作,因此C语言集高级语言和低级语言的功能于一体,效率高、可移植性强,特别适合单片机系统的编程与开发。2.1.2 单片机采用C语言编程的好处

与汇编语言相比,C语言在功能性、结构性、可读性、可维护性上有明显的优势,因而易学易用。用过汇编语言后再使用C语言来开发,体会会更加深刻。下面简要说明单片机采用C语言编程的几点好处。1. 语言简洁,使用方便、灵活

C语言是现有程序设计语言中规模最小的语言之一,C语言的关键字很少,ANSI C标准一共只有32个关键字,9种控制语句,压缩了一切不必要的成分。C语言的书写形式比较自由,表达方法简洁,使用一些简单的方法就可以构造出相当复杂的数据类型和程序结构。同时,当前几乎所有单片机都有相应的C语言级别的仿真调试系统,调试十分方便。2. 代码编译效率较高

当前,较好的C语言编译系统编译出来的代码效率只比直接使用汇编语言低20%左右,如果使用优化编译选项甚至可以更低。况且,随着单片机技术的发展,ROM空间不断增加,51系列单片机中,片上ROM空间做到32KB、64KB的比比皆是,代码效率所差的20%已经不是一个重要问题。3. 无须深入理解单片机内部结构

采用汇编语言进行编程时,编程者必须对单片机的内部结构及寄存器的使用方法十分清楚;在编程时,一般还要进行RAM分配,稍不小心,就会发生变量地址重复或冲突。

采用C语言进行设计时,则不必对单片机硬件结构有很深入的了解,编译器可以自动完成变量存储单元的分配,编程者可以专注于应用软件部分的设计,大大加快了软件的开发速度。4. 可进行模块化开发

C语言是以函数作为程序设计的基本单位的,C语言程序中的函数相当于汇编语言中的子程序。各种C语言编译器都会提供一个函数库,此外,C语言还具有自定义函数的功能,用户可以根据自己的需要编写满足某种特殊需要的自定义函数(程序模块),这些程序模块可不经修改,直接被其他项目所用。因此采用C语言编程,可以最大限度地实现资源共享。5. 可移植性好

用过汇编语言的读者都知道,即使是功能完全相同的一种程序,对于不同的单片机,必须采用不同的汇编语言来编写。这是因为汇编语言完全依赖于单片机硬件。C语言是通过编译来得到可执行代码的,本身不依赖机器硬件系统,用C语言编写的程序基本上不用修改或者进行简单的修改,即可方便地移植到另一种结构类型的单片机上。6. 可以直接操作硬件

C语言具有直接访问单片机物理地址的能力,可以直接访问片内或片外存储器,还可以进行各种位操作。

介绍到这里,我想说一下我学习单片机编程的一个小插曲。在20世纪90年代中期,我最初接触单片机的时候,在我心中觉得51就是单片机,单片机就是51,根本不知道还有其他单片机的存在。那时,我学习的是汇编语言,根本不知道用C语言也可以进行单片机开发。幸运的是,我有一个同事,比较精通C语言,我们一起做一个项目的时候,我才真正发现C语言的威力,于是,在同事的影响下,我开始使用C语言进行单片机编程。其实我也很庆幸,学习和使用了两年多的汇编语言。由于这些锻炼,我对单片机底层结构和接口时序弄得很清楚。在使用C语言开发的时候,优化代码和处理中断就不会太费劲。

总之,用C语言进行单片机程序设计是单片机开发与应用的必然趋势,我们一旦学会使用C语言之后,就会对它爱不释手,尤其是进行大型单片机应用程序开发,C语言几乎是唯一的选择。2.1.3 如何学习单片机C语言

C语言常用语法不多,尤其是单片机的C语言常用语法更少,初学者没有必要将C语言的所有内容都学习一遍,只要跟着本书学下去,当遇到难点时,停下来适当地查阅C语言基础教材里的相关部分,便会很容易掌握。有关C语言的基础教材较多,在这里,笔者向大家推荐谭浩强的《C程序设计》一书,该书语言通俗,实例丰富,十分适合初学者学习和查阅。

C语言仅仅是一个编程语言,其本身并不难,难的是如何灵活运用C语言编写出结构完善的单片机程序。要达到这一点,就必须花费大量的时间进行实践、实验,光看书不动手,等于是纸上谈兵,很难成功!因此,本书主要是通过不断地实践、实战,使读者在玩中学,在学中玩,步步为营,步步深入,使自己在不知不觉中,成为单片机的编程高手。2.1.4 一个简单的流水灯程序

下面我们先来看一个实例,这个例子的功能十分简单,就是让单片机的P2口的LED灯按流水灯的形式进行闪烁,每个LED灯的闪烁时间为0.5s,硬件电路如图2-1所示。图2-1 点亮P2口LED灯电路

图中采用STC89C52单片机,这种单片机属于80C51系列,其内部有8KB的Flash ROM和512B(字节)的RAM,并且可以通过串口进行ISP程序下载,不需要反复插拔芯片,非常适于做实验。STC89C52的P2引脚上接8个发光二极管,RP7、RP9为限流电阻排,以免LED被烧坏;P2口是准双向口,可以外接上拉电阻,也可以不接,图中外接了RP13上拉电阻排。

根据要求,用C语言编写的程序如下。#include#define uint unsigned intsbit P20=P2^0; //定义位变量sbit P21=P2^1;sbit P22=P2^2;sbit P23=P2^3;sbit P24=P2^4;sbit P25=P2^5;sbit P26=P2^6;sbit P27=P2^7;void Delay_ms(uint xms) //延时程序,xms是形式参数{ uint i, j; for(i=xms;i>0;i--) //i=xms,即延时x毫秒,xms由实际参数传入一个值 { for(j=115;j>0;j--) {;} //此处分号不可少,表示是一个空语句 }}void main(){ while(1) //循环显示 { P20=0; //P20脚灯亮 Delay_ms (500); //将实际参数500传递给形式参数xms,延时0.5s P20=1; //P20脚灯灭 P21=0; //P21脚灯亮 Delay_ms (500); P21=1; //P21脚灯灭 P22=0; //P22脚灯亮 Delay_ms (500); P22=1; //P22脚灯灭 P23=0; //P23脚灯亮 Delay_ms (500); P23=1; //P23脚灯灭 P24=0; //P24脚灯亮 Delay_ms (500); P24=1; //P24脚灯灭 P25=0; //P25脚灯亮 Delay_ms (500); P25=1; //P25脚灯灭 P26=0; //P26脚灯亮 Delay_ms (500); P26=1; //P26脚灯灭 P27=0; //P27脚灯亮 Delay_ms (500); P27=1; //P27脚灯灭 }}

这里,采用单片机C语言编译器Keil软件作为开发环境,关于Keil软件的详细内容,将在后面进行介绍。

下面我们对这个程序进行简要的分析。

程序的第一行是“文件包含”,所谓“文件包含”是指一个文件将另外一个文件的内容全部包含进来。所以,这里的程序虽然只有几行,但C编译器(Keil软件)在处理的时候却要处理几十行或几百行。为加深理解,可以用任何一个文本编辑器打开Keil\c51\inc文件夹下面的reg52.h来看一看里面有什么内容,在C编译器处理这个程序时,这些内容也会被处理。这个程序包含reg.h的目的就是为了使用P2这个符号,即通知C编译器程序中所写的P2是指80C51单片机的P2端口,而不是其他变量,这是如何做到的呢?用写字板程序打开reg52.h显示如下。#ifndef __REG52_H__#define __REG52_H__/* BYTE Register */sfr P0 = 0x80;sfr P1 = 0x90;sfr P2 = 0xa0;sfr P3 = 0xb0;……#endif

可以看到:“sfr P2= 0xa0;”,即定义符号P2与地址0xa0对应,熟悉80C51内部结构的读者不难看出,P2口的地址就是0xa0。

程序的第2行是一个宏定义语句,注意后面没有分号。#define命令用它后面的第一个字母组合代替该字母组合后面的所有内容,也就是相当于我们给“原内容”重新起一个比较简单的“新名称”,方便以后在程序中使用简短的新名称,而不必每次都写烦琐的原内容。该例中,我们使用宏定义的目的就是将unsigned int用uint代替,在上面的程序中可以看到,在我们需要定义unsigned int类型变量时,并没有写unsigned int,取而代之的是uint。

程序的第3~10行用符号P20~P27来表示P2口的P2.0~P2.7八只引脚。在C语言里,如果直接写P2.0、P2.1……P2.7,C编译器并不能识别,而且它们不是一个合法的C语言变量名,所以得给它另起一个名字,这里起的名为P20~P27,可是P20~P27是否就是P2.0~P2.7呢?你这么认为,C编译器可不这么认为,所以必须给它们建立联系,这里使用了Keil的保留字sbit来定义。

main称为“主函数”,每一个C语言程序有且只有一个主函数,函数后面一定有一对大括号“{}”、在大括号里面书写其他程序代码。

Delay_ms(500)的用途是延时。由于单片机执行指令的速度很快,如果不进行延时,灯亮之后马上就灭,灭了之后马上就亮,速度太快,人眼根本无法分辨,所以需要进行适当的延时,这里采用自定义函数Delay_ms(500),以延时0.5s的时间,函数前面的void表示该延时函数没有返回值。

Delay_ms(500)函数是一个自定义函数,它不是由Keil编译器提供的,即你不能在任何情况下写这样一行程序以实现延时,如果在编写其他程序时写上这么一行,会发现编译通不过。注意观察本程序会发现,在使用Delay_ms(500)之前,第11~16行已对Delay_ms(uint xms)函数进行了事先定义,因此,在主程序中才能采用Delay_ms(500)进行调用。

注意,在延时函数Delay_ms(uint xms)定义中,参数xms被称作“形式参数”(简称形参);而在调用延时函数Delay_ms(500)中,小括号里的数据“500”,这个“500”被称作“实际参数”(简称实参)。参数的传递是单向的,即只能把实参的值传给形参,而不能把形参的值传给实参。另外,实参可以在一定范围内调整,这里用“500”来要求延时时间为0.5s,如果是“1000”,则延时时间是1000ms,即1s。

在延时函数Delay_ms(uint xms)内部,采用了两层嵌套for语句,如下所示。void Delay_ms(uint xms) //延时程序,xms是形式参数{ uint i, j; for(i=xms;i>0;i--) //i=x毫秒,即延时xms,xms由实际参数传入一个值 { for(j=115;j>0;j--) {;} //此处分号不可少,表示是一个空语句 }}

在这个延时函数中,采用的是一种比较正规的形式,C语言规定,当循环语句后面的大括号只有一条语句或为空时,可省略大括号,因此,上面两个for循环语句中的大括号都可以省略,也就是说,可以采用以下简化的形式。void Delay_ms(uint xms) //延时程序,xms是形式参数{ uint i, j; for(i=xms;i>0;i--) //i=xms,即延时x毫秒,xms由实际参数传入一个值 for(j=115;j>0;j--); //此处分号不可少 }

第一个for后面没有分号,那么编译器就会认为第二个for语句就是第一个for语句的内部语句,而第二个for语句后面有分号,编译器就会认为第二个for语句内部语句为空。程序在执行时,第一个for语句中的i每减一次,第二个for语句便执行115次,因此上面这个例子便相当于共执行了xms×115次for语句。通过改变xms变量的值,可以改变延时时间。2.1.5 利用C51库函数实现流水灯

上面介绍的程序虽然可以实现流水灯的功能,程序比较烦琐,下面采用C51自带的库函数_crol()_()来实现,具体源程序如下所示。#include#include#define uint unsigned int#define uchar unsigned charvoid Delay_ms(uint xms) //延时程序,xms是形式参数{ uint i, j; for(i=xms;i>0;i--) //i=xms,即延时x毫秒,xms由实际参数传入一个值 for(j=115;j>0;j--); //此处分号不可少 }void main(){ uchar led_data=0xfe; //给led_data赋初值0xfe,点亮第一个LED灯 while(1) //大循环 { P2= led_data; Delay_ms(500); led_data=_crol_(led_data,1);//将led_data循环左移1位再赋值给led_data }}

该源程序在ch2/my_8LED文件夹中。

显然,这个流水灯程序比上面的流水灯程序要简捷许多,下面简要进行说明。

程序中,_crol_是一个库函数,其函数原形为:unsigned char _crol_(unsigned char c, unsigned char b);

这个函数是C51自带的库函数,包含在intrins.h头文件中,也就是说,如果在程序中要用到这个函数,那么必须在程序的开头处包含intrins.h这个头文件。函数实现的功能是,将字符c循环左移b位。

函数中,_crol_是函数名,不用多讲,函数前面没有void,取而代之的是unsigned char,表示这个函数返回值是一个无符号字符型数据;有返回值的意思是说,程序执行完这个函数后,通过函数内部的某些运算而得出一个新值,该函数最终将这个新值返回给调用它的语句。小括号里有两个形参,unsigned char c和unsigned char b,它们都是无符号字符型数据。

现在我们应该清楚led_data=_crol_(led_data,1)这条语句的含义了,其作用就是,将led_data中的数据向左循环移1位,再赋给变量led_data。

有左移位库函数,当然也有右移库函数,函数原形为:unsigned char _cror_(unsigned char c, unsigned char b);

右移位函数与左移位函数使用方法相同,这里不再重复。2.1.6 小结

通过以上的几个简单的C语言程序,我们可以总结出以下几点。(1)C程序是由函数构成的。一个C源程序至少包括一个函数,一个C源程序有且只有一个名为main()的函数,也可能包含其他函数,因此,函数是C程序的基本单位。主程序通过直接书写语句和调用其他函数来实现有关功能,这些其他函数可以是由C语言本身提供给我们的,这样的函数称之为库函数(流水灯程序中的_crol_(led_data,1)函数就是一个库函数),也可以是用户自己编写的,这样的函数称之为用户自定义函数(流水灯程序中的Delay_ms(uint xms)函数就是一个自定义函数)。那么,库函数和用户自定义函数有什么区别呢?简单地说,任何使用C语言的人,都可以直接调用C的库函数而不需要为这个函数写任何代码,只需要包含具有该函数说明的相应的头文件即可;而自定义函数则是完全个性化的,是用户根据自己的需要编写的。(2)一个函数由两部分组成。

① 函数的首部,即函数的第一行。包括函数名、函数参数(形式参数)等,函数名后面必须跟一对圆括号,即便没有任何参数也是如此。

② 函数体,即函数首部下面的大括号“{}”内的部分。如果一个函数内有多个大括号,则最外层的一对“{}”为函数体的范围。(3)一个C语言程序,总是从main函数开始执行的,而不管物理位置上这个main()放在什么地方。(4)主程序中的Delay_ms(uint xms)如果写成delay_ms(uint xms)就会编译出错,即C语言区分大小写,这是很多初学者在编写程序时常犯的错误,书写时一定要注意。(5)C语言书写的格式自由,可以在一行写多个语句,也可以把一个语句写在多行。没有行号(但可以有标号),书写的缩进没有要求。但是建议读者自己按一定的规范来写,可以给自己带来方便。(6)每个语句定义的最后必须有一个分号,分号是C语句的必要组成部分。(7)可以用/*…..*/的形式为C程序的任何一部分作注释,在“/*”开始后,一直到“*/”为止的中间的任何内容都被认为是注释;如果使用的是Keil开发软件,那么,该软件也支持C++风格的注释,就是用“//”引导的后面的语句是注释。这种风格的注释,书写比较方便,只对本行有效,在只需要一行注释的时候,我们往往采用这种格式。但要注意,只有Keil支持这种格式,其他的编译器不一定支持这种格式的注释。2.2 低成本单片机开发板介绍

学习单片机离不开开发板,边学边练,这样才能尽快掌握。目前,市场上这类产品种类很多,价格也相差很大,这里简单介绍几种低成本的、实用的开发板供学习时参考,当然,如果你具有一定的动手能力,也可以自己制作。2.2.1 低成本单片机开发板1

先介绍第一款低成本单片机开发板DD-900。DD-900实验开发板由笔者与顶顶电子共同开发,具有实验、仿真、ISP下载等多种功能,支持51系列和部分AVR单片机。只需一套DD-900实验开发板和一台计算机而不需要购买仿真器、编程器等其他任何设备,即可轻松进行学习和开发。图2-2所示的是DD-900实验开发板的实物图。图2-2 DD-900实验开发板实物图

1. DD-900实验开发板硬件资源十分丰富,可以完成单片机应用中几乎所有的实验,主要硬件资源和接口如下。(1)8路LED灯。(2)8位共阳LED数码管。(3)1602字符液晶接口。(4)12864图形液晶接口。(5)4个独立按键。(6)4×4矩阵按键。(7)RS232串行接口。(8)RS485串行接口。(9)PS/2键盘接口。(10)I2C总线接口EEPROM存储器AT24C04。(11)Microwire总线接口EEPROM存储器93C46。(12)8位串行A/D转换器ADC0832。(13)10位串行D/A转换器TLC5615。(14)实时时钟DS1302。(15)NE555多谐振荡器。(16)步进电机驱动电路ULN2003。(17)单总线温度传感器DS18B20。(18)红外遥控接收头。(19)1个蜂鸣器。(20)1个继电器。(21)AT89S系列单片机ISP下载接口。(22)3V输出接口。(23)单片机引脚外扩接口。

DD-900实验开发板主要硬件资源在板上的位置如图2-3所示。图2-3 DD-900实验开发板主要硬件资源在板上的位置

2. DD-900实验开发板的外扩接口插针J1、J2,可以将单片机的所有引脚引出,方便和外围设备(如无线遥控、nRF905无线收发等)进行连接。

3. 将仿真芯片(如SST89E516RD)插入到DD-900的锁紧插座上,配合Keil软件,可按单步、断点、连续等方式,对源程序进行仿真调试,也就是说,DD-900实验开发板可作为一台独立的51单片机仿真器使用。

4. 通过串口,DD-900实验开发板可完成对STC89CXX系列单片机的程序下载。同时,实验开发板还设有ISP下载接口,借助下载线(下面将要介绍)可方便地下载AT89S系列单片机程序。因此,DD-900实验开发板可作为一台独立的51单片机下载编程器使用。

5. DD-900实验开发板不但支持51单片机的实验、仿真、下载,也支持AVR系列单片机的实验、下载(代表型号:AT90S8515、ATmega8515L)。

6. DD-900实验开发板可完成很多实验,不同的实验可能会占用单片机相同的端口,为了使各种实验不相互干扰,需要对电路信号和端口进行切换。DD-900采用了“跳线”的形式来完成切换(共设置了7组,JP1~JP7),这种切换方式的特点是:可靠性高,编程方便,但操作起来比较麻烦,需要根据不同的实验来切实跳线的位置。

DD-900实验开发板下载程序时,需要采用计算机串口,由于目前的计算机大都取消了串口,因此,需要一根USB转串口线,这样,DD-900实验开发板就可以通过计算机的USB接口下载程序了,USB转串口线如图2-4所示。图2-4 USB转串口线2.2.2 低成本单片机开发板2

这是笔者在淘宝上看到的一款低成本的单片机开发板,价格只有几十元,单片机常见的功能基本都有,性价比很高,其外观如图2-5所示。图2-5 低价格单片机开发板2

该开发板可进行流水灯实验、LED显示实验、独立和矩阵按键实验、1602和12864液晶显示实验、点阵实验、A/D实验、D/A实验、DS1302时钟实验、EEPROM AT 24C02实验、步进电机和直流电机实验、红外遥控实验、DS18B20温度传感器实验等。通过外接插针接口,还可扩展一些其他实验。作为入门的初学者,这款实验板的功能已经足够使用。

这款实验板上安装有74HC138译码器和74HC245三态缓冲门,可以扩展较多的IO接口,实验时,可不用跳线或只需要少量跳线,即可完成不同的实验。

另外,该开发板集成有USB转串口芯片CH340,也就是说,把USB转串口线的功能也集成在开发板上,下载程序时,不用再购买USB转串口线,只需要一根普通的USB线,把计算机和开发板连接起来即可方便地下载程序。2.2.3 低成本单片机开发板3

这也是笔者在淘宝上看到的一款低成本的单片机开发板,价格同样便宜,只有几十元,其外观如图2-6所示。图2-6 低价格单片机开发板3

该开发板除没有集成LED点阵外,其他功能与上款开发板基本一致,也是一款非常适合初学者入门的开发板。2.2.4 低成本单片机开发板4

这款单片机开发板功能比以上几种要丰富一些,当然价格要稍高一点,在物价如此高的今天,一百多元也算是低成本的了,其外观如图2-7所示。图2-7 低成本单片机开发板4

和前几款相比,这款开发板最大的亮点有以下几点:一是可以进行双色点阵实验;二是设有彩屏接口,可行方便地进行彩屏实验;三是通过接外AVR核心板和ARM核心板(插入原51芯片的插座上)还可以进行AVR和ARM单片机的实验与学习。2.2.5 单片机仿真器

单片机仿真器是在产品开发阶段,用来替代单片机进行软硬件调试的、非常有效的开发工具。使用仿真器,可以对单片机程序进行单步、断点、全速等手段的调试,在集成开发环境Keil中,检查程序运行时单片机中RAM、寄存器内容的变化,观察程序的运行情况。使用仿真器可以迅速发现和排除程序中的错误,从而大大缩短单片机开发的周期。

下面仅介绍单片机的“片上仿真”。“片上仿真”是基于单片机本身的仿真,也就是说,只要一片单片机,不需要额外购买别的东西,就可以实现仿真。对于单片机爱好者来说,片上仿真是最高性价比的选择,各大单片机公司都已开发出不同性能的支持片上仿真的单片机。其中STC公司有一款性能很不错的片上仿真单片机——IAP15F2K61S2。

虽然IAP15F2K61S2也是40脚的单片机,但如果把它直接插在开发板上,你会发现单片机是不工作的。不仅IO接口不兼容,连VCC电源输入的位置也不同。接下来是外部晶体的使用,IAP15F2K61S2单片机不需要接外部晶体,因为它的内部集成了一个高精度的时钟源,可以用软件设置成5~30MHz的时钟频率。这一改进对我们使用者的意义是:不论我们做何应用,都不需要外接晶体的电路了。只要连接VCC和GND,单片机就可以工作。再连接TXD和RXD,单片机就能ISP下载和仿真了。因此,使用IAP15F2K61S2之前,需要制作一个IAP15F2K61S2转接板,还好,STC公司早已考虑到这一点,专门设计好了IAP15F2K61S2转接板,有兴趣的读者可到STC公司网站,下载IAP15F2K61S2转接板原理图、使用说明等相关资料。IAP15F2K61S2转接板实物图如图2-8所示。图2-8 IAP15F2K61S2转接板实物图

使用时,首先将IAP15F2K61S2转接板放在单片机开发板的锁紧插座中锁紧。然后与Keil调试软件配合,即可按单步、断点、连续等方式调试实际应用程序。

目前市场上除了上面介绍的IAP15F2K61S2转接板外,还有普中公司设计的一款仿真器,其外观和内部转接板如图2-9所示。图2-9 普中仿真器2.3 单片机开发六步走

本节中,将以一个LED流水灯为例,教你一步一步学习单片机开发,为单片机初学者寻找一条通向成功的“正确之路”“光明之路”。2.3.1 第一步:硬件电路设计与制作

硬件电路设计是一门大学问,若设计不周,轻则完不成任务,达不到要求,重则可能发生短路、烧毁元件等事故。要想设计一个功能完善、电路简捷的硬件电路,不但要熟悉掌握电子元器件、模拟电路、数字电路等基本知识,还要学会Protel(Altium Designer)软件的使用。

Protel是电子爱好者设计原理图和制作PCB图的首选软件,在国内的普及率很高,几乎所有的电子公司都要用到它。

Protel软件发展很快,主要版本有Protel 99 SE、Protel DXP、Protel DXP 2004,从Protel DXP 2004以后,Protel改名为Altium Designer,主要版本有Altium Designer 6.0、Altium Designer 6.9、Altium Designer 8.3等,目前最新版本为Altium Designer 18。使用Protel(Altium Designer)软件,既可以绘制规范的电路原理图,又可以制作出漂亮的PCB板。对于从事电子工程的技术人员,必须熟练掌握Protel;对于电子爱好者和初学者,如果还不能掌握,也可以使用市场上常见的万用板来代替PCB板。用万用板进行组装的特点是:方法简单,用料便宜,但组装时对焊接和连线有较高的要求。

在本书以后的实验中,基本都采用实验开发板进行学习和实验,也就是说,硬件电路我们已为你设计好了。但如果在实践中进行单片机开发,硬件电路设计与制作是必不可少的步骤,甚至非常重要。

为了方便,我们仍以前面介绍的流水灯为例进行演示,在前面介绍的“低成本单片机开发板2”上(实物图参见图2-5)进行实验,流水灯电路原理图参见图2-1。2.3.2 第二步:编写程序

想让单片机按你的意思(想法)完成一项任务,必须先编写供其使用的程序,编写单片机的程序应使用该单片机可以识别的“语言”,否则你将是对“机”弹琴。通过前面的学习我们知道,单片机编程语言主要有汇编语言和C语言,这里,我们会选用C语言进行编程。

编写程序时需要软件开发平台,我们选用Keil软件。Keil软件是51单片机实验、开发中应用最为广泛的软件,界面友好,易学易用,在调试程序、软件仿真方面也有很强大的功能。因此,很多开发51应用的工程师或普通的单片机爱好者,都对它十分喜欢。

Keil软件提供了文本编辑处理、编译链接、项目管理、窗口、工具引用和软件仿真调试等多种功能,通过一个集成开发环境(μVision IDE)将这些部分组合在一起。使用Keil软件,可以对汇编语言程序进行汇编,对C语言程序进行编译,对目标模块和库模块进行链接以产生一个目标文件,生成Hex文件,对程序进行调试等。另外,Keil还具有强大的仿真功能,在仿真功能中,有两种仿真模式:软件模拟方式和硬件仿真。在软件模拟方式下,不需要任何51单片机硬件即可完成用户程序仿真调试,极大地提高了用户程序开发效率;在硬件仿真方式下,借助仿真器(仿真芯片),可以实现用户程序的实时在线仿真。

总之,Keil软件功能强大,应用广泛,无论是单片机初学者,还是单片机开发工程师,都必须掌握好、使用好。

下面,我们就开始启动Keil,用C语言编写8位流水灯程序。

1. 先在F盘(其他位置也可以)新建一个文件夹,命名为my_8LED,用来保存8位流水灯程序。点击“Project”菜单,选择下拉式菜单中的“New μVision Project”,弹出文件对话窗口,选择你要保存的路径,在“文件名”中输入你的第一个C程序项目名称,这里我们用“my_8LED”,如图2-10所示。图2-10 保存文件对话框

保存后的文件扩展名为uvproj,这是Keil项目文件扩展名,以后我们可以直接点击此文件以打开先前做的项目。

2. 点击“保存”后,这时会弹出一个选择器件对话框,要求你选择单片机的型号,你可以根据你使用的单片机来选择。Keil几乎支持所有的51核的单片机,在这里,我们选择AT89S52,如图2-11所示,然后单击【OK】按钮。图2-11 选择单片机型号对话框

Keil中没有STC89C系列单片机型号,如果你制作的实验开发板采用STC89C52等单片机,仍然可以选用AT89S52。由于STC89C52单片机中的个别寄存器和AT89S52有所不同,因此,在使用这些不同的寄存器,需要在程序中用sfr关键字进行声明。

值得庆幸的是,宏晶科技公司的下载软件,提供了一项功能,可以把STC单片机加载到Keil软件,这为选择和使用STC单片机提供了极大的方便。

加载和使用方法如下。(1)到宏晶科技公司官网下载STC-ISP软件,打开STC-ISP

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载