单片机原理(3):中断、定时/计数、串行通信
中断(Interrupt)是指在计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
定时器/计数器(Timer/Counter)在实时控制系统中,实现对于外界事件的定时延时及计数功能。
串行通信(Serial Communicate)是计算机与外界交换信息的一种基本通信方式。
中断系统
中断过程中,请求产生中断的事件称为中断源,中断源向CPU提出的请求为中断请求(Interrupt Requst,IRQ),CPU通过上下文切换保存好当前的工作状态后,转而去处理中断请求,也就是产生中断响应。直到处理完中断请求事件,才返回原来的工作状态,继续工作。整个过程如下图所示:

51单片机中断系统的结构图如下:

中断源
51单片机中有5个中断源,如下表所示:
| 中断号 | 优先级 | 中断源 | 中断入口地址 |
|---|---|---|---|
| 0 | 1(最高级) | 外部中断0 | 0003H |
| 1 | 2 | 定时器0 | 000BH |
| 2 | 3 | 外部中断1 | 0013H |
| 3 | 4 | 定时器1 | 001BH |
| 4 | 5(最低级) | 串口中断 | 0023H |
每个中断源都分配了对应的中断号及中断服务入口地址,在这个中断入口地址里,存放着跳转到相应中断服务程序的跳转指令。当多个中断源同时向CPU提出中断请求时,CPU将根据中断源的优先级来依次响应中断。
相关寄存器
SFR中与中断有关的寄存器有:
IE
**IE(Interrupt Enable)**,中断允许寄存器,可位寻址,其各位定义如下:
位地址 | AFH | AEH | ADH | ACH | ABH | AAH | A9H | A8H
——|——|——|——|——|——|——|——|——|——
定义 | EA | - | (ET2) | ES | ET1 | EX1 | ET0 | EX0
- **EA(Enable All)**:CPU中断总控制位,EA=1,CPU对所有中断开放,EA=0,CPU禁止一切中断响应。
- **ES(Enable Serial)**:串口中断允许控制位,ES=1,允许串行口接受、发送中断。
- **ET0/ET1(Enable Timer)**:定时/计数器0/1中断允许控制位,ET0/ET1=1,允许T0/T1中断。52系列单片机里还有ET2。
- **EX0/EX1(Enable Exterior)**:外部中断INT0/INT1中断允许控制位,EX0/EX1=1,允许外部中断INT0/INT1中断。
IP
**IP(Interrupt Priority)**,中断优先级寄存器,可位寻址,其各位定义如下。未设置时或复位后,IP各位均为””则按照系统默认的优先级
位地址 | BFH | BEH | BDH | BCH | BBH | BAH | B9H | B8H
——|——|——|——|——|——|——|——|——|——
定义 | - | - | (PT2) | PS | PT1 | PX1 | PT0 | PX0
- **PS(Priority Serial)**:串行口优先级设定位,PS=1,串行口为高优先级。
- **PT0/PT1(Priority Timer)**:定时/计数器0/1优先级设定位,PT0/PT1=1,定时/计数器0/1为高优先级。
- **PX0/PX1(Priority Exterior)**:外部中断INT0/INT1优先级设定位,PX0/PX1=1,外部中断INT0/INT1为高优先级。
TCON
**TCON(Timer Control)**,定时/计数器控制寄存器,可位寻址,其各位定义如下:
位地址 | 8FH | 8EH | 8DH | 8CH | 8BH | 8AH | 89H | 88H
——|——|——|——|——|——|——|——|——|——
定义 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0
- **TF0/TF1(Timer Flag)**:定时/计数器0/1溢出标志位,当定时/计数器计满溢出时,由硬件自动置“1”,并申请中断;在进入中断服务程序后,又由硬件自动置“0”。
- **TR0/TR1(Timer Run)**:定时/计数器0/1启停控制位,TR0/TR1=1,启动定时/计数器。
- **IE0/IE1(Interrupt Exterior)**:外部中断INT0/INT1中断请求标志位,外部中断源有请求时,对应的标志位IE0/IE1由硬件置“1”,当CPU响应该中断后,又由硬件自动置“0”。
- **IT0/IT1(Interrupt Touch)**:外部中断INT0/INT1的触发方式选择位,IT0/IT1=0,对应外部中断设置为低电平触发方式,IT0/IT1=1,对应外部中断设置为边沿触发方式。
中断处理过程
51单片机在CPU的每个机器周期的S5 P2期间,将自动查询TCON中各个中断申请标志,若查询到某个中断标志位被置位,将启动中断机制。
中断源发出中断请求后。要使CPU能够响应中断,IE中的中断总允许位EA及对应的中断允许位(ES/ET/EX)都需要置为“1”。
处理外部中断时,若外部中断设为低电平触发方式,则CPU在每个查询中断申请标志时也将对INTi引脚进行采样,测得INTi=0,则认为有中断申请,随即将IEi标志位置位,否则测得INTi=1,则认为无中断请求,而清除IEi标志位。所以施加在INTi引脚上的低电平持续时间应该大于一个机器周期,且小于中断服务程序得执行时间。
若外部中断设为边沿触发方式,则CPU在每个查询中断申请标志时将对INTi引脚进行采样,若在连续两个机器周期采样到先高后低的电平变化,则认为有中断申请,随即将IEi标志位置位,否则测得INTi=1,则认为无中断请求,而清除IEi标志位。所以,为了保证CPU在两个机器周期内能够检测到由高到低跳变得电平,输入的高低电平持续时间至少要保持12个振荡周期(即一个机器周期)时间。
在中断处理过程中,如果正在执行同级或高优先级的中断服务程序,或是正在执行的指令还没完成,则中断响应会受到阻断。51单片机的中断响应时间最短为3个机器周期,其他情况的中断响应时间一般是3~8个周期。
在CPU响应中断后,应该撤除该中断请求,否则会再次产生中断,进入死循环。
中断程序的编写
由中断的处理过程可知,在编写中断管理与控制程序时应该考虑一下几个方面:
- CPU开中断和关中断
- 某个中断源中断请求的允许或屏蔽
- 各中断源优先级别的设定
- 外部中断请求的触发方式
中断程序基本编写格式如下:
汇编:
1 | ;中断入口设置 |
C语言:
1 |
|
定时/计数器
51单片机内部有两个16位可编程的定时/计数器0和1,分别用T0及T1表示。它们的工作方式、定时时间、量程、启动方式、等均可通过程序来设置和改变。
计数功能用于统计从T0(P3.4)、T1(P3.5)引脚输入的脉冲负跳变数量,每输入一个脉冲负跳变,计数器就加1。负跳变指的是一个机器周期采样为高电平,后一个机器周期采样为低电平。
定时功能是单片机通过对内部机器脉冲信号计数实现的,计数值乘以机器周期即是相应的时间。如单片机采用12MHz晶振,机器内部脉冲频率为1MHz,机器周期为1us,计数1000次,即1ms时间。
当计数值溢出后,定时计数器给出中断请求,进而使CPU去处理中断事件。
51单片机定时/计数器结构如下:

相关寄存器
除前面介绍过的中断相关寄存器外,SFR中与定时/计数器有关的寄存器有:
TMOD
TMOD(Timer Mode),定时/计数器模式控制寄存器,不可位寻址,其各位定义如下。其中TMOD的高半字节D4D7用来控制定时/计数器1,低半字节D0D3用来控制定时/计数器0。
位号 | D7H | D6H | D5H | D4H | D3H | D2H | D1H | D0H
——|——|——|——|——|——|——|——|——|——
定义 | GATE | C\T | M1 | M0 | GATE | C\T | M1 | M0
- GATE:门控制位,用来控制定时/计数器的启动方式。GATE=1,由外部中断引脚INT0/INT1来启动定时器T0/T1, 当INT0/INT1引脚为高电平且TR0/TR1置位,启动定时器T0/T1;GATE=0,仅由TR0/TR1置位而启动定时器T0/T1。
- C\T:功能选择位,C\T=0,为定时模式,计数脉冲由内部提供,计数周期等于机器周期;C\T=1,为计数模式,计数脉冲由外部引脚T0或T1引入。
- M0/M1:工作方式控制位,用于设置定时/计数器的工作方式,如下表:
| M0 | M1 | 工作方式 | 功能 |
|---|---|---|---|
| 0 | 0 | 方式0 | 13位计数器 |
| 1 | 0 | 方式1 | 16位计数器 |
| 0 | 1 | 方式2 | 8位重装计数器 |
| 1 | 1 | 方式3 | 定时器0分为两个独立8位计数器 |
T0、T1
**T0、T1(Timer)**,两个定时/计时器的初始赋值寄存器,不可位寻址,用于存放定时/计数的初始值。它们是两个16位寄存器,均可分为两个独立的8位寄存器,高8位记为TH,即TH0、TH1,低8位记为TL,即TL0、TL1。使用定时/计数器时,当外部或系统时钟振荡器输入一个脉冲时,对应寄存器的值便自动加1。
编程时需要注意,16位计数初始值要分两次写入对应初始值寄存器。
定时/计数过程
51单片机定时/计数器的工作模式、工作方式、计数初始值及启停操作均需要在使用前进行初始化。
首先是通过TMOD中的GATE位来设置定时/计数器T0/T1的启动操作方式,工作在定时还是计数模式则是通过C/T位来设置。其次就是选择它们的工作方式。
工作方式0、1、3为非自动重装方式,在初始化程序和对应中断服务程序中均需要对初始数据寄存器THi、TLi装载。方式0是一个13位定时/计数器,只用了16位寄存器的高8位THi和TLi的低5位0~4位,TLi高3位未用,装入数据时需要注意。方式1为16位寄存器。
方式3只适用于定时/计数器T0,一般在定时/计时器T1作串行口波特率发生器时,才会选择这个工作模式。此时T0拆分为两个独立8位计数寄存器TH0和TL0,其中TL0下为8位定时/计数器,操作方式同方式0、1;TH0只做简单的内部定时功能,它借用定时/计时器1的控制位TR1和溢出标志位TF1,占用T1的中断资源,启动和停止也仅受TR1控制,此时T1仅可用在不需要中断的场合。
方式2为8位重装寄方式,仅由TLi作为工作寄存器,THi的值一直保持不变。TLi溢出时,THi的值作为装载值由CPU自动装入TLi,自动完成计数值初始化。所以此种方式下需要初始化时在THi和TLi中放入相同的计数值。
T0/T1寄存器中的初值X与定时/计数器的工作方式、工作模式有关。
在工作方式0下,为13位寄存器,也就是说最大的计数值M=$2^{13}$=8192,超过这个数字就会溢出,触发中断。工作方式为1下,为16位寄存器,M=$2^{16}$=65536。工作方式为2下,为8位寄存器,M=$2^{8}$=256。工作方式为3下,定时/计数器0分为高8位和低8位两个独立8位计数器,THi、TLi的M均为$2^{8}$=256。
不管是进行定时还是计数模式,其具体实现都是归结于计数。
计数模式下,是对外部脉冲数计数,初值X = M - 计数值。定时模式下,是对机器周期进行计数,**初值X = M - 计数值 = M - $\frac{定时时间T_c}{机器周期T_p}$ = M - $\frac{定时时间T_c × 晶振频率}{12}$**。
最后,中断中的相关寄存器也需要进行设置,设置TRi=1,来启动定时/计数器。
定时/计数程序编写
通过上面对定时/计数过程的分析,可知编写想关功能程序时,要先进行初始化,再根据公式计算出定时初值并装载。
定时/计数程序基本编写格式如下:
汇编:
1 | ;中断入口设置 |
C语言:
1 |
|
串口通信
通信相关概念
计算机通信方式可以分为并行(Parallel)与串行(Serial)通信两大类,它将计算机技术和通信技术的相结合,完成计算机与外部设备或计算机与计算机之间的信息交换:
并行通信:数据的各个二进制位在不同的数据线上同时传输。这样传输速度快,效率高,但所需的数据线多,成本高,抗干扰能力较差,适用于近距离传输。
串行通信:将数据拆分成多个二进制位,逐一的在同一条数据线上输出。虽然这样传输速度较慢,效率较低,但所需的数据线少、硬件电路简单、抗干扰能力强,且适用于远距离数据传输。
串行通信又分为同步(Synchronous)通信和异步(Asynchronous)通信两种方式:
同步通信:串行连续地传输数据,待发送的若干个字符数据构成一个数据块,在该数据块前部添加1~2个同步字符,在数据块的末尾添加校验信息,以此种方式构成数据帧,以数据帧为单位进行串行通信。
异步通信:每个字符数据被封装成帧,之后以帧的形式发送。每一帧由四部分构成,分别是起始位、数据位、校验位和停止位。起始位是数据开始传送的标志,用逻辑0表示;数据位紧跟起始位,通常是5~8位二进制位;校验位用于校验数据位是否发送正确,可以选择奇校验、偶校验或者不使用校验位。帧和帧之间可以连续,或者加入任意的空闲位,空闲位用逻辑1表示。
串行数据的传输制式可分为单工(Simplex)、半双工(Half Duplex)、全双工(Full Duplex)。
- 单工:数据传输仅能沿一个方向,不能实现反向传输。
- 半双工:数据传输可以沿两个方向,但需要分时进行。
- 全双工:数据可以同时进行双向传输。
串行通信的错误校验方式有奇偶校验(Parity Check)、代码和校验、循环冗余校验(Cyclical Redundancy Check,CRC)三种:
- 奇偶校验:在发送数据时,数据位尾随的1位为奇偶校验位(1或0)。奇校验时,数据中“1”的个数与校验位“1”的个数之和应为奇数;偶校验时,数据中“1”的个数与校验位“1”的个数之和应为偶数。接收字符时,对“1”的个数进行校验,若发现不一致,则说明传输数据过程中出现了差错。
- 代码和校验:发送方将所发数据块求和(或各字节异或),产生一个字节的校验字符(校验和)附加到数据块末尾。接收方接收数据同时对数据块(除校验字节外)求和(或各字节异或),将所得的结果与发送方的“校验和”进行比较,相符则无差错,否则即认为传送过程中出现了差错。
- 循环冗余校验:通过某种数学运算实现有效信息与校验位之间的循环校验,常用于对磁盘信息的传输、存储区的完整性校验等。这种校验方法纠错能力强,广泛应用于同步通信中。
波特率(Baud Rate)是串口通信时每秒钟传输二进制代码的位数,单位是位/秒(bps)。
51单片机的串行接口是一个全双工通信接口,即能够同时进行数据发送和接收。它可作通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART)用,也可以作同步移位寄存器。其结构如下:

相关寄存器
除前面介绍过的中断及定时/计数器相关寄存器外,SFR中与串口通信相关的寄存器有:
SCON
**SCON(Serial Control)**,串行口控制寄存器,可位寻址,其各位定义如下:
位地址 | 9FH | 9EH | 9DH | 9CH | 9BH | 9AH | 99H | 98H
——|——|——|——|——|——|——|——|——|——
定义 | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI
- **SM0和SM1(Serial Mode)**:串行口工作方式控制位,用于设置串行口工作方式,如下表:
| SM0 | SM1 | 工作方式 | 功能 | 波特率 |
|---|---|---|---|---|
| 0 | 0 | 方式0 | 8位同步移位寄存器 | 晶振频率/12 |
| 0 | 1 | 方式1 | 10位UART | 可变 |
| 1 | 0 | 方式2 | 11位UART | 晶振频率/64 或 /32 |
| 1 | 1 | 方式3 | 11位UART | 可变 |
- SM2:多机通讯控制位,主要在以上工作方式为2或3下使用,工作方式0或1下都应该设为“0”状态。
- **REN(Receive Enable)**:串行允许接收位,REN=1,允许接受数据。
- **TB8(Transfer Bit 8)**:工作方式为2或3下存放发送数据的第9位,由软件置”0”或”1”。
- **RB8(Receive Bit 8)**:工作方式为2或3下存放接受数据的第9位。方式0下不使用;方式1下,当SM2=0时,用于存放接收到的停止位。
- TI(Transfer Interrupt):发送中断标志位,用于指示一帧数据是否发送完成。使用前必须软件复位为“0”,发送完一帧数据后硬件将自动置”1”。
- RI(Receive Interrupt):接受中断标志位,用于指示一帧数据是否接受完成。接受完一帧数据后硬件将自动置”1”,之后必须软件复位为“0”。
SBUF
**SBUF(Serial Data Buffer)**,串行数据缓冲器,不可位寻址。串行口两个SBUF,分别为发送寄存器和接收寄存器,它们在物理结构上是完全独立的,在SFR中的字节地址都是99H。这个重叠的地址靠读/写指令区分:串行发送时,CPU向SBUF写入数据,此时99H表示发送SBUF;串行接收时,CPU从SBUF读出数据,此时99H表示接收SBUF。
PCON
**PCON(Power Control)**,电源控制寄存器,不可位寻址,其中只有一位与串口设置有关,其余都用于电源控制。其各位定义如下:
位号 | D7H | D6H | D5H | D4H | D3H | D2H | D1H | D0H
——|——|——|——|——|——|——|——|——|——
定义 | SMOD | - | - | - | GF1 | GF0 | PD | IDL
- **SMOD(Serial Mode)**:波特率选择位。工作方式1、2、3下串行通信波特率与$2^{SMOD}$成正比。也就是SMOD=1,通信波特率可提高一倍。
- GF0/GF1(General Flag):通用标志位,用户可自由使用
- PD(Power Down):掉电控制位。PD=0,单片机正常工作;PD=1,进入掉电模式,外部晶振停振,CPU、定时器、串行口全部停止工作,只有外部中断工作。在该模式下,只有硬件复位和上电能够唤醒单片机。
- IDL(Idle):空闲控制位。IDL=0,单片机正常工作;IDL=1,单片机进入空闲模式,除CPU不工作外,其余仍继续工作,在空闲模式下可由任一个中断或硬件复位唤醒。
串行通信过程
一般情况下,当CPU允许接收(REN=1)且接收中断标志RI复位时,就启动一次接收过程。外界数据通过引脚RXD(P3.0)串行输入,数据最低位首先输入一个大小为9位移位寄存器,当一帧数据接收完毕后再并行送入接收SBUF中,同时RI也置“1”。当用软件读取完数据并复位RI后,才进行下一次操作。
当发送中断标志TI复位后,CPU便开始执行一条写SBUF指令,启动一次发送过程,发送控制器同时启动,并开始发送数据。发送的数据通过引脚TXD(P3.1)输出,首先输出最低位。当一帧数据发送完毕即发送SBUF为空时,CPU自动将TI值“1”。使用软件将TI复位,才执行下一个发送过程。
51单片机串行口有4种工作方式,通过SCON寄存器中的SM0、SM1口选择。
方式0下,串行口为同步移位寄存器的输入输出方式,主要用于和外部同步移位寄存器外接,以达到扩展一个并行输入或输出口的目的。这种方式下,数据从RXD端串行输入或输出,同步移位信号从TXD输出,波特率固定为晶振频率的1/12。TXD引脚每输出一位同步移位脉冲,数据就由RXD引脚输入或输出一个二进制位,发送和接收均为8位数据,低位在先,高位在后,没有起始位和停止位。此时,SM2、RB8、TB8均设为“0”,不起作用。方式0工作时序图如下:

方式1下,串行口为10位异步通信方式,即1个起始位、8个有效数据位和1个停止位,波特率由定时/计数器T1溢出率及PCON中的SMOD位共同决定。进行发送操作时,发送电路会自动在8位发送数据前后分别加上一位起始位和一位停止位。接收操作时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位,随后将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向CPU申请中断。如果上述条件不满足,数据则会被舍弃。此时,SM2也要设为“0”。方式1工作时序图如下:

方式2及方式3下,串行口都为11为异步收发方式,即1个起始位、8个有效数据位、1个附加数据位和1个停止位,其两者的差异在于通信波特率的不同:方式2的波特率取决于晶振频率和PCON中的SMOD位,固定为晶振频率的1/64或1/32;方式3的波特率由定时器T1的溢出率和SMOD位共同决定,故其波特率是可调的。比方式1多出来的一个附加位发送时为SCON中的TB8,接收时为RB8,由用户安排,可作奇偶校验位,也可作其他控制位。这两种方式很适合主从式的通信结构,在多机通讯时,主机的SM2位设为“0”,而从机的SM2位设为“1”,以便之间相互识别。
方式0下:$$波特率 = \frac{晶振频率 f_{osc}}{12}$$
方式2下:$$波特率 = \frac{2^{SMOD}}{64} * f_{osc}$$
方式1下及方式3下,波特率都由定时/计数器T1溢出率及PCON中的SMOD位共同决定。T1的溢出率又取决于计数速率和计数值。定时模式下,计数速率为晶振频率的1/12;计数模式下,计数速率取决于外部输入时钟频率,但不可超过晶振频率的1/24。作波特率发生器时,T1通常设置为定时模式,工作在工作方式2下,作8位重装寄存器,此时波特率计算公式为:$$ {T1溢出周期 = 定时时间 = \frac{12}{f_{osc}} * (256 - 计数初值X) }$$
$$ T1溢出率 = \frac{1}{T1溢出周期} $$
$$ {波特率 = \frac{2^{SMOD}}{32} * T1溢出率 } = \frac{2^{SMOD} * f_{osc}}{384 * (256 - X)}$$
则T1的计数初值,也就是装载值为:
$$ {计数初值X = 256 - \frac{2^{SMOD} * f_{osc}}{384 * 波特率}}$$
串行通信程序编写
由串行通信的基本过程可知,在使用串行口之前需要对串行口进行初始化,确定使用的工作方式并进行相关配置。
串行通信程序基本编写格式如下:
汇编:
1 | ;中断入口设置 |
C语言:
1 |
|
更新历史:
- 2017.11.27 完成初稿
单片机原理(3):中断、定时/计数、串行通信


