第5章

51单片机的定时/计数器和串口











在前面各章的案例中都多次用到了定时。通过执行延时子程序实现期望的定时功能,称为软件定时。在执行软件定时的过程中,CPU无法进行其他操作,效率比较低。考虑到定时功能在各种计算机系统中大量用到,目前几乎所有的单片机内部都集成了定时/计数器,利用这一内部资源可以实现可编程的定时和计数功能。

在现代社会生产和生活中,很多时候需要将多个单片机系统相互连接起来,实现信息的交换、传递和共享。当传输距离比较近时,可以采用速度比较快的并行传输。如果传输距离比较远,为节省系统构建和信息传输的成本,通常采用串行通信。

本章将对51单片机中的定时/计数器和串行通信接口这两大重要内部资源进行详细介绍。

5.1磨刀霍霍——预备知识

作为本章内容的入门,这里首先对定时、计数、串行通信及接口的基本概念做个简要了解。

5.1.1定时和计数的基本概念

从基本工作原理的角度看,51单片机内部集成的定时/计数器实质上都是一个数字计数器,因此这里首先对数字电子技术中的计数器及相关概念做简要复习。



图5174161的引脚

在数字电子技术中,利用D触发器或JK触发器的串联,可以实现多位二进制计数。以集成4位二进制计数器74161为例,其外部引脚如图51所示,功能表如表51所示。

74161内部由4个JK触发器构成计数器。在引脚CLR为高电平期间,当引脚LOAD端送入负脉冲时,在时钟脉冲CLK的上升沿,由A~D端子送入的4位二进制数打入芯片内部,并立即出现在QA~QD输出端。这4位二进制数称为预置数,又称为计数初值。

在CLR、ENP和ENT都为高电平期间,由CLK端每送入一个时钟脉冲,计数器的计数值递增1。CLK端送入的周期脉冲称为计数脉冲。当ENP或ENT端为低电平时,内部计数器暂停计数,计数值将保持不变,称为门控信号。

当计数值达到15,即4位二进制数为1111B时,RCO端输出一个正脉冲,称为计数溢出。之后,又从0000B开始重新计数,也可以通过LOAD输入一个正脉冲重装计数初值并重新计数。



表5174161的引脚功能表




清零预置使能时钟预置数据输入计数值输出



CLRLOADENPENTCLKABCDQAQBQCQD


LLLLL
HL上升沿ABCDABCD
HHL保持不变
HHL保持不变
HHHH上升沿计数


1. 定时和计数

利用74161这样的数字计数器,最基本的功能当然是实现计数(Count),也就是统计在指定时间内计数脉冲的个数。例如,假设计数开始前设置计数初值为0,由外部电路产生的脉冲作为计数脉冲从CLK端送入,则在某段给定的时间结束后,根据当前计数值即可确定该段时间内外部电路送入脉冲的个数。在实际系统中,利用计数功能可以实现外部事件出现次数的统计、脉冲宽度或频率的测量等功能。

如果计数脉冲来自一个标准的时钟脉冲,其频率或周期是已知的、恒定不变的,则计数器从给定的计数初值开始计数,直到计数溢出时,其间经过的时间可以由设定的计数初值确定,这样的功能称为定时(Time)。利用计数溢出信号可以实现很多定时控制功能,例如实现期望的延时,当期望的延时时间到后,切换LED的亮灭状态,或者使并口某个引脚的高/低电平状态翻转以输出指定频率的周期脉冲等。

例如,假设计数脉冲周期为1 ms,计数初值设为0111B,则当计数溢出时,一共经过了15-7=8个计数脉冲周期,因此从开始计数到计数溢出,一共经过了8 ms的时间。反之,如果希望从启动计数开始,要求经过10 ms的时间计数器出现溢出,则可以在计数开始前设置计数初值为15-10=5=0101B。

由此可见,任何一个计数器都可以实现计数和定时功能,二者基本的区别在于计数脉冲是已知频率和周期的,还是频率和周期未知或者不确定的。如果计数脉冲是频率恒定的时钟脉冲,则一般用于实现定时; 如果计数脉冲的频率或周期是未知的,或者不断变化的,则一般用于实现计数。实现定时功能的电路称为定时器(Timer); 实现计数功能的电路称为计数器(Counter)。二者统称为定时/计数器。

2. 可编程定时/计数器

所谓可编程定时/计数器,指的是计数器的所有或部分功能(包括计数初值的装入,计数过程的启停、计数溢出信号的检测等)由CPU通过执行程序来实现,从而能够将硬件和软件实现的优点综合起来,实现灵活的设置和控制,又不占用CPU过多的时间。

一个典型的可编程定时/计数器与CPU的连接可以用图52表示。工作过程中,CPU通过执行指令向定时/计数器送出计数初值,并发送启停控制信号。一旦启动,定时/计数器就在计数脉冲的作用下,不断地自动递增或递减计数。在计数过程中,CPU还能随时通过执行相应的指令暂停或终止计数。



图52可编程定时/计数器与CPU的连接


在计数过程中,CPU能随时通过指令读取计数值。当计数器发生计数溢出时,CPU可以及时检测并作出反应,也可以在计数溢出时由定时/计数器主动向CPU发出信号标志。

上述所有操作都是由CPU内部通过执行指令实现的,也就是能够对定时/计数器的工作过程进行程序控制。例如,在程序中可以通过指令灵活地修改定时/计数器的计数初值以实现不同长度的定时,检测到计数溢出后执行预定的操作,根据需要暂停计数或者重新开始计数等。

MCS51的51子系列单片机内部集成了2个可编程定时/计数器T0和T1,52子系列还增加了一个T2。这些定时/计数器作为51单片机集成的内部资源,可以实现16位、13位或8位计数。每个定时/计数器都有多种工作方式可供选择,其中T0有4种,T1和T2分别有3种。定时/计数器产生的进位溢出使相应的位单元置位,程序中通过查询该位或采用中断方式进行处理。

3. 脉冲频率和宽度测量的基本原理

定时/计数器一个典型的应用是实现脉冲宽度、频率或周期的测量。这里说的脉冲可以是一个单脉冲或周期脉冲。对于周期脉冲,其宽度也就代表了脉冲的周期,周期的倒数等于脉冲的频率。

(1) 脉冲宽度和周期的测量。

为了测量一个脉冲的宽度,可以将待测脉冲作为计数器的启停控制信号(例如74161的门控信号ENP或ENT),将另一个标准的时钟脉冲作为计数脉冲。在待测脉冲为高电平期间,计数器不断对计数脉冲进行计数,每来一个标准时钟脉冲,计数值递增1。当待测脉冲高电平结束,脉冲变为低电平时,计数器立即停止计数。此时根据当前计数值和设置的计数初值以及标准脉冲的周期,即可计算得到待测脉冲高电平持续的时间,即脉冲的宽度。

假设标准脉冲的周期为Tc,计数初值为N0,待测脉冲高电平结束时刻的当前计数值为N,则待测脉冲的宽度为T=NTc。如果待测脉冲为占空比等于50%的周期方波,则将上述结果再乘以2,即可得到脉冲的周期。上述测量原理可以用图53表示。



图53脉冲宽度的测量


显然,根据上述测量的基本原理,由于计数值只能是整数,因此待测脉冲的宽度必须大于标准脉冲的周期。另外,在计数的开始和结束时刻,待测脉冲和标准脉冲的正负跳变不一定同步,这将导致计数结果N出现±1个字的波动。因此,为保证测量精度,一般要求待测脉冲的宽度或周期远大于标准脉冲的周期。同时,一般的计数器都有计数范围的限制(例如74161的最大计数值为15),这又要求待测脉冲相对于标准脉冲的周期不能太大,否则在计数过程中将出现溢出,导致测量结果错误。

(2) 脉冲频率的测量。

利用上述方法测得脉冲的周期后,取倒数即可得到周期脉冲的频率。在51单片机系统中,还广泛采用另一种方法实现周期脉冲频率的测量。这种测量方法是基于频率最基本的概念提出来的。

所谓周期脉冲的频率,指的是单位时间内脉冲的个数。因此,如果用一个计数器工作在定时方式,定时设为单位时间(例如1 s),同时让另一个计数器工作在计数方式,在定时1 s时间内,统计待测脉冲的个数,则该计数值也就是脉冲的频率。实际系统中考虑到定时/计数器的位数、计数值的范围以及测量的实时性等,定时单位时间不一定是1 s。例如,假设定时时间长度为1 ms,则只需要将计数结果乘以1000,即可得到待测脉冲的频率。也可以直接用计数值表示频率,但单位为kHz。

上述测量原理可以用图54表示。显然,采用这种方法测量频率,要求待测脉冲的周期不能超过定时的时间长度,或者说频率不能过低,否则将带来比较大的相对测量误差。另外,实际的计数器都有计数范围(最大计数值)的限制,这又决定了待测脉冲的频率不能太高,否则在定时的单位时间范围内计数器将出现溢出,导致计数和测量结果错误。



图54脉冲频率的测量

5.1.2串行通信与串口

计算机系统中各部件之间的数据传输或者通信有两种基本的形式,即并行通信和串行通信。并行通信通常使用多条数据线将数据字节的各个位同时传输,每一位二进制数据分别通过一条传输线进行传输,另外还需要一条或几条控制信号线。并行通信的示意图如图55(a)所示。

串行通信是将数据字节分成一位一位的形式在一条传输线上逐个传输。一次只能传输一位,对于1字节的数据,至少要分8位才能传输完毕,如图55(b)所示。



图55并行通信与串行通信


并行通信相对传输速度快。但由于传输线较多,长距离传输时成本高,因此这种方式适合于短距离的数据传输。串行通信所需的传输线少,连线简单,但传输速度慢,适用于远距离或数据量少的通信,其传输距离可以从几米直到几千千米。

1. 串行通信的基本概念

串行通信又可以分为同步和异步通信、单工和双工通信等。这里对相关的几个基本概念做些简要介绍。

(1) 同步通信和异步通信。

串行通信可以采用同步和异步两种通信方式。在同步串行通信中,通过一条同步时钟线将同步时钟同时加到收发双方,双方数据的发送和接收都由同一个时钟控制完全同步地进行。



图56同步通信及数据帧格式

同步传输用来对数据块进行传输,一个数据块中可以包含若干连续的字符数据,并严格按照事先约定的通信协议确定每个数据帧的传输格式(例如,数据的位数、数据中各位的传输顺序等),通信过程中以特定的位组合作为帧的开始和结束标志(称为同步字符)。同步通信中数据帧的格式如图56所示。

异步串行通信是指收、发双方分别使用各自的时钟控制数据的发送和接收,这样可省去连接收、发双方的一条同步时钟信号线,使得异步串行通信连接更加简单且容易实现。

异步传输以字符为单位进行数据传输,每个字符的传输都从起始位开始、到停止位结束,字符与字符之间的间隙(时间间隔)不固定,但字符中的各位以固定的时间传输,即字符之间是异步的,但同一字符内的各位之间是同步的。

在单片机中集成的串口采用的是异步串行通信方式,其传输的数据格式如图57所示。当没有数据发送时,数据线保持为高电平状态。在发送数据时,先发送起始位,即将数据线复位为低电平,然后再逐位发送数据。数据发送完毕后再使数据线变为高电平,即向接收方发送一位停止位。



图57异步通信及数据格式


异步串行通信不要求收、发双方时钟严格一致,实现容易,成本低,但是每个数据帧的传送都要附加起始位、停止位,有时还要再加上校验位,因此传输效率不高。

(2) 单工和双工通信。

按照信号传输的方向,一般又将串行通信分为单工方式、半双工方式和全双工方式三种。

所谓单工方式,指的是信号(不包括联络信号)在信道中只能沿一个方向传输,而不能沿相反方向传输,如图58(a)所示。显然这种情况下只需要一根数据线即可实现数据的传输。 

所谓半双工方式,指的是通信双方均具有发送和接收信息的能力,信道也具有双向传输性能,但是通信的任何一方不能同时既发送信息又接收信息,即在指定时刻数据只能沿某一个方向传输,如图58(b)所示。半双工方式大多采用双线制,在收发两端由内部电路进行发送和接收的切换。在外部发送和接收的数据都通过同一根线传输。

若信号在通信双方之间沿两个方向同时传输,任何一方在同一时刻既能发送又能接收信息,这样的方式称为全双工方式,如图58(c)所示。显然,这种传输方式需要在发送端和接收端之间连接两根数据线。



图58单工、半双工和全双工串行通信方式


(3) 数据传输速率。

串行通信的传输速率表示数据传输的快慢,一般可以用两种指标进行描述,即波特率和字符速率。

波特率(Baud Rate)指的是串行通信时每秒传送的码元数。在计算机通信中,一个码元一般指的是需要传输的一位二进制数据,单位为bit/s,简写为b/s,有时也写为baud(波特)。串行通信常用的标准波特率在RS232C标准中已有规定,典型的有600、1200、2400、4800、9600、19200和115200等。

在异步串行通信中,传输一个字符不仅需要传输字符本身(例如字符的ASCII码),还要在前后附加起始位和停止位,合成来称为一帧数据,代表一个字符或符号。因此串行通信的传输速率还可以用
字符速率进行描述,又称为符号速率(Symbol Rate),单位为字符/秒。

例如: 假设在异步串行通信中每个字符帧规定为10个数据位(1位起始位、7位数据位、1位偶校验位和1位停止位)。如果已知传输的速率为120字符/秒,则波特率为120×10=1200 b/s,传输一位数据所需的时间为波特率的倒数,即1/1200≈0.833 ms。反之,如果已知波特率为9600 b/s,则符号速率为960字符/秒,表示每秒传输960帧,传输一帧所需的传输时间为1/960≈1.04 ms。

2. 串口与串行通信接口标准

实现串行通信的接口称为串行通信接口,简称串口。实现同步和异步通信的接口分别称为通用同步通信接口和通用异步通信接口,又称为通用同步收发器(Universal Synchronous Receiver/Transmitter,USRT)和通用异步收发器(Universal Asynchronous Receiver/Transmitter,UART)。在51单片机中只有一个UART,而在高档的嵌入式微处理器(例如STM32系列微处理器)中,还有USART(通用同步异步收发器),既能实现同步通信,也能实现异步通信。

串口的两个最基本的功能是数据传输和数据格式转换。数据传输主要定义传输过程中的标准、数据帧格式及工作方式,控制具体的数据传输过程等。数据格式转换是将传输的数据进行串行和并行之间的相互转换,在发送端需要将并行数据转换为串行数据,而在接收端需要将串行数据转换为并行数据。

在两台单片机或者两台设备进行串行通信时,除了要求单片机和设备必须有串口以外,还需要用连接导线将收发双方的串口连接起来,并按照事先规定的协议或格式标准进行通信。

51单片机串行通信接口的输入和输出信号均为TTL电平,即二进制0码和1码分别用低电平0V和高电平+5V表示。一


图59TTL电平直接连接


般认为,当传输距离在1.5 m内时,可以将两台51单片机的串口直接相连,如图59所示。其中RxD和TxD分别为数据接收端和数据发送端,两台51单片机的RxD和TxD端交叉连接在一起。一台51单片机发送数据,则另一台51单片机接收数据。

这种直接以TTL电平实现串行数据传输的方法,抗干扰性差,传输距离短,传输速率低。为提高串行通信可靠性,增大串行通信距离和提高传输速率,在实际系统中可以采用格式串行通信接口标准,如RS232C、RS422A、RS485等。

(1) RS232C接口。

RS232C是美国电子工业协会(Electronic Industry Association,EIA)推荐的串行通信总线标准,其全称是“使用二进制进行交换的数据终端设备(Data Terminal Equipment,DTE)和数据通信设备(Data Communication Equipment,DCE)之间的接口标准”。RS232C标准的传输距离在15 m之内,数据传输速率局限在20 kb/s以下,其传输速率主要有: 50、75、110、150、300、600、1200、2400、4800、9600、19200 b/s。

RS232C标准规定采用一种具有25根引脚的25针D型连接器(插针和插座)来连接通信双方的串口是一种标准的,而目前绝大多数计算机采用9针D型连接器,简称DB9连接器,如图510所示。 

表52是RS232C接口DB9连接器的引脚功能分配,其中最基本的两根引脚是TxD和RxD。TxD是发送数据引脚,数据传输时,数据位由该引脚发; RXD是接收数据引脚,发送器发出的数据位由该引脚进入接收器。



图510RS232C的9针D型连接器




表52RS232C接口DB9连接器的引脚功能




针脚信号功能(传输信号)


1DCD载波检测,
Received Line Signal Detector(Data Carrier Detect)

2RXD接收数据,Received Data
3TXD发送数据,Transmit Data
4DTR数据终端准备好,Data Terminal Ready
5SGND信号地,Signal Ground
6DSR数据准备好,Data Set Ready
7RTS请求发送,Request To Send
8CTS清除发送,Clear To Send
9RI振铃提示,Ring Indicator


当传输的距离比较近时,利用RS232C标准可以实现具有该标准接口的各台设备之间的直接连接。如果传输的距离比较远,需要通过调制解调器(MODEM)进行连接和数据传输,如图511所示。 此时就需要用到表52中的其他引脚。限于篇幅,这里就不详细介绍了。



图511使用MODEM时RS232C接口的连接


RS232C标准采用负逻辑电平,即逻辑1和0分贝分别用
-15~-3 V和+3~+15 V表示。由此可见,RS232C的逻辑电平与TTL逻辑电平不兼容,因此必须进行电平转换。常用的电平转换集成芯片有Motorola公司制造的MC1488和MC1489,MAXIM公司生产的MAX系列RS232C收发器MAX232、MAX213E、MAX241E芯片等。图512所示是采用芯片MAX232A实现电平转换时的电路连接。



图512RS232C电平转换芯片的连接


(2) RS422A接口。

RS232C虽应用广泛,但推出较早,传输速率低、通信距离短、接口处信号易产生串扰,于是国际上又推出了RS422A标准。

RS422A与RS232C主要区别是,收发双方信号地不再共地,RS422A采用了平衡驱动和差分接收的方法。每个方向用于数据传输的是两条平衡导线,这相当于两个单端驱动器。输入同一个信号时,其中一个驱动器输出永远是另一个驱动器的反相信号,从而使得两条线上传输的信号高/低电平时钟相反。若传输过程中混入了干扰和噪声(以共模形式出现),由于差分接收器的作用,就能识别有用信号并正确接收传输信息,使干扰和噪声相互抵消。

RS422A能在长距离、高速率下传输数据。最大传输率为10 Mb/s,此速率下,电缆允许长度为12 m,如采用较低速率,最大传输距离可达1219 m。

(3) RS485接口。

RS422A接口需要四芯传输线,长距离通信不经济。在工业现场,常采用双绞线传输的RS485串行通信接口。RS485是RS422A的改进,二者的主要区别是: RS422A为全双工,采用两对平衡差分信号线; RS485为半双工,采用一对平衡差分信号线。

采用RS485很容易实现1对N的多机通信。RS485标准允许最多并联32台发送器和32台接收器。RS485与RS422A一样,最大传输距离约1219 m,最大传输速率为10 Mb/s。通信线路采用平衡双绞线,双绞线长度与传输速率成反比,只有在很短距离下才能获得最大传输速率,一般100 m长双绞线最大传输速率仅为1 Mb/s。

5.2小试牛刀——实战入门

在对51单片机中的定时/计数器和串口有了初步了解后,这里通过几个案例介绍其应用及程序设计方法。







微课视频




动手实践51: 周期脉冲信号的产生

要求由51单片机的P1.0引脚输出一个周期为0.4 ms的脉冲信号,脉冲的周期用51单片机内部的定时/计数器T0实现控制。假设51单片机的时钟频率为6 MHz。

本案例的电路原理图如图513所示(参见文件ex5_1.pdsprj),其中51单片机的P1.0引脚接入示波器的A通道,以便观察输出信号的波形。



图513示波器电路符号及面板


示波器Digital Oscilloscope是Proteus中提供的一个虚拟仪器(Virtual Instrument),有4个输入端(通道),可以同时观察4个输入信号的时间波形。向原理图中调入示波器的方法有如下两种: 

(1) 在Proteus窗口左侧的工具栏中选择Virtual Instruments Mode(虚拟仪器模式),在该工具栏右侧列表框中单击选中OSCILLOSCOPE并将其放置到原理图中合适的位置; 

(2) 在原理图中右击,在弹出的快捷菜单中选择Place/Virtual Instrument/OSCILLOSCOPE命令。

本案例的主程序如下(参见文件p5_1.asm): 



; 定时/计数器方式2的应用——周期脉冲信号的产生

SIGBITP1.0; 定义输出信号引脚

ORG0000H

AJMPMAIN

ORG0100H; 主程序

MAIN:MOVTMOD,#00000010B; 设置T0工作方式2

MOVTH0,#156; 设置计数初值

MOVTL0,#156

SETBTR0; 启动定时

LOOP:JNBTF0,$; 定时到?否,则等待

CLRTF0; 清除TF0

CPLSIG; 输出信号波形取反

SJMPLOOP; 循环

END





运行程序前,注意在原理图中双击51单片机芯片,在弹出的对话框中设置51单片机的时钟频率为6 MHz。启动运行后,将自动打开示波器面板。由示波器面板可以观察到P1.0输出脉冲的周期为0.4 ms,脉冲幅度为5 V。修改程序中的计数初值156,重新编译,之后在Proteus中重新启动运行,可以观察到示波器上脉冲周期的变化。

动手实践52: 周期脉冲频率的测量

本案例的原理图如图514所示(参见文件ex5_2.pdsprj)。图中用信号发生器SIGNAL GENERATOR产生频率范围为1~250 kHz的待测脉冲,并由P3.5(第二功能为T1引脚)送入51单片机内部的定时/计数器T1,作为其计数脉冲,同时送入示波器的A通道,以便观察其波形。











图514









微课视频






图514周期脉冲频率的测量电路原理图



根据前述频率测量的基本原理,本案例用T0工作在方式0重复实现1 ms定时,定时脉冲通过P2.0引脚送入示波器的B通道,以便观察其波形。在每次定时1 ms时间内,用定时/计数器T1统计待测脉冲的个数,计数结果即为待测脉冲的频率(以kHz为单位),以二进制形式用8个LED显示。

假设51单片机的时钟脉冲频率为12 MHz。为了用T0工作在方式0实现1 ms的重复定时,所需的计数初值为1C18H(具体计算方法将在后面介绍)。主程序如下(参见文件p5_2.asm): 



; 定时和计数功能的配合使用——周期脉冲频率的测量

SIGBITP2.0

RESULTEQUP1

ORG0000H

AJMPMAIN

ORG0100H

MAIN:MOVTMOD,#01100000B; 设置T0工作方式0定时方式

; T1工作在方式2计数方式

LP:MOVTH0,#0E0H; 设置T0计数初值已定时1 ms

MOVTL0,#18H

MOVTH1,#0; 初始化T1计数初值为0

MOVTL1,#0

SETBTR0; 启动T0定时

SETBTR1; 启动T1计数

JNBTF0,$; 等待T0定时到

CLRTF0

CPLSIG; 输出定时1 ms脉冲

CLRTR1; 停止T1计数,以便读取结果

MOVA,TL1

CPLA

MOVRESULT,A; 输出显示测量结果

SJMPLP

END





在Proteus原理图中加载并启动上述程序的运行,将自动弹出示波器和信号发生器面板,如图515所示。通过信号发生器面板可以调节待测脉冲的频率,图中设置为4 kHz。在示波器面板中,可以清楚地看到待测脉冲和1 ms定时脉冲。此时,根据8个LED的显示可知测量结果为00000100B=4 kHz。调节待测脉冲的频率,可以看到8个LED亮灭状态的变化。


















图515





图515信号发生器和示波器面板


注意运行过程中调节待测脉冲的频率不能超过255 kHz。例如,当待测脉冲频率为300 kHz时,根据上述测量原理,LED应该显示300的二进制代码,已经超过8个LED能够显示的8位结果。待测脉冲频率更不能超过500 kHz,否则无法得到正确的测量结果,具体原因将在后面解释。

动手实践53: 利用串口实现并口的扩展

在51单片机中,串口一个重要的应用是实现并口和各种外部资源的扩展。如果一台51单片机系统在工作过程中不需要与外接进行串行通信,则可以利用串口扩展并口,也就是通过串口相关的引脚实现并行数据的输入/输出,相当于为51单片机系统增加了并口。

利用串口为51单片机扩展并口,在外部需要用到一些特殊的集成电路芯片,典型的有4094、74164和74165等。其中4094和74164是串入/并出芯片,74165是并入/串出芯片。

本案例以扩展并口为例,介绍利用串口为51单片机扩展并口的基本方法。电路原理图如图516所示(参见文件ex5_3.pdsprj)。











图516





图516利用串口实现并口的扩展


在图516中,8位串入/并出芯片74164的A和B直接短接,用作串行数据输入端,因此与51单片机的RxD(P3.0引脚的第二功能)相连接; CLK端为串行时钟信号输入端,直接与51单片机的TxD(P3.1引脚的第二功能)相连接; Q0~Q7为并行输出端,输出8位数据用于控制LED的亮灭。

引脚MR为清零端,当输入低电平时8个输出端清0。本案例无需将输出端清零,因此MR端恒定地接电源。当MR=1时,如果没有CLK端的脉冲,74164输出数据就一直保持不变。

本案例的主程序代码如下(参见文件p5_3.asm): 



ORG0000H

AJMPMAIN

ORG0100H

MAIN:MOVSCON,#00H; 串口初始化,方式0

MOVA,#0FEH

LP:MOVSBUF,A; 串口发送一个数据

JNBTI,$; 等待发送完毕

ACALLDELAY; 延时

CLRTI; 清除TI标志位

RLA; 数据循环移动一位

SJMPLP; 循环

DELAY:MOVR7,#0FFH; 延时子程序

LP1:MOVR6,#0FFH

DJNZR6,$

DJNZR7,LP1

RET

END





在Proteus中加载程序,启动运行后,可以看到8个LED从下往上进行跑马灯显示。







微课视频





动手实践54: 点点双机单工通信

在系统中,一台51单片机发送数据,并由另一台51单片机接收,两台51单片机的串口(或者通过RS232C、RS485接口实现电平转换后)直接连接起来,相当于在两台51单片机之间存在一条专用线路,这种串行通信称为点点双机单工通信。

在图517所示原理图(参见文件ex5_4.pdsprj)中,51单片机U2从并口P1读入8个开关数据,并通过其串口引脚RxD传送给51单片机U1。51单片机U1从TxD引脚串行接收到8位数据后,立即通过并口P2输出,以控制8个LED的亮灭。注意设置两台51单片机的时钟频率为12 MHz。













图517






图517点点双机单工通信连接原理图


本案例需要在Keil C51中创建两个工程,在第一个工程中创建如下源程序实现数据的串行发送(参见文件p5_4t.asm): 



; 串口点-点双机单工通信(发送)

SWTEQUP2

ORG0000H

AJMPMAIN

ORG0100H

MAIN:MOVSP,#60H

MOVSCON,#01000000B; 设置51单片机U2的串口方式1,禁止接收	

MOVTMOD,#00100000B; 设置定时/计数器T1

MOVTL1,#0E6H; 设置T1计数初值以确定波特率

MOVTH1,#0E6H

SETBTR1; 启动T1定时

MOVSWT,#0FFH

LP0:MOVA,SWT; 读入开关数据

CPLA

MOVSBUF,A; 通过串口发送

LP1:JNBTI,LP1; 等待发送完毕

CLRTI; 清除TI标志位

LJMPLP0; 循环

SJMP$

END





在第二个工程中创建如下源程序实现数据的串行接收(参见文件p5_4r.asm): 



; 串口点-点双机单工通信(接收)

LEDEQUP1

ORG0000H

AJMPMAIN 

ORG0100H

MAIN:MOVSP,#60H

MOVSCON,#01010000B; 51单片机U1工作方式1,允许接收

MOVTMOD,#00100000B; 设置定时/计数器T1工作方式2定时功能 

MOVTL1,#0E6H; 设置T1的计数初值以确定波特率

MOVTH1,#0E6H

SETBTR1; 启动T1定时

LP:JNBRI,$

CLRRI; 清除接收中断请求标志位

MOVA,SBUF; 从串口读接收到的数据

CPLA; 由P1口输出控制LED

MOVLED,A

SJMPLP; 等待串口接收数据发出中断

END





将上述两个工程生成的HEX文件分别加载到U1和U2单片机,之后启动程序运行。在运行过程中,单击8个开关以改变其通断状态,可以观察到8个LED的亮灭状态变化。

此外,在原理图的右下角还添加了一个虚拟终端(VIRTUAL TERMINAL),以便观察两台51单片机之间串行发送的8位数据。为调入该虚拟终端,在原理图中右击,在弹出的快捷菜单中选择Place/Virtual Instrument/VIRTUAL TERMINAL命令即可。

利用虚拟终端可以模拟PC的串口。将虚拟终端的RxD端子接到原理图中51单片机U1的TxD端(也就是51单片机U2的RxD),则U1发送的数据不仅送到U2,同时通过PC的串口送入


图518虚拟终端窗口

虚拟终端,即可在虚拟终端上观察到51单片机串口传送的数据。注意双击虚拟终端,在弹出的对话框中设置Bode Rate(波特率)为1200 b/s。

在运行过程中,将自动弹出虚拟终端窗口(如图518所示),其中不断显示两台51单片机之间传输的8位开关数据。注意,在虚拟终端窗口右击,在弹出的快捷菜单中勾选Hex Display Mode(十六进制显示模式)。

5.3庖丁解牛——原理剖析


下面结合上述案例对51单片机内部集成的定时/计数器和串口进行详细介绍。

5.3.1定时/计数器的内部结构

51单片机内部集成的定时/计数器分别表示为T0、T1,对52子系列还有一个T2。这些定时/计数器在内部电路上相对独立,可以在应用系统中单独使用,也可以配合使用。在51单片机内部,3个定时/计数器具有相同的结构,其使用方法也都类似。下面的介绍都以T0为例,对定时/计数器T1和T2来说,只需要将相应描述中的0换为1和2即可。

定时/计数器T0的内部结构如图519所示,其中最核心的是一个递增计数器,另外有很多控制电路。



图519定时/计数器T0的内部结构

1. 递增计数器

51单片机中的定时/计数器是一个递增计数器。启动计数前,可以通过程序指令将计数器的计数初值写入特殊功能寄存器TH0和TL0。计数过程中,在每个计数脉冲Tc作用下,这两个特殊功能寄存器中保存的计数值会从计数初值开始不断递增变化,称为当前计数值。当计数值的最高位出现进位时,称为计数溢出,此时TF0标志位被置位,可用于向CPU发出中断请求,或者供CPU查询。

在51单片机中,通过程序配置,计数初值和当前计数值都可以是8位、13位或16位二进制数据,从而实现8位、13位或16位计数。

2. 计数脉冲控制电路

在图519所示中,除递增计数器和计数溢出标志位TF0以外,剩下的电路都是为了对计数器所需的计数脉冲进行控制而设置的。这部分电路的输出控制两个开关S1和S2的通断和切换,从而将不同的计数脉冲送入计数器,并实现计数的启停控制。

这些电路的输入信号有C/、TR0、T0、GATE和INT0,其中T0和INT0信号由外部电路产生,并分别通过51单片机的引脚P3.4和P3.2送入,作为定时/计数器的外部计数脉冲和门控信号。此时这两个引脚工作在第二功能,而不是用作普通的并口引脚。

上述5个信号中的另外3个信号C/、TR0和GATE不是由外部电路送来,而是由51单片机内部电路产生的。具体来说,这3个信号分别是特殊功能寄存器TMOD和TCON中的3位。当用指令向这两个特殊功能寄存器写入指定的8位二进制数据时,各位1码和0码就决定了对应的信号分别是高电平还是低电平,再送入计数器控制电路。这3个信号与两个特殊功能寄存器各位之间的对应关系将在后面介绍,这里先介绍这些信号的作用。

(1) C/: 计数和定时功能选择信号。当该信号为低电平时,开关S1打在上面,计数器的计数脉冲由51单片机内部时钟电路产生的时钟脉冲经过12分频而得到的,因此其频率已知且恒定不变,此时定时/计数器实现定时功能。如果将该信号设置为高电平,则计数脉冲由外部电路通过T0引脚送入,此时定时/计数器实现计数功能。

(2) GATE: 门控允许信号。当GATE=0时,不管INT0引脚送入高电平还是低电平,或门输出都为高电平,开关S2的通断与INT0信号无关。当GATE=1时,在INT0引脚送入信号的高电平期间,S2闭合,计数脉冲能够送到计数器,计数器进行正常计数; 在INT0引脚送入信号的低电平期间,开关S2断开,计数脉冲不能够送到计数器,计数器停止计数INT0引入的信号称为门控信号。

(3) TR0: 计数启动信号。在或门输出高电平的前提下,当TR0=1时,与门输出高电平,控制开关S2接通,允许计数脉冲送入计数器开始计数; 否则,如果TR0=0,则不能启动计数。

3. 相关的特殊功能寄存器

51单片机的所有内部资源都是利用程序指令通过对特殊功能寄存器进行访问和控制的。定时/计数器作为一个重要的内部资源,在其内部电路中,计数初值和计数值保存在TH0和TL0中,可以采用与普通的内部RAM单元一样的程序指令对其进行读写访问。此外,与计数脉冲控制相关的3个信号分别对应TMOD和TCON这两个特殊功能寄存器中的一些位,下面着重介绍这两个特殊功能寄存器。

(1) TMOD。

TMOD被称为定时方式(Timer Mode)寄存器。该寄存器在内部RAM中的地址为89H,只能实现字节访问,不能进行位寻址。

TMOD寄存器各位的含义如图520所示。其中高4位和低4位分别用于设置定时/计数器T1和T0的工作方式等。以低4位为例,其中D3位为GATE,D2位为C/T,分别用于设置门控允许信号和计数、定时功能。最低2位M1M0可以有4种组合,分别用于设置定时/计数器T0工作在方式0、1、2和3的这4种工作方式。



图520TMOD寄存器各位的含义


例如,如下指令设置定时/计数器T0工作在方式2的定时方式,禁用门控; 设置定时/计数器T1工作在方式0的计数方式,允许门控。



MOVTMOD,#11000010B





(2) TCON。

在3.3.6节已经介绍过该寄存器,其低4位用于外部中断的设置,高4位用于对定时/计数器的控制,如图521所示。在高4位中,各名称后缀为0的位用于控制定时/计数器T0; 后缀为1的位用于控制定时/计数器T1。



图521TCON寄存器各位的含义


以T0为例,与之相关的是TR0和TF0位。其中,TR0是启动位,用位操作指令设置该位为1时启动计数,将该位清零时停止计数; TF0是计数溢出标志位,当计数溢出时,由硬件将该位设置为1,可供程序检测。例如,如下指令执行后,将启动定时/计数器T0的计数。



SETBTR0 





而如下指令: 



JBTF0,TOUT




将检测T0计数是否溢出。当计数溢出时,TF0=1,则转到标号为TOUT的指令执行。

5.3.2定时/计数器的工作方式

在开始计数前,通过向TMOD寄存器写入8位二进制数据,可以设置定时/计数器的工作方式。其中T0可以有4种工作方式,分别称为方式0、方式1、方式2和方式3; 而T1只有前面3种工作方式。

1. 方式0和1

这两种工作方式的主要区别在于计数位数不同,其中方式0是13位计数,方式1是16位计数。

方式1是16位计数。计数开始前将16位计数初值的高、低8位直接存放到TH0和TL0中。在计数过程中,TH0和TL0中存放的16位计数值将不断递增变化。当计数到0FFFFH时,如果再来一个计数脉冲,则计数值加1时,最高位出现进位,当前计数值回到0000H,同时TF0被置位,发生计数溢出。之后,将从0000H开始重新计数。

方式0是13位计数。13位计数初值的高8位存入TH0,低5位存入TL0的低5位,TL0的高3位始终为0。例如,假设计数初值为4660,先将其用13位二进制代码表示为1001000110100B,再将其高8位10010001B=91H存入TH0,低5位10100B前面添加3位0得到TL0=00010100=14H。

2. 方式2

方式2是8位计数。在计数开始前将8位计数初值同时存入TH0和TL0。在计数过程中,TL0不断做递增计数,而TH0中的计数初值保持不变。当计数到0FFH时,再来一个计数脉冲,则发生计数溢出。之后,内部电路控制将TH0中保存的计数初值重新装入TL0,并从原来的计数初值重新开始计数。

由此可见,方式2与方式0和1的主要区别在于: 方式2可以自动重装初值; 方式0和1在计数溢出后,无法自动重新装入计数初值,只能从全0码开始重新计数。如果需要,则必须在计数溢出后用指令将计数初值重新装入TH0和TL0。

3. 方式3

在方式3下,定时/计数器T0分为两个相互独立的8位计数器TH0和TL0,如图522所示。其中TH0只能实现简单的定时功能,计数脉冲只能是51单片机内部时钟的12分频,并借用定时/计数器T1的TR1和TF1,以控制定时的启停、作为计数溢出标志位。此外,计数溢出时不能自动重装初值。



图522定时/计数器方式3的结构


在方式3下,TL0占用原定时/计数器T0的控制位和引脚,实现与方式0和1类似的功能,只是计数位数不同。这种方式下,由于TH0单独用作另一个8位计数器,因此TL0也不能自动重装初值。

当设置定时/计数器T0工作在方式3时,由于TH0需要借用定时/计数器T1的TR1和TF1,因此T1无法用TR1控制其计数的启停,也无法设置溢出标志位。在这种情况下,T1一般用作串口通信所需的波特率发生器,在启动后就不断重复计数,产生的溢出脉冲经分频后作为串口工作所需的时钟脉冲。

5.3.3定时/计数器的使用步骤与案例解析

根据前面的介绍,定时/计数器各种工作方式的原理是类似的,主要是计数位数不同。因此一般根据所需的计数初值或者在计数过程中计数器可能达到的最大计数值来选择和设置计数器的工作方式。之后,按照标准的步骤即可很方便地实现定时和计数功能。

1. 定时功能

如果是利用定时/计数器实现定时功能,则一般要求定时到后应能出现计数溢出,以便CPU能够通过检测TF0或TF1判断定时是否到。此时,可以根据所需定时时间的长短计算得到计数初值,再根据各种工作方式下计数初值的范围选择工作方式。

当计数初值N0=0时,方式0~2的计数过程从启动计数到计数溢出所需的计数脉冲个数分别为213=8192、216=65536和28=256,称为最大计数值或计数满值,记为Nm。如果计数初值N0≠0,则计数器从N0开始计数,必须在计数值达到Nm时才发生溢出。假设计数脉冲周期为Tc,则计数溢出时的定时时间为T=(Nm-N0)Tc。因此为实现期望的定时时间T,所需的计数初值应为N0=Nm-T/Tc。

例如,假设T0工作在方式1,已知51单片机的时钟频率为6 MHz,则计数器的计数脉冲频率为6/12=0.5 MHz,Tc=2 μs。因此,为实现1 ms定时,所需的计数初值N0=Nm-T/Tc=65536-1 ms/2 μs=65036=0FE0CH。

显然,对于不同的工作方式,为实现相同长度的定时,所需的计数初值是各不相同的。在上例中,如果设置T0工作在方式0,则计数初值应为8192-500=7692。如果设置工作在方式2,则计数初值应为256-500<0,这说明为实现1 ms定时,不能工作在方式2。

在根据所需的定时时间计算计数初值,并根据计数初值确定定时/计数器的工作方式后,实现定时功能的程序只需要做如下设置和操作。

(1) 根据工作方式确定方式控制字,并用MOV指令存入TMOD寄存器。

(2) 用MOV指令将计数初值存入TH0和TL0。对于方式0和方式1,必须根据计数初值的高、低8位分别设置TH0和TL0; 对方式2,必须用两条MOV指令将8位的计数初值同时存入TH0和TL0。

(3) 用SETB TR0指令启动计数。

(4) 用JB、JNB或JBC指令检测TF0标志位,并等待计数溢出(定时到)。

(5) 定时到后,继续做相应的操作。

在动手实践51程序p5_1.asm的主程序中,第一条指令设置TMOD寄存器的方式控制字为02H=00000010B,由其低4位指定定时/计数器T0的工作方式为方式2、实现定时功能、禁用门控信号。由于本案例只用到了T0,因此方式控制字的高4位没用,可任意设置为0码或1码,这里设置为0码。

程序接下来设置计数初值为156(注意没有后缀,所以是十进制数)。由于T0工作在方式2,因此用两条MOV指令将该计数初值同时送到TH0和TL0。之后执行SETB指令将TCON寄存器中的TR0置位,从而启动定时。

由于在原理图中设置51单片机的时钟脉冲为6 MHz,则定时时间为(256-156)Tc=0.2 ms。在定时/计数器的定时计数过程中,CPU循环执行程序中的JNB指令,不断检测计数溢出标志位TF0。当计数溢出时,定时/计数器电路自动将TF0设置为1,CPU执行JNB指令检测到TF0=1后退出循环。

显然,从启动定时到退出循环,定时/计数器T0定时0.2 ms时间到。因此,接下来将TF0溢出标志清除,以便等到下次定时到后重新将其置位。此外,定时到后通过执行CPL指令将P1.0引脚取反,使P1.0引脚上出现高/低电平的翻转。

由于定时/计数器T0工作在方式2,因此在当前定时到后,计数初值将从TH0自动重新装入TL0,又开始下一轮定时。在程序中,利用SJMP返回标号LOOP所在指令,又重复上述过程,等待下一次0.2 ms定时到后,又使P1.0引脚输出高/低电平翻转一次。

通过上述过程,在P1.0引脚输出高/低电平不断切换的周期脉冲。显然,每次高/低电平切换的时间间隔等于利用定时/计数器T0每次循环定时的时间0.2 ms,因此最后输出脉冲的周期为0.4 ms。

2. 计数功能

如果是利用定时/计数器实现计数功能,则在初始化时一般将计数初值设为0。启动计数后,每来一个计数脉冲,计数值递增1。在期望的条件满足时,停止计数,并根据当前计数值求得希望的参数。例如在给定的一段时间内外部送来计数脉冲的个数,并进一步求得脉冲的周期或频率。

显然,如果计数器的最大计数值过小,在计数过程中将出现溢出,导致最后根据当前计数值计算所需参数的过程较复杂。因此为了实现计数功能,一般需要保证计数不溢出。此时,应根据计数脉冲的频率高低对可能达到的最大计数值Nm进行估计,并据此选择定时/计数器合适的工作方式。

 如果Nm=1~28(1~256),可以选择任何一种工作方式; 

 如果Nm=28~213(256~8192),则不能设置为方式2,可以选择方式0或1; 

 如果Nm=213~216(8192~65536),则只能选择方式1。



图523程序p5_2.asm流程图

根据由T0引脚送入的外部脉冲频率或周期,确定为保证计数不溢出可能达到的计数值,并根据计数初值确定定时/计数器的工作方式。之后,在程序中只需要进行如下设置和操作。

(1) 根据工作方式确定方式控制字,并用MOV指令存入TMOD寄存器。

(2) 用MOV指令向TH0和TL0存入计数初值00H。

(3) 用SETB TR0指令启动计数。

(4) 当规定的条件满足(例如定时1 ms)时,停止计数并读取计数值。

在动手实践52中,同时利用了51单片机内部两个定时/计数器实现待测脉冲频率的测量,其中T0实现定时1 ms的功能。本案例中同时将T0定时产生的1 ms定时脉冲由P2.0引脚输出送到示波器,以便观察。

在每次定时1 ms的过程中,用T1对通过P3.5引脚送入的待测脉冲进行计数。实现该案例的程序p5_2.asm的流程图如图523所示。 

在程序中,首先设置方式控制字为01100000B,其中,低4位确定T0工作在方式0,实现定时功能,禁用门控信号; 高4位确定T1工作在方式2,实现计数功能,禁用门控信号。

做了上述初始化设置后,在之后的死循环中,利用T0不断定时1 ms,并在每次定时时间范围内对待测脉冲进行计数,从而得到待测脉冲的频率送入LED显示。下面再对案例程序做一些相关说明。

(1) 计数初值的计算和设置。

在本案例中,定时计数器T1用于实现对待测脉冲的计数,因此设置其计数初值为0,同时存入TH1和TL1。程序中每定时1 ms测量一次频率后,再跳转到LP处,将T1的计数初值清零,以便重新开始下一次频率测量。

定时/计数器T0用于实现1 ms定时,其计数初值的计算方法如下: 已知时钟频率为12 MHz,则计数器计数脉冲频率为12/12=1 MHz,Tc=1 μs。由于T0工作在方式0,因此为实现1 ms定时,所需的计数初值N0=Nm-T/Tc=8192-1 ms/1 μs=7192。将该计数初值用13位二进制表示为1110000011000B,其高8位为1110000=0E0H,在低5位11000B之前添加3个0,得到00011000B=18H。程序中将0E0H和18H作为计数初值,分别存入TH0和TL0。

特别需要注意的是,由于T0工作在方式0,因此每次定时1 ms到后,不会自动重装初值。在主程序中,每次循环都必须跳转到标号LP处,用指令重装初值。

(2) T1计数的启动和停止。

程序中启动T0和T1开始计数之后,利用JNB指令不断检测TF0,等待T0定时1 ms到。在此过程中,T1同时不断对由P3.5引脚送入的待测脉冲进行计数。

当检测到TF0=1时,T0定时到,则清除TF0,以便等到T0下一次定时到后重新将其置位。同时清除TR1,以便停止T1计数,并从TL1读取当前计数值。

(3) 测量结果的显示。

每次定时1 ms到,停止TR1计数后,从TL1读取计数值,取反后由P1口输出控制LED的亮灭,以便观察测量结果。在上述过程中,之所以要将读取的计数值取反,是考虑到人眼观察的正常习惯。在LED上一般点亮表示1码,熄灭表示0码。如果将读取的计数值直接输出控制LED,因为LED采用共阳极接法,则显示结果将刚好相反。

(4) 频率测量范围分析。

本案例中,在每次定时1 ms时间范围内由T1统计待测脉冲的个数。由于计数值只能为整数,因此在1 ms范围内至少需要送入一个待测脉冲。这就意味着待测脉冲的频率至少应为1 kHz。

由于T1工作在方式2,实现的是8位二进制数的计数。在每次循环测量时,将计数初值设为0,因此当计数脉冲在1 ms内的个数超过255时,将出现计数溢出,计数过程又从0重新开始。在定时到时,根据当前计数值得到的测量结果将出现错误。因此在1 ms时间范围内待测脉冲的个数不能超过255个,也就意味着频率不能超过255 kHz。

在调试过程中,读者试着调节信号发生器产生的脉冲频率,使其超过255 kHz,观察LED显示的测量结果是否正确。

显然,如果需要扩大频率测量,可以增加计数位数。例如,如果设置T1为方式1以实现16位二进制数的计数,则待测脉冲的最高频率可以增大到65535 kHz。

但是需要注意,在定时/计数器工作过程中,51单片机需要两个机器周期的时间才能检测到T0或T1引脚上输入的一个待测脉冲,因此待测脉冲的频率不能超过51单片机时钟脉冲频率的1/24。假设时钟频率为12 MHz,则待测脉冲的最高频率不能超过500 kHz。

5.3.4定时/计数器门控信号的作用

在定时/计数器中,当设置GATE=0时,计数的启停只需要用TR0或TR1进行控制。当设置GATE=1时,计数的启停不仅要受到TR0或TR1信号的控制,还要受到由INT0或INT1引脚送入门控信号的控制。利用这一特性,可以实现一些特殊的应用功能,例如脉冲宽度的测量。

下面通过一个具体案例体会门控信号的作用。







微课视频




动手实践55: 脉冲宽度的测量

本案例的电路原理图如图524所示(参见文件ex5_5.pdsprj)。与图514不同的是,这里将待测脉冲从INT1引脚(P3.3的第二功能)引入,作为定时/计数器T1的门控信号。在该脉冲信号为高电平期间,T1工作在定时方式对内部标准时钟进行计数。当高电平期间结束后,根据T1计数值即可求得脉冲的宽度。



















图524





图524脉冲宽度的测量电路原理图


本案例的汇编语言程序如下(参见文件p5_5.asm): 



ORG0000H

AJMPMAIN

ORG0100H; 主程序

MAIN:MOVTMOD,#10010000B; 设置T1工作方式1定时门控方式

SETBTR1; 允许T1计数







LP:MOVTH1,#0; T1计数初值初始化为0

MOVTL1,#0

JNBP3.3,$; 等待脉冲低电平结束,高电平开始

JBP3.3,$; 等待脉冲高电平结束

MOVA,TL1; 读取计数值 

CPLA

MOVP1,A; 显示测量结果

MOVA,TH1

CPLA

MOVP2,A

SJMPLP

END





根据测量的基本原理,在本案例中用待测脉冲作为门控信号,控制定时/计数器T1对51单片机内部的标准脉冲进行计数。程序中设置定时/计数器T1工作在方式1的定时方式,并设置GATE1=1。需要注意的是,由于是对标准脉冲进行计数,因此T1实现的是定时功能而不是计数功能,C/位必须设为0。

设置工作方式以后,程序中用SETB指令将TR1置位,该操作的作用是使TR1=1,但计数过程不一定已经启动。在设置的方式控制字中GATE=1,因此必须等到门控信号(即待测脉冲)高电平到来时才开始计数。

程序之后用了一个大循环,不断循环测量并显示待测脉冲的周期。下面对每次循环实现的主要操作做一些解释说明。

(1) 循环一开始(即每次计数测量开始),将计数器的初值设为0,存入TH1和TL1。

(2) 设置计数初值后,程序中用JNB指令检测门控信号的低电平是否结束,等待高电平的到来。

(3) 一旦门控信号高电平到来,计数器开始对内部标准计数脉冲进行计数。而CPU通过执行程序中的JB指令等待门控信号的高电平结束。当门控信号高电平结束时,计数器自动停止计数,此时CPU读取计数值即可得到测量结果。

上述测量过程可以用图525表示。在Proteus原理图中设置51单片机的时钟频率为12 MHz,加载上述程序并启动运行,设置信号发生器输出脉冲的频率为1 kHz,16个LED上显示16位二进制数为01F4H =500,表示脉冲的高电平宽度为500 μs。



图525脉冲宽度的测量过程示意图

5.3.551单片机串口的基本结构

51单片机具有一个全双工的串行异步通信接口UART,可以同时发送、接收数据。该串口有四种工作方式,发送和接收数据可通过查询或中断方式处理,使用十分灵活。

51单片机集成的UART也主要实现数据传送和数据格式转换功能,其内部结构如图526所示,其中主要包括数据缓冲器、发送控制器、接收控制器、输出控制门和输入移位寄存器等。从应用的角度看,可以归纳为3个特殊功能寄存器,即串口数据缓冲器
(Serial Buffer,SBUF)、串口控制寄存器(Serial Controller,SCON)和电源控制寄存器(Power Controller,PCON)。此外,在串口工作过程中还要用到定时/计数器T1。



图526串口的基本结构

1. SBUF

串口内部有一个8位的数据缓冲器SBUF,用于存放待发送和接收到的数据。该特殊功能寄存器的地址为99H,可以通过名称进行字节操作,不能进行位寻址。

例如,如下指令: 



MOVSBUF,A




将累加器A中的数据送入SBUF,然后由串口内部电路控制发送出去。而如下指令: 



MOVA,SBUF




将SBUF中存放的数据读取出来存入累加器A。

2. SCON

51单片机内部通过串口控制寄存器SCON进行访问,可以对串口内部的发送和接收控制器、输入移位寄存器以及门电路进行控制,以便在波特率发生器(定时/计数器T1)送来的时钟信号控制下,通过输入移位寄存器将外部的串行数据转换为并行数据存入SBUF,或者由门电路将SBUF中的并行数据转换为串行数据输出。同时,控制或门电路发出串口中断请求RI(Receive Interruption,接收中断)和TI(Transmission Interruption,发送中断)信号。

特殊功能寄存器SCON的地址为98H,可以进行字节访问或位操作,各位的格式如图527所示。这里首先对最常用的SM0、SM1、RI和TI位的含义做些解释和说明,其余各位将在后面再做介绍。



图527SCON寄存器各位的含义


(1) SM0和SM1: 这两位二进制数的组合00~11分别指定串口的工作方式为方式0~3。

(2) REN: 控制是否允许串口接收数据。通过指令将该位置位,则允许串口接收数据; 否则禁止串口接收数据,只能进行数据发送。

(3) RI: 接收中断标志位。当串口接收到一个数据时,自动将该位置位。因此通过检测RI位的状态,CPU可以判断一个字符帧是否接收完毕,能否从接收SBUF读取接收到的数据。当RI=1时,串口不会接收数据。因此,在接收完一个数据并被CPU读取后,必须将RI清零,以便等待接收下一个数据。

(4) TI: 发送中断标志位。当一个数据发送完毕后,该位自动置位,因此通过检测TI状态,CPU可以确定一个字符帧是否发送完毕,是否可以向串口写入下一个需要发送的数据。当TI=1时,串口不会发送数据,因此一个数据发送完毕后必须将TI清零,以便准备发送下一个数据。

3. PCON与波特率发生器

在51单片机中,串口进行数据传送所需的波特率由PCON和波特率发生器共同决定,涉及特殊功能寄存器有TMOD、TCON、PCON、TL1、TH1等。具体来说,在不同的工作方式下,串口的波特率确定方法不同。

(1) 方式0的波特率固定不变,始终等于51单片机时钟频率的1/12。

(2) 方式2的波特率只有两种,等于时钟频率的1/32或1/64,具体取决对PCON寄存器中最高位SMOD位的设置。当设置该位为0时,方式2的波特率为时钟频率的1/64; 当设置该位为1时,方式2的波特率为时钟频率的1/32。

(3) 方式1和方式3的波特率由SMOD位以及定时/计数器T1的计数初值和定时时间共同决定。此时,T1必须工作在方式2,定时时间为(256-计数初值)×12/时钟频率,相应的波特率为


波特率=2SMOD/T1的定时时间/32

根据上式,如果给定串口的波特率,T1的计数初值应设为


计数初值=256-时钟频率×2SMOD /(12×波特率×32)


例如,假设51单片机的时钟频率为12 MHz,SMOD=0,要求串口传输的波特率为1200 b/s,则


计数初值=256-12×106×20/(12×1200×32)≈230=0E6H


5.3.651单片机串口的工作方式

通过设置SCON中的最高2位,可以确定51单片机的UART工作在4种不同的方式,其中方式0一般用于外接移位寄存器芯片扩展I/O接口,方式1通常用于双机通信,方式2和方式3通常用于多机通信。这里首先介绍简单的方式0和方式1。

1. 方式0

方式0称为同步移位寄存器方式。在这种工作方式下,数据传输的波特率固定为51单片机时钟频率的1/12。在传输数据的过程中,RXD(P3.0引脚的第二功能)用作数据线,传输输入或输出的数据; TXD(P3.1引脚的第二功能)用作时钟线,输出同步移位时钟。每次传输,发送和接收8位数据,数据由低位到高位逐位传输。

对发送过程,当TI=0时,将累加器A中实现存入的需要发送的数据由串口内部电路控制逐位移出,并由TxD引脚送出51单片机。发送完毕时,TI自动置位。方式0数据的发送时序如图528(a)所示。

对接收过程,首先必须设置SCON中的D4位REN=1,并且在RI=0时,通过串口内部电路将从RxD引脚送入的数据逐位存入SBUF。当接收完8位数据后,串口将RI置位。CPU在此过程中不断检测RI,当检测到RI=1时,从SBUF寄存器中读取接收到的数据存入累加器A。数据的接收时序如图528(b)所示。




图528方式0数据的收发时序

在动手实践53中,将74164芯片的A、B端和CLK端分别连接到51单片机的RxD和TxD引脚,由TxD送来的时钟脉冲正好作为74164的移位时钟,在其作用下,将RxD送来的各位数据依次存入74164。

在程序p5_3.asm中,当CPU执行完串口的初始化后,通过执行指令



MOVSBUF,A




将数据存入SBUF,并启动数据的发送过程。8位数据从RxD逐位串行送出,TxD端同步输出时钟脉冲。在该时钟脉冲作用下,74161将从RxD线上接收到的数据逐位移入,并立即输出控制各LED的亮灭。

之后,CPU执行JNB指令不断检测串口的TI位。当检测到TI=1时,表示8位数据已经发送完毕。经过适当延时以等待LED可靠显示当前8位数据后,清除TI标志位。再将数据循环左移一位,并返回循环的开始,将左移一位后的数据通过串口重新发送出去。

当TxD端送来8个时钟脉冲后,8位数据完整地存入74164,此时TxD不再送来时钟脉冲(保持恒定的高电平),74164输出8位恒定的二进制数据,控制LED稳定地点亮或熄灭。如果将RxD和TxD信号接入示波器,运行过程中由示波器窗口观察到这两个信号的工作波形如图529所示。



图529串口RxD和TxD信号的波形

2. 方式1

方式1称为8位异步通信方式,一个数据帧包括1位起始位、8位数据位和1位停止位。传送数据的过程中,发送的数据通过TxD引脚送出51单片机,接收的数据逐位从RxD引脚送入。

显然,方式1与方式0的一个重要区别是,RxD和TxD都用作数据线,没有专门的时钟线,所以属于异步通信。此外,传输的数据帧格式不同,方式1每次数据传输,实际上一共传输了10位二进制数,所以有些地方又称为10位异步通信方式,方式1的数据收发时序如图530所示。



图530方式1数据的收发时序


需要强调的是,对串口的方式1在程序中进行初始化时,必须同时对定时/计数器T1进行初始化,以便确定传输的波特率和传输速率。

在方式1下,51单片机串口可以实现单工或全双工通信。从程序上看,如果某个系统中两台51单片机之间数据是单向传输(例如一台51单片机是主机,另一台51单片机为从机,数据只由主机发送从机),则可以认为是单工方式。

基于上述思路,在动手实践54中,假设51单片机U1只能发送,U2只是接收,因此将51单片机U1的TxD与U2的RxD引脚相连接,并且两台51单片机分别加载执行不同的程序。

在发送程序p5_4t.asm中,首先对串口和定时/计数器T1进行初始化。假设51单片机时钟频率为12 MHz,T1工作在方式2,则程序中设置计数初值为0E6H,对应的波特率为1200 b/s。注意51单片机复位后PCON中的最高位SMOD=0。之后启动T1定时,产生周期脉冲作为串口数据传送所需的时钟脉冲。在后面的循环程序中,每次循环从P2口读取开关数据,存入SBUF后立即由串口发送出去。之后,CPU通过执行JNB指令检测TI并等待数据发送完毕,再重复上述过程。

在接收程序p5_4r.asm中,首先设置串口和定时/计数器T1的工作方式并启动T1定时,为串口提供波特率时钟。注意在方式控制字中,必须设置REN=1,以便允许51单片机U2的串口接收数据。之后,不断检测RI标志位。当检测到RI=1时,表示串口接收到一个有效数据,则将RI复位,同时51单片机中的CPU从SBUF中读取接收到的数据,并由P1口输出控制LED。

5.3.751单片机的内部中断

定时/计数器在计数过程中,一旦计数溢出,TCON寄存器中的TF0位将被置位。如果允许,则其可以立即向CPU发出中断请求,称为定时/计数器中断。51子系列内部有两个定时/计数器T0和T1,52子系列还有一个定时/计数器T2。每个定时/计数器都可以发出中断请求。

同样地,对串口来说,发送端每执行一次数据发送,发送完毕时将自动使SCON中的TI位置位; 接收端每接收到一个数据帧,并将其中的8位数据存入SBUF后,将自动使RI位置位。在上述两种情况下,如果允许,则串口都将向CPU发出中断请求,以便通知CPU开始发送下一个数据,或者从串口读取接收到的数据。串口发出的中断称为串口中断。

与通过INT0和INT1引脚送入的外部中断不同,定时/计数器中断和串口中断是由51单片机内部的定时/计数器和串口产生的,称为内部中断。

至此,已经介绍了51单片机中的所有中断源,其中包括2个外部中断、2个或3个定时/计数器中断、1个串口中断。在51单片机中,对这些中断源的管理和控制由专门的硬件和软件配合实现,这些硬件和软件构成51单片机的中断系统。图531所示为51子系列的中断系统。图中,T0和T1为定时/计数器中断,TX和RX为串口的发送中断和接收中断,2个串口中断TX和RX利用或门组合为一个串口中断。

在第3章已经对2个外部中断做了介绍,这里再对定时/计数器中断和串口中断以及所有中断的一些共同问题做进一步概括介绍。



图53151单片机的中断系统

1. 中断请求与中断响应


在图323所示IE寄存器中,除了EX0和EX1这两位用于对2个外部中断进行开放和关闭以外,另外的ET0和ET1位用于开放和屏蔽2个定时/计数器中断(对52子系列的单片机,还有一个定时/计数器T2中断,对应IE寄存器中的ET2位),ES位用于开放和屏蔽串口中断。

与外部中断一样,在程序中,如果希望采用中断方式处理定时/计数器的计数溢出和串口数据的收发,必须在中断请求到来前用指令SETB使IE中的相应位置位,从而开放定时/计数器和串口中断。

一旦开中断,当相应的中断请求到来时,51单片机即可响应中断,转到相应的中断服务程序。对于定时/计数器T0、T1和T2,其中断服务程序的入口地址分别在ROM的000BH、001BH和002BH单元; 对于串口中断,其中断服务程序的入口地址在ROM的0023H单元(参见表31)。

需要注意的是,51单片机响应边沿触发的外部中断和定时/计数器中断后,相应的中断请求标志位IE0、IE1或TF0、TF1将会自动复位。但是,对于电平触发的外部中断和串口中断标志位RI和TI,响应后不能自动复位,必须在中断服务程序中用专门的CLR指令将其清零。

2. 中断优先级

不管是外部中断还是内部中断,中断请求到来的时刻是随机的。这就意味着,CPU正在处理某个中断请求时,可能又有一个新的中断请求到来; 还可能在某个时刻,同时有多个中断请求到来。但是,CPU在任何一个时刻只能响应并处理一个中断请求。这就涉及CPU对各中断请求的响应顺序问题,这就是中断优先级。

在51单片机中,可以将各中断源的中断优先级规则归纳为下面3条: 

(1) CPU同时接收到几个中断请求时,首先响应优先级最高的中断请求; 

(2) 正在进行的中断过程不能被新的同级或低优先级的中断请求所中断,一直到该中断服务程序结束,返回了主程序且执行了主程序中的一条指令后,CPU才能响应新的中断请求; 

(3) 新来的高优先级中断请求能够打断正在进行的低优先级中断服务,从而实现两级中断嵌套。

所谓中断嵌套,就是51单片机正在执行低优先级的中断服务程序时,可被高优先级中断请求所中断,待高优先级中断处理完毕后,再返回低优先级中断服务程序。中断嵌套的过程如图532所示。




图532中断嵌套


51单片机的中断系统中有两个中断优先级组,每个中断请求源所属的优先级组可由软件设置为高优先级或低优先级组,具体是通过图533所示中的中断优先级(Interrupt Priority)IP寄存器实现的。



图533IP寄存器各位的含义


IP寄存器的字节地址为0B8H,可以位寻址。IP中各位的含义如图533所示。其中,PX0和PX1分别为外部中断INT0和INT1的优先级控制位; PT0和PT1分别为定时/计数器T0和T1的中断优先级控制位; PS为串口中断的优先级控制位; PT2为定时/计数器T2的中断优先级控制位,只用于52子系列。当某位为1时,设置相应的中断源为高优先级; 否则为低优先级。

除了利用上述IP进行优先级设置外,位于同一级的各中断源还有一个默认的优先级顺序,该顺序正好与各中断源中断服务程序入口地址在ROM中的存放顺序一致,从高级到低级依次为外部中断0、定时/计数器T0中断、外部中断1、定时/计数器T1中断、串口中断和定时/计数器T2中断。

51单片机复位时,IP的初始值为00H,因此所有的中断源都属于低优先级组。在程序中,可以根据实际系统的需要利用指令随意设置各中断源的优先级。

例如,如下指令: 



MOVIP,#00010100B




将PS和PX1设为1,其余位设为0,则外部中断1、串口中断属于高优先级组,外部中断0、定时/计数器T0中断、定时/计数器T1中断和定时/计数器T2中断属于低优先级组,再根据默认的优先级顺序,各中断源的优先级顺序从高到低依次为外部中断1、串行口中断、外部中断0、定时/计数器T0中断、定时/计数器T1中断和定时/计数器T2中断。

下面通过两个案例介绍定时/计数器中断和串口中断的用法。







微课视频



动手实践56: 定时/计数器中断的应用

将动手实践51改为用中断方式实现,可以编写如下程序(参见文件p5_6.asm): 



; 定时/计数器中断的应用

ORG0000H

AJMPMAIN

ORG000BH

AJMPT0D

;======================================================

; 主程序







;======================================================

ORG0100H

MAIN:MOVTMOD,#00000010B; 设置T0工作方式

MOVTH0,#156; 设置计数初值

MOVTL0,#156

SETBET0; 开定时/计数器T0中断

SETBEA

SETBTR0; 启动定时

SJMP$; 等待定时到

;======================================================

;定时/计数器T0中断服务程序 

;======================================================

T0D:CPLP1.0; P1.0口取反

RETI; 中断返回

END





与程序p5_1.asm采用查询方式相比,在上述采用中断方式的程序中,主要的改动有如下几点: 

(1) 在主程序中启动定时之前需要将ET0和EA置位,开中断。

(2) 在ROM的000BH单元中存放一条AJMP T0D指令,当定时到时,51单片机执行该条指令,转到T0的中断服务程序T0D。

(3) 在中断服务程序中,原来检测和清除TF0的操作都不再需要。当定时到时,定时计数器内部电路将TF0置位。由于主程序中已经开了T0中断,因此将立即向51单片机发出中断请求。这就意味着,一旦程序执行进入中断服务程序,TF0肯定已经被置位,所以不再需要检测。另外,51单片机响应此中断后,内部电路会自动将TF0重新复位,因此也不需要再安排专门的CLR指令将其清零。







微课视频




动手实践57: 串口中断的应用——双工通信

51单片机的串口本身可以实现双工通信。在工作过程中,两台51单片机都可以通过执行程序同时实现数据的发送和接收。为了体会点点双工通信的控制程序及中断方式下的数据传输过程,重新绘制原理图如图534所示(参见文件ex5_7.pdsprj)。



图534两台51单片机之间的点点双工通信连接原理图


在图534中,为了实现双工通信,将两台51单片机的RxD和TxD引脚相互交叉连接。两台51单片机的P1口和P2口都分别连接了8个LED和8个开关。要求实现的功能是: 每台51单片机将开关的状态送到对方单片机连接的LED显示。例如,用与U1单片机连接的DSW1的状态控制与U2单片机连接的LED U3的显示。注意设置两台51单片机的时钟频率都为12 MHz。

由于两台51单片机实现的功能相同,并且都是通过相同的并口与开关和LED相连接,因此两台51单片机的控制程序完全一样,完整的代码如下(参见文件p5_7.asm): 








图534





; 点-点双机双工通信(中断方式)

LEDDATAP1

SWTDATAP2

ORG0000H

AJMPMAIN

ORG0023H

AJMPINS; 串口中断服务程序入口

;===============================================================

; 主程序

;===============================================================

ORG0100H

MAIN:MOVSP,#60H; 主程序 

MOVSCON,#01010000B; 单片机工作方式1,允许接收

MOVTMOD,#00100000B; 设置定时/计数器T1工作方式2定时功能

MOVTL1,#0E6H; 设置T1的计数初值以确定波特率

MOVTH1,#0E6H

SETBTR1; 启动T1定时

SETBEA

SETBES; 开串口中断

MOVSWT,#0FFH

MOVA,SWT

MOVSBUF,A; 发送第一个数据

SJMP$; 循环等待串口中断

;===============================================================

; 串口中断服务程序

;===============================================================

INS:CLREA; 关串口中断

JBRI,REC; 是接收串口中断,则跳转

CLRTI; 是发送串口中断,则清除TI

MOVA,SWT

MOVSBUF,A; 发送数据

SJMPEXT









REC:CLRRI; 清除接收串口中断请求标志位

MOVA,SBUF; 从串口读接收到的数据

CPLA; 由P1口输出控制LED

MOVLED,A

EXT:SETBEA; 开串口中断

RETI; 串口中断返回

END





在上述程序中,两台51单片机执行完全相同的程序流程,不断读取并发送所连接的开关数据,并等待串口中断。一旦有中断请求到来,则在中断服务程序中首先判断是发送还是接收中断。如果是发送中断,则先清除TI,然后读取开关数据送到串口的SBUF并通过串口发送出去; 如果是接收中断,则先清除RI,然后从串口SBUF中读取接收到的数据并通过P1口输出控制LED。

在原理图中单击两个开关,可以看到另一台51单片机上连接的LED的亮灭状态变化。这就意味着,两台51单片机在任何时刻都既可以发送数据,也可以接收数据,从而实现全双工通信。

为了观察数据传送过程,可以在原理图中添加一个示波器,并将单片机U1的RxD和TxD引脚分别接到示波器的A和B通道。单击两个开关设置需要传输的数据,在运行过程中或暂停运行状态观察示波器的波形如图535所示。



图535串口通信中RxD和TxD信号的波形


图535中的两路脉冲分别是单片机U1和U2发送的开关数据,读取顺序是从右往左对应数据的高位到低位。此外,在波形上容易读取传输每位数据的时间近似为0.8 ms,其倒数近似为1200 b/s,这就是程序中设置的波特率。

注意根据各开关的状态读出波形上传输一帧的最高位和最低位。在波形上可以清楚地看到,在每帧数据的开始(即8位开关数据最低位的左边)有一位低电平,这就是起始位。每帧数据传输的最后一位(即8位开关数据的最高位)右边,有一位高电平,这就是停止位。由于程序不断循环收发,所以每次传输一帧共10位数据,就这样不断地重复进行数据的发送和接收。

5.4牛气冲天——实战进阶

在熟悉了51单片机定时/计数器和串口的基本概念及其典型应用的基础上,本节继续介绍应用过程中的一些特殊问题和高级技术。

5.4.1定时/计数器的级联

不管设置定时/计数器工作在哪一种工作方式,由于计数位数有限,计数脉冲的周期或频率固定,因此都只能实现有限长度的定时。表53给出了在51单片机两种典型的时钟脉冲频率下,3种工作方式能够获得的最长定时时间。


表53定时/计数器的最长定时时间




时 钟 频 率方式0方式1方式2


6 MHz16.384 ms131.072 ms0.512 ms
12 MHz8.912 ms65.536 ms0.256 ms


在实际系统中,为了获得更长的定时,可以有两种基本的方法,即定时/计数器和程序控制配合、多个定时/计数器级联使用。下面通过具体案例体会后一种方式实现的基本原理。

动手实践58: 长定时的实现

在计数位数有限的情况下,定时时间太短的一个主要原因在于定时/计数器进行定时所需的标准计数脉冲频率太高。为此可以考虑将一个定时/计数器用作分频器,将标准计数脉冲进行分频,以增大其周期。然后将分频后得到频率较低的信号再作为另一个定时/计数器的计数脉冲,即可获得更长的定时。

在本案例中,利用定时/计数器T0和T1级联实现0.5 s的定时。其中T0工作在定时方式,用于在P1.1引脚产生周期为20 ms的方波脉冲; P1.1引脚输出的方波脉冲再作为T1计数器的计数脉冲,控制P1.0引脚输出1 Hz的周期方波脉冲,电路连接如图536所示(参见文件ex5_8.pdsprj)。为便于观察,将P1.0引脚输出周期为20 ms的脉冲和P1.1引脚输出周期为1 s的脉冲同时送入示波器的A和B通道。



图536定时/计数器级联的电路连接

1. 定时/计数器级联——查询方式

这里设置定时/计数器T0工作在方式1定时方式,每定时10 ms将P1.0引脚的输出信号取反,从而得到周期为20 ms的计数脉冲。设置定时/计数器T1工作在方式2,则可设置其计数初值为256-0.5 s/20 ms=231。每定时0.5 s,计数溢出,将P1.1引脚取反,即可输出周期为1 s的方波脉冲。程序代码如下(参见文件p5_8_1.asm): 



; 长定时的实现——定时/计数器的级联(查询方式)

SIG1BITP1.0

SIG2BITP1.1

ORG0000H

AJMPMAIN

ORG0100H; 主程序

MAIN:MOVTMOD,#01100001B; 设置T0工作方式1定时方式,T1方式2计数方式

MOVTH0,#0D8H; 设置T0计数初值

MOVTL0,#0F0H

MOVTH1,#231; 设置T1计数初值

MOVTL1,#231

SETBTR0; 启动T0定时10 ms

SETBTR1; 启动T1计数  

LP:JNBTF1,NEXT;  T1计数溢出(0.5 s定时到)?

CLRTF1

CPLSIG2;  P1.1引脚取反

NEXT:JNBTF0,$;  等待T0定时10 ms到

CLRTF0

CPLSIG1;  P1.0(T1计数脉冲)取反

MOVTH0,#0D8H; 重装T0计数初值

MOVTL0,#0F0H

SJMPLP; 循环

END





注意到在上述程序中,由于T1工作在方式2,所以计数溢出后不用重装计数初值; 但T0工作在方式1,所以每次计数溢出后都需要重装计数初值。

2. 定时/计数器级联——中断方式

本案例考虑将1 s长定时改为用中断方式实现。具体做法是: 将定时/计数器T0作为一个中断源,通过中断处理将P1.0引脚输出脉冲取反。主程序中定时/计数器T1实现0.5 s的定时仍然采用查询方式。

本案例完整的程序如下(参见文件p5_8_2.asm): 



; 长定时的实现——定时/计数器的级联(中断方式)

SIG1BITP1.0

SIG2BITP1.1

ORG0000H

AJMPMAIN









ORG000BH; T0中断服务程序入口

AJMPT0DEL

;=====================================================================

; 主程序

;=====================================================================

ORG0100H

MAIN:MOVTMOD,#01100001B; 设置T0方式1定时方式,T1方式2计数方式

MOVTH0,#0D8H; 设置T0计数初值

MOVTL0,#0F0H

MOVTH1,#231; 设置T1计数初值

MOVTL1,#231

SETBET0; 开T0中断

SETBEA

SETBTR0; 启动T0定时10 ms

SETBTR1; 启动T1计数  

LP:JNBTF1,$; 等待T1计数溢出(0.5 s定时到) 

CLRTF1

CPLSIG2; P1.1引脚取反

SJMPLP

;====================================================================

; T0中断服务程序

;====================================================================

T0DEL:CPLSIG1; P1.0(T1计数脉冲)取反

MOVTH0,#0D8H; 重装T0计数初值

MOVTL0,#0F0H	  	

RETI

END





在上述程序的主程序中,仍然用同样的方法设置两个定时/计数器的工作方式和计数初值,并启动两个定时/计数器的计数。之后,主程序通过查询TF1的状态,等待定时/计数器T1计数溢出。一旦计数溢出,则将P1.1引脚输出取反,再返回不断循环。

在本案例中,只用了定时/计数器T0中断,因此在程序一开始,将AJMP T0DEL指令存放到000BH单元。一旦T0定时到,则CPU响应中断后执行该指令,从而跳转到标号为T0DEL的指令。从这条指令开始就是定时/计数器T0的中断服务程序。在中断服务程序中,将P1.0引脚输出取反,同时重装定时/计数器T0的计数初值,再执行RETI指令返回。

在CPU执行主程序循环的过程中,定时/计数器T0在不断计数。一旦计数溢出,立即暂停主程序中循环的执行,跳转到定时/计数器T0的中断服务程序。因此,执行RETI指令后,将返回到主程序的循环中,继续查询TF1的状态并等待定时/计数器T1计数溢出。

需要注意的是,如果是采用中断方式检测计数是否溢出,CPU在响应中断后将由内部硬件电路自动将TF0清零,以便下一次计数溢出时重新将其置位。因此,在T0的中断服务程序中,不需要另外安排清除TF0的操作。

上述两个程序运行后,在示波器上观察P1.0和P1.1引脚输出的两路脉冲如图537所示。



图537定时/计数器产生的50 Hz和1 Hz周期方波脉冲

5.4.2串口方式2和方式3及其应用

在SCON中,当设置SM1和SM0为10和11时,分别指定串口的工作方式为方式2和方式3。在这两种方式下,串口仍然用TXD和RxD引脚发送和接收数据。方式2和方式3与方式1的区别在于发送数据帧的格式不同; 而方式2和3之间的主要区别在于传输的波特率不同。方式2的波特率固定为振荡器频率的1/32或1/64; 而方式3的波特率由定时/计数器T1的计数初值决定。

方式2和方式3数据帧的格式如图538所示。由此可见,这两种方式除了发送8位数据位以外,另外还需要发送一位TB8,合起来共9位构成数据帧,因此称为9位异步通信方式。此外,与方式1一样需要前后分别附加一位起始位和一位停止位,合起来共需传送11位数据。因此有些地方又称为11位异步通信方式。



图538串口方式2和方式3数据帧的格式


对发送方,数据帧的最后一位为TB8。在发送前,首先用位操作指令设置TB8为0或1,然后将待发送的8位数据存入SBUF即可启动串行数据的发送。发送数据结束后将TI置位。

对接收方,接收到的8位数据存入SBUF,等待CPU读取,而第9位数据自动存入SCON寄存器的RB8位。这9位数据接收结束后,串口内部电路将RI置位。

1. 串行通信中的错误校验

在串行通信过程(特别是长距离通信)中,数据传输的过程会受到各种干扰(传输线路引入的噪声)的影响,造成数据传输错误。因此,在接收端一般都需要对数据传输的正确与否进行校验,以保证传输数据准确无误。常用的数据校验方法有奇偶校验、循环冗余码校验等。

(1) 奇偶校验。

串行数据发送时,在数据位后面尾随1位奇偶校验位(1或0)。当约定为奇校验时,数据位和校验位中1码的个数应为奇数; 当约定为偶校验时,1码的个数应为偶数。

在通信过程中,收发双方需要事先约定采用奇校验还是偶校验。在发送时,发送方根据待发送数据位中1码个数的奇偶正确设置相应的校验位,以保证发送的数据位和校验位中1码总的个数为奇数或偶数。

按照此约定,如果在传输过程中由于干扰使得数据位中的某一位发生错误,即1码变为0码或0码变为1码,则接收到的数据位和校验位中1码个数的奇偶将不满足约定。此时,由于接收的数据是错误的,CPU不应该也不需要读取,接收方可以要求发送方重新发送。

(2) 代码和校验与循环冗余码校验。

代码和校验是发送方将所发数据块求和或各字节异或,产生1字节的校验字符(校验和)附加到数据块末尾。接收方接收数据时同时对数据块(除校验字节)求和或各字节异或,将所得结果与发送方的“校验和”进行比较,如果相符,则无差错; 否则即认为在传输过程中出现了差错。

循环冗余码校验纠错能力强,容易实现。该校验是通过某种数学运算实现有效信息与校验位之间的循环校验,常用于对磁盘信息的传输、存储区的完整性校验等。是目前应用最广的检错编码方式之一,广泛用于同步通信中。

2. 多机串行通信

在单片机集散式分布系统中,往往采用一台主机(Master)和多台从机(Slave)。主机可以与系统中任何一台从机进行串行通信(发送或接收数据),一般各从机之间不直接进行数据传输。对这样的主从式多机通信系统,由于所有的从机都通过同样的RxD和TxD两根线与主机进行数据传输,因此工作过程中一个关键的问题是主机如何找到当前需要进行通信的从机,并且禁止其他从机接收主机发出的数据。

一种最简单的做法是,事先为每个从机指定一个唯一的、固定不变的编码代号,称为从机地址。传输数据之前,主机先向系统中所有从机发送当前需要通信的从机地址。所有从机都接收到该地址,但只有事先规定的地址与该发送地址相同的从机,才向主机发送一个应答信号。主机接收到该应答信号以后,才开始与该从机进行数据传输。

由此可见,相对于方式1的点点通信,多机通信系统中的每次数据传送过程都必须包括如下几个操作步骤: 主机向所有从机发送地址; 被寻址的从机向主机发送应答信号; 传输数据。其中前两个阶段称为联络过程,在此根据需要还可能执行其他的操作; 第三个阶段的传输数据可能是主机发往从机或者从机发往主机。

为了实现上述多机主从式通信,51单片机的串口必须工作在方式2或方式3,并且要用到SCON寄存器中的SM2和TB8/RB8位。

(1) SM2: 多机通信控制位。对串口工作方式0和方式1,一般将该位设为0。当串口以方式2或方式3接收时,如果设置SM2=0,则与方式1一样实现普通的点点通信,接收到的8位数据都将存入SBUF。如果设置SM2=1,则只有当接收到的第9位数据RB8为1时,才将接收到的前8位数据送入SBUF。如果接收到RB8位为0,则将接收到的前8位数据丢弃,相当于不接收数据。

(2) TB8/RB8: 在方式2、方式3的点点通信中,一般用作奇偶校验位。在多机通信中,一般用该位区分是数据帧(0码)还是地址帧(1码)。在方式1下,该位无用,可随意设置为1或0。

由此可知,在从机的SM2位都设为1时,利用RB8/TB8位可以控制从机是否接收数据,从而实现从机的选择应答。在应答过程中,主机向所有从机发送一个地址帧,其中TB8=1,因此所有从机都将接收到该地址。

在所有从机接收到地址帧后,通过执行自身的程序判断接收到的地址是否与自身事先设置的地址是否相同。如果相同,表示主机正在寻址该从机,因此从机将其SM2位复位,而没有被寻址的从机其SM2位保持为1。

由于本寻址的从机SM2位已经复位,该从机能够与主机之间进行普通的点点通信,主机发送的数据能够被该从机收到。由于没有被寻址的从机其SM2位保持为1,只要主机后续发送的数据帧中TB8=0,则主机发送的数据这些从机将不会接收到。

至此,可以将多机主从式通信过程所需的程序操作步骤总结如下。

(1) 如果系统中只有1个主机,则将主机的SM2位复位,所有从机的SM2位置位,以便所有从机都能接收到主机发来的从机地址。

(2) 主机发送从机地址,其中设置TB8=1。

(3) 所有从机接收到地址帧后,将其与本从机地址比较,并根据比较结果设置SM2位。

(4) 主机发送TB8=0的数据帧,送往被寻址到的从机。

(5) 通信结束后,从机将SM2重新置位。

动手实践59: 串行通信中的奇偶校验

本案例的原理图与动手实践57中的图536所示相同,为方便,这里将其重新保存为ex5_9.pdsprj,相应的程序如下(参见文件p5_9.asm): 



; 点-点通信中的偶校验

LEDDATAP1

SWTDATAP2

ORG0000H

LJMPMAIN

ORG0023H; 串口中断服务程序入口

LJMPINS

ORG0100H

MAIN:MOVSP,#60H

MOVSCON,#11010000B; 串口初始化,方式3,允许接收(REN=1)







MOVTMOD,#20H

MOVTL1,#0E6H

MOVTH1,#0E6H

SETBTR1

SETBEA

SETBES

MOVSWT,#0FFH

MOVA,SWT; A中1码个数为偶数,则P=0;1码个数为奇数,则P=1

MOVC,P

MOVTB8,C; 设置TB8 = P,使总的1码个数为偶数(偶校验)

MOVSBUF,A; 发送第一个数据

SJMP$; 循环等待中断

;===============================================================

; 串口中断服务程序

;===============================================================

INS:CLREA

JBRI,REC

CLRTI; 是发送中断,则清除TI

MOVA,SWT

MOVC,P; 偶校验

MOVTB8,C

MOVSBUF,A; 发送数据

SJMPEXT

REC:CLRRI

MOVA,SBUF; 接收数据,并根据A中1码的个数奇偶设置P标志位 

; 接收的第9位数据(即发送的第9位TB8)自动存入RB8

;XRLA,#01H; 模拟接收到的8位数据最低位错误

JBP,GO; 检测P = RB8?

JNBRB8,DONE

SJMPEXT; 否,偶校验错误,返回

GO:JBRB8,DONE

SJMPEXT

DONE:MOVLED,A; 是,偶校验正确,输出点亮LED

EXT:SETBEA

RETI

END





启动运行后,单击各开关,开关数据都能正常发送到对方51单片机,并在LED上正确显示。为了模拟奇偶校验,在中断服务程序中添加XRL A,#01H(去掉上述程序中该条指令前面的分号即可)。现在重新运行程序可以发现: 不管如何单击开关,两个51单片机上连接的LED都不会点亮,意味着数据没有被正确接收。

上述程序中采用的是偶校验。发送方根据发送开关数据中1码个数的奇偶设置SCON中的TB8位,对应的代码如下: 



MOVA,P2

MOVC,P

MOVTB8,C





在上述3条指令中,首先从P2口读取开关数据并存入A,该操作将影响PSW中的P标志位。当读取的开关数据(即累加器A)中有偶数个1时,P=0; 否则P=1。后面2条指令将P标志位中的0或1存入TB8。因此,如果有偶数个开关打在OFF位置,表示A中发送的8位数据中有偶数个1,则TB8=0; 当A中有奇数个1时,TB8=1。注意在原理图中,开关打在ON位置为0码; 开关打在OFF位置为1码。

在接收端,将接收到的前8位数据存入SBUF,第9位存入SCON中的RB8位。在中断服务程序中,如果检测到是接收中断,则首先清除RI标志,并将接收到的前8位数据读入累加器A。该操作将影响P标志位。

程序中接下来利用JB指令检测P标志位。如果P=1,则跳转到标号为GO的指令,继续检测RB8是否也为1。如果P=RB8=1,则将读取得到的8位数据由P1口输出以点亮LED; 否则A中的数据不输出,而是直接中断返回。同理,如果检测到P=RB8=0,接收到的数据也将由P1口输出。

如果传输过程中没有错误,则接收到的数据位和校验位RB8一定满足上述两种情况,也就是数据位和校验位中1码的个数一定为偶数。如果传输过程中有一位数据位发生错误,则P和RB8一定不相等,因此接收到的数据都不会由P1口输出到LED,此时LED将保持原来的状态,也就相当于CPU没有接收错误的数据。

在上述程序中用XRL指令将接收到的数据最低位取反,用于模拟传输过程中数据的最低位发生错误。此时,通过奇偶校验发现该错误,则不将数据由P1口控制LED。

动手实践510: 多机主从式通信

本案例利用如图539所示原理图(参见文件ex5_10.pdsprj)演示一个简单的多机主从式通信系统。其中U1是主机,U2~U4是3个从机,假设其地址分别为0~2。系统要实现的功能是: 将主机内部RAM中存放的若干字节数据送往指定的某个从机,并保存到从机内部RAM中指定的单元。



图539简单的多机主从式通信系统

注意本案例需要在Keil C51中创建两个工程,后面将这两个工程代码文件分别加载到主机U1和从机U4中。在两个工程中分别添加如下主机和从机的源程序(参见文件p5_10m.asm和p5_10s.asm)。



; 多机通信——主机

SADDEQU1; 从机地址

RTEQU1; 命令,1:主机发送数据;0:主机接收数据

BUFTEQU40H; 主机发送数据缓冲区

BUFREQU50H; 主机接收数据缓冲区  

ORG0000H

AJMPMAIN 

ORG0100H

MAIN:MOV40H,#10; 初始化设置待发送数据

MOV41H,#20

MOV42H,#30

MOV43H,#40

MOVSCON,#11010000B; 串口初始化:方式3,允许接收,SM2=0

MOVTMOD,#20H; T1初始化以确定波特率

MOVTH1,#0E6H

MOVTL1,#0E6H

SETBTR1

LP:SETBTB8; TB8置位

MOVA,#SADD; 发送地址帧

MOVSBUF,A 

JNBRI,$; 等待从机应答 

CLRRI

MOVA,SBUF

XRLA,#SADD; 判断应答地址是否相等

JZMIO1; 相等,则继续

SJMPLP; 不相等,则重新联络

MIO1:CLRTB8; 地址相等,向从机发送命令(TB8=0表示命令)

MOVA,#RT

CLRTI

MOVSBUF,A; 发送命令

JNBTI,$

JZRX; 命令RT=0?  

ACALLSEND_DATA; 否,主机发送数据

SJMPLP

RX:CLRRI

ACALLREC_DATA; 是,主机接收数据

SJMPLP

SEND_DATA:; 主机发送子程序

MOVR7,#4; 否则,发送数据

MOVR0,#BUFT

LPT:CLRTI

MOVSBUF,@R0 

JNBTI,$

INCR0

DJNZR7,LPT

RET









REC_DATA:; 主机接收子程序

MOVR7,#4; 接收数据

MOVR1,#BUFR

LPR:JNBRI,$

CLRRI

MOVA,SBUF

MOV@R1,A

INCR1

DJNZR7,LPR

RET

END

;==========================================================

; 多机通信——从机

SADDEQU1; 本机地址

BUFTEQU50H; 从机发送数据缓冲区

BUFREQU40H; 从机接收数据缓冲区	

ORG0000H

AJMPMAIN	

ORG0023H

AJMPSIO; 串口中断入口	

ORG0100H

MAIN:MOVSP,#20H; 设置堆栈指针  

MOV50H,#50; 从机发送数据初始化

MOV51H,#60

MOV52H,#70

MOV53H,#80

MOVSCON,#11110000B; 置串口方式3,允许接收,SM2=1

MOVTMOD,#20H; 初始化T1,以确定波特率

MOVTH1,#0E6H

MOVTL1,#0E6H

SETBTR1

SETBEA

SETBES; 开串口中断

SJMP$  

SIO:CLRRI; 串口中断服务程序

MOVA,SBUF; 接收地址

XRLA,#SADD

JNZRETN; 不是本机地址,则跳转

MOVSBUF,#SADD; 否则,向主机回送本机地址  

CLRSM2; 清除SM2,准备传输命令和数据

JNBRI,$; 接收主机命令 

CLRRI

JNBRB8,SIO1; 是命令帧,转SIO1

SJMPRETN; 否则,将SM2置位并返回	 

SIO1:MOVA,SBUF; 接收并分析命令

JZTX; 命令0,则转发送

RX:MOVR0,#BUFR; 否则,接收数据

MOVR7,#4; 数据字节数送R7

LPRX:JNBRI,$; 接收数据存入缓冲区

CLRRI

MOV@R0,SBUF









INCR0

DJNZR7,LPRX

SJMPRETN

Tx:MOVR1,#BUFT

MOVR7,#4; 数据字节数送R7

LPTX:CLRTI

MOVSBUF,@R1; 发送数据 

JNBTI,$

INCR1

DJNZR7, LPTX

RETN:SETBSM2; 发送完,置SM2=1后返回

RETI

END





将上述两个工程编译成功后分别加载到主机和从机U4,启动运行后,自动弹出两个虚拟终端窗口,暂停程序运行后观察主机和从机内部RAM分配情况如图540所示。



图540多机通信运行结果


在图540(a)中,两个虚拟终端分别显示的是主机和从机发送的数据。主机连续不断地循环发送从机地址02H、数据收发命令01H以及内部RAM中的4字节数据0AH、14H、1EH和28H。对应主机的每次循环,从机向主机发送1字节的应答地址02H。在图540(b)中,主机RAM中4字节数据发送给从机U4,并存入内部RAM地址从40H开始的单元。

本案例演示了一个基本的多机通信过程,整个过程包括主机和从机U4的主程序以及中断服务程序,其中的主要操作可以用图541所示流程图进行描述。

需要说明的是,上述流程图对主机和从机分开绘制,但在工作过程中,主机和从机的发送和接收过程相互联系的,因此接下来按照完整的传输过程,将主机和从机在每个阶段的操作合并在一起介绍。





图541多机通信的基本过程



(1) 串口初始化。

在主机的主程序中,首先设置串口的方式控制字及定时/计数器T1的计数初值并启动定时,其中特别注意设置SM2=0。

在从机的主程序中,初始化操作也包括上述两项,但其中设置SM2=1。此外,定时/计数器T1的工作方式和计数初值必须与主机完全相同,以保证主、从机具有相同的波特率。

在本案例中,从机收发数据采用中断方式,因此在从机的初始化程序中还需要开串口中断。

(2) 地址联络过程。

做了上述初始化设置后,主机向所有从机发送当前需要通信的从机地址,并等待被寻址的从机回送应答地址(从机的本机地址)。

由于设置所有从机的SM2=1,并且主机发送地址时TB8=1,因此所有从机都将接收到主机送来的从机地址。各从机在接收到地址后,立即响应串口中断并进入各自的中断服务程序。

在中断服务程序中,各从机的CPU从SBUF中读出地址,并与事先规定的本机地址进行比较,比较过程用XRL指令实现。如果接收到的地址与从机程序中定义的本机地址SADD相等,则该从机将本机地址通过串口发送回主机,并将该从机的SM2清零,准备传输命令和数据。如果两个地址不相等,说明该从机不是当前主机需要寻址的从机,则不向主机回送本机地址,也不再参与后续的命令和数据传输,而直接中断返回。

(3) 命令的发送和接收。

主机接收到正确的应答地址后,意味着找到被寻址的从机,开始继续传输命令和数据。此时将TB8清零。

对从机来说,只有被寻址的从机才将其SM2清零,之后即可像方式1一样参与后续命令和数据的传输。也就是不管接收到RB8位是1码还是0码,接收到的所有命令和数据都将存入SBUF,等待CPU读取。对未被寻址的从机,由于SM2保持为1,因此在TB8=0时,接收到的RB8也为0,则将接收到的前8位数据丢弃不存入SBUF,也就是不接收后续的命令和数据。

在将TB8清零后,主机向从机首先发送命令,该命令设为一个8位二进制数据,并在主程序的一开始用EQU伪指令定义为一个常量RT。RT 的值可以设为0或1,分别表示主机接收数据和发送数据。主机将该命令发送到被寻址的从机,之后根据该命令转入数据的收发。

对被寻址的从机来说,主机发送的上述命令用于指示从机发送还是接收数据。显然与主机相反,当接收到命令为0或1时,表示从机发送或接收数据。

(4) 数据的收发。

在本案例中,主机和从机通过串口发送和接收数据实现的功能是相同的,因此主、从机程序中实现数据的发送与接收操作是类似的。只是在主机程序中,将数据的发送和接收分别定义为一个子程序; 而在从机程序中,将数据的发送和接收都放在中断服务程序中。

下面以主机程序中发送数据的代码为例,介绍数据收发的基本操作。

在主机发送子程序SEND_DATA中,首先将常数4(需要发送的数据字节数)存入R7,将主机发送数据缓冲区的起始地址存入R0。之后通过循环注意将缓冲区中原来存放的4字节数据通过串口发送出去。注意每次发送将1字节数据送入SBUF之前,必须清除TI。发送过程中利用JNB指令检测TI的状态。当检测到TI=1时,表示当前字节数据发送完毕,再修改缓冲区地址指针并继续循环发送下1字节数据。

(5) 调试方法。

调试时,必须将上述主机和从机程序分别加载到原理图中的主机U1和从机U4。启动运行后即可观察到在主机主程序一开始定义到缓冲区中的4字节数据被正确发送到从机U4,并保存到其内部RAM地址为50H开始的单元。

如果将主机程序中的RT常量值修改为0,则表示将从机U4内部RAM中地址从50H开始单元的4字节数据发送到主机,并保存到主机内部RAM中相同地址的单元。重新运行后,主机和从机内部RAM单元分配情况如图542所示。



图542从机向主机发送数据

本章小结


51单片机内部不仅有CPU和并口,还有定时/计数器和串口这两个重要的资源。定时/计数器和串口借用P3口某些引脚的第二功能,以便与外部电路相连接,以提供所需的信号(例如输入定时/计数器的计数脉冲和门控信号、通过串口传送数据等)。CPU通过特殊功能寄存器实现对这些内部资源的访问和工作过程的控制。

1. 定时/计数器

(1) 51子系列单片机内部分别有2个可编程定时/计数器,分别表示为T0和T1。注意在51单片机的引脚上,P3.4引脚和P3.5引脚的第二功能名称也为T0和T1。

(2) 定时/计数器可以实现定时和计数功能。T0有4种工作方式(即方式0~3),T1有3种工作方式(即方式0~2)。当需要用T1工作在方式2为串口提供波特率发生器时,可以设置T0工作在方式3,以实现一个8位的定时/计数器。

(3) 与定时/计数器相关的特殊功能寄存器有TMOD和TCON。TMOD用于设置定时/计数器的工作方式、定时和计数功能选择、门控信号的禁用或启用; TCON中的TR0或TR1位用于配合门控信号等实现计数的启停控制,并且用TF0或TF1位标识计数是否溢出。特别注意,TMOD不能进行位操作。

(4) 不管是计数还是定时功能,定时/计数器的初始化都需要设置工作方式、计数初值,而工作方式的选择也主要考虑所需计数初值的大小范围。

(5) 初始化之后,通过将TR0或T1置位以启动计数。对定时功能,通过循环不断地检测TF0或TF1是否为1以确定计数溢出是否溢出; 对计数功能,可以在达到一定条件(例如指定的计数时间范围结束)后将TR0或TR1复位以暂停计数,以便读取计数值。

2. 串口

(1) 51单片机中只集成了一个串口,可实现点点双工通信或多机主从式串行通信,也可以利用串口实现并口或其他资源的扩展。在串行数据传输过程中,借用了P3.0引脚和P3.1引脚的第二功能实现串行数据和时钟信号的传输。

(2) 在初始化时,通过对SCON的访问,可以设置串口的工作方式、是否允许接收数据等; 通过PCON和定时/计数器T1的计数初值,可以确定串行通信的波特率。

(3) 在串行通信过程中,CPU对串行数据的收发操作都是通过SBUF寄存器实现的。为确保传输的准确可靠,从SBUF收发数据之前必须检测SCON中的TI或RI标志位,以确定串口的数据收发操作已经完成,即SBUF中已经存放有接收到的数据,或者已经准备好CPU向其写入下一个待发送的数据。

(4) 如果设置串口工作在方式2和方式3,可以实现多机主从式通信。借助于SCON寄存器中的TB8和RB8位,还可以实现串行通信中的奇偶校验等高级功能。

3. 中断系统

(1) 在51单片机中,根据中断源所处的位置,将所有的中断分为外部中断和内部中断。第3章介绍了外部中断,而内部中断主要指的是本章介绍的定时/计数器中断和串口中断。

(2) 内部中断和外部中断的处理过程是类似的。如果需要采用中断方式,必须在主程序中初始化时开中断。之后,一般通过死循环等待中断请求的到来,转到相应的中断服务程序。

(3) 对定时/计数器,如果采用中断方式处理计数溢出和定时到,需要编写相应的中断服务程序,并在ROM的000BH或001BH单元安排一条转移指令,跳转到中断服务程序。

(4) 对串口,如果希望采用中断方式进行数据收发。此时,在初始化中需要通过IE寄存器打开串口中断。在工作过程中,一旦数据收发完成,通过SCON中的RI或TI向CPU发出中断请求。CPU响应后,通过执行ROM中0023H单元中的转移指令跳转到串口中断服务程序。特别注意,每次响应串口中断后,必须用指令清除RI或TI标志位。

(5) 51单片机将所有的中断源分为两组优先级,并为每个中断规定了一个默认的优先级顺序。优先级的作用是规定了当同时有多个中断请求到来,CPU响应的先后顺序。当CPU正在处理某个中断时,如果有新来的中断请求,CPU是否予以响应,从而实现中断嵌套。

4. 定时/计数器和串口的高级应用

(1) 由于计数位数和计数脉冲频率有限,任何一个定时/计数器能够实现定时的时间长度也是有限的。在实际系统中,可以采用硬件和软件配合或者采用多个定时/计数器级联的方法实现长定时。

(2) 在工业现场利用串口进行长距离传输过程中,经常会受到各种噪声和干扰的影响,造成数据传送的错误。利用51单片机的串口工作在方式2或方式3,可以实现奇偶校验,自动检测是否有传输错误。

(3) 在方式2和方式3下,51单片机的串口可以实现多机主从式通信,从而构成由很多套51单片机系统构成的多机系统和测控网络。

思考练习

51填空题

(1) 51单片机的P3.5引脚工作在第二功能时称为信号引脚,用于输入定时/计数器所需的。

(2) 51单片机的P3.2引脚工作在第二功能时称为信号引脚,通过该引脚输入的信号可以作为定时/计数器的信号。

(3) 要设置定时/计数器T0工作在方式1的计数方式,允许门控; 设置定时/计数器T1工作在方式2的定时方式,禁止门控,相应的指令为MOVTMOD,B。

(4) 在程序中,指令JNB TF1,$ 实现的功能是等待定时/计数器T1出现。

(5) 已知51单片机的时钟频率为6 MHz,设置TMOD=01000000B,用定时/计数器T0实现2 ms定时,则应设置TH0=H,TL0=。

(6) 已知串口每秒传送1000个字符,每个字符由1位起始位、8位数据位和1位停止位构成,则波特率为,传输一位二进制所需的时间为。

(7) 利用串口进行数据的收发时,发送和接收的数据都在中。

(8) 通过串口发送数据之前,必须用指令将位复位,否则无法发送数据。当数据发送完毕,该位会自动置位。

(9) 51单片机从串口读取接收到的数据后,必须用指令将位复位。当串口接收到下一个数据时,该位会自动被置位。

(10) 当51单片机需要通过串口接收数据时,必须在初始化时将位置位。

(11) RS232C串行通信接口标准采用负逻辑电平,即逻辑1用电平表示,逻辑0用表示。

(12) 51子系列单片机有个外部中断和个内部中断。

(13) 在51单片机中,不管要使用哪个中断,都必须用指令开中断。

(14) 51单片机将所有中断的优先级分为组,即优先级和优先级。 

52选择题

(1) 要使定时/计数器T0停止计数,可以选用的指令是()。



A. CLR IT0B. CLR TF0C. CLR IE0D. CLR TR0

(2) 定时/计数器T1用作计数功能时,计数脉冲由()提供。

A. P3.5引脚B. P3.4引脚C. P0.0引脚D. 内部时钟电路

(3) 已知51单片机时钟频率为12 MHz,要利用定时/计数器工作在方式1实现1 ms定时,所需的计数初值为()。

A. 03E8HB. 0FC18HC. 0FCHD. 18H

(4) 要允许用INT0启动定时/计数器T0的计数,必须将TMOD中的()。

A. C/位置位B. C/位复位

C. GATE位置位D. GATE位复位

(5) 要利用SETB TR0启动定时/计数器T0的计数,必须将TMOD中的()。

A. C/位置位B. C/位复位

C. GATE位置位D. GATE位复位

(6) 采用查询方式检测到定时/计数器T0计数溢出时,计数溢出标志位TF0应()。

A. 由硬件自动复位B. 由硬件自动置位

C. 用程序指令置位D. 用程序指令复位

(7) 当定时/计数器T1计数溢出时,TF1=()。

A. 0B. 1

C. 0FFHD. 当前计数值

(8) 要从串口读入接收到的数据,可以选用的指令是()。

A. MOVA,DPTRB. MOVA,SCON

C. MOVA,SBUFD. MOVA,TCON

(9) 51单片机串口发送数据的顺序是()。

① 数据送SBUF② 硬件自动将TI置位 

③ 通过P3.1引脚串行发送一帧数据完毕④ 用软件将TI复位

A. ①③②④B. ①②③④C. ④③①②D. ③④①②

(10) 51单片机串口接收数据的顺序是()。



① 从P3.0接收一帧数据后,硬件将RI置位② 用软件将RI复位

③ 从SBUF读取接收到的数据④ REN位置位

A. ①②③④B. ④①②③C. ④③①②D. ③④①②

(11) 串口工作在方式0时,P3.1引脚传输的是()。



A. 发送的数据B. 接收的数据C. 同步时钟D. 空闲

(12) 51单片机串口适合用于点点双机通信的工作方式是()。

A. 方式0B. 方式1C. 方式2D. 方式3

(13) 下面有关串口功能的描述,错误的是()。

A. 将发送的并行数据转换为串行数据

B. 在发送的串行数据中自动人添加起始位和停止位

C. 一帧数据接收完毕将RI置位

D. 接收到的数据由CPU读走后,自动将TI复位

(14) 51单片机复位后,下列中断源中默认优先级最低的是()。

A. 外部中断INT1B. 串口中断 

C. 定时/计数器T0中断D. 定时/计数器T1中断

(15) 当CPU响应定时/计数器T0中断时,PC中自动装入的值是()。

A. 0003HB. 000BHC. 0013HD. 001BH

(16) 下面有关中断优先级的描述,错误的是()。

A. 每个中断源都有两个优先级

B. 低优先级的中断处理可以被高优先级打断

C. 相同优先级的中断,可以按照默认优先级实现嵌套处理

D. 复位后,所有中断都属于低优先级

53简述定时和计数功能的主要区别。

54简述51单片机定时/计数器查询方式实现定时功能时程序的基本流程。

55简述51单片机中定时/计数器方式2与方式0和方式1的主要区别。

56简述51单片机中用串口扩展并口的基本原理和方法。

57总结51单片机的串口方式1、2、3之间的主要区别,完成表54。


表54串口各种方式的主要区别





工 作 方 式数据帧波特率典 型 应 用


方式1

方式2

方式3


58简述串口工作在方式1时的初始化流程。

59简述51单片机的中断优先级的管理规则。

510执行如下指令MOV IP,#1CH后,分析说明各中断的优先级顺序。

综合设计

51已知51单片机时钟频率为12 MHz,要求通过P1.7端口输出高电平和低电平持续时间分别为10 ms和20 ms的周期矩形波,编写相应的汇编语言程序。

52将动手实践52改为用中断方式实现,定时每隔1 ms,响应一次中断。在中断服务程序中测量和显示待测脉冲的频率。

53利用串口和并入/串出芯片74165为单片机扩展一个输入并口,实现8个开关状态的检测。画出连接线路图,并编写相应的汇编语言程序。

54将动手实践54中的接收机改为用中断方式接收数据,编写接收机的控制程序。