单片机原理(3):中断、定时/计数、串行通信

中断(Interrupt)是指在计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

定时器/计数器(Timer/Counter)在实时控制系统中,实现对于外界事件的定时延时及计数功能。

串行通信(Serial Communicate)是计算机与外界交换信息的一种基本通信方式。

中断系统

中断过程中,请求产生中断的事件称为中断源,中断源向CPU提出的请求为中断请求(Interrupt Requst,IRQ),CPU通过上下文切换保存好当前的工作状态后,转而去处理中断请求,也就是产生中断响应。直到处理完中断请求事件,才返回原来的工作状态,继续工作。整个过程如下图所示:

中断过程

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

中断系统结构

中断源

51单片机中有5个中断源,如下表所示:

中断号优先级中断源中断入口地址
01(最高级)外部中断00003H
12定时器0000BH
23外部中断10013H
34定时器1001BH
45(最低级)串口中断0023H

每个中断源都分配了对应的中断号及中断服务入口地址,在这个中断入口地址里,存放着跳转到相应中断服务程序的跳转指令。当多个中断源同时向CPU提出中断请求时,CPU将根据中断源的优先级来依次响应中断。

相关寄存器

SFR中与中断有关的寄存器有:

IE

IE(Interrupt Enable),中断允许寄存器,可位寻址,其各位定义如下:

位地址AFHAEHADHACHABHAAHA9HA8H
定义EA-(ET2)ESET1EX1ET0EX0

* 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各位均为”“则按照系统默认的优先级

位地址BFHBEHBDHBCHBBHBAHB9HB8H
定义--(PT2)PSPT1PX1PT0PX0

* 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),定时/计数器控制寄存器,可位寻址,其各位定义如下:

位地址8FH8EH8DH8CH8BH8AH89H88H
定义TF1TR1TF0TR0IE1IT1IE0IT0

* 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开中断和关中断
* 某个中断源中断请求的允许或屏蔽
* 各中断源优先级别的设定
* 外部中断请求的触发方式

中断程序基本编写格式如下:

汇编:

                ;中断入口设置
                ORG 0000H   ;起始地址
                LJMP MAIN   ;跳转到主程序
                ORG 0003H   ;中断入口地址1
                LJMP INT1    ;跳转到外部中断INT0服务程序
                ORG 000BH   ;中断入口地址2
                LJMP INT2    ;跳转到定时器0中断服务程序,没有则不写或写成“RETI”,下同
                ORG 0013H   ;中断入口地址3
                LJMP INT3    ;跳转到外部中断INT1服务程序
                ORG 001BH   ;中断入口地址4
                LJMP INT4    ;跳转到定时器1中断服务程序
                ORG 0023H    ;中断入口地址5
                LJMP INT5    ;跳转到串口中断服务程序

                ;主程序
                ORG 0030H   ;起始地址
          MAIN: SETB IT0   ;IT0=1,边沿触发
                SETB EA   ;EA=1,开启总中断
                SETB EX0   ;EX0=1,允许外部中断INT0
                ……
          LOOP: NOP
                LJMP LOOP   ;死循环

                ;中断服务程序
                ORG 0100H   ;起始地址
          INT1: PUSH ACC   ;保存原来状态,下同
                PUSH PSW  ;
                ……
          INT2: ……
                ……
                POP PSW   ;恢复原始状态,下同
                POP ACC   ;
                RETI            ;中断返回

                END            ;结束

C语言:

#include "reg51.h"

// 主程序
void main() {
  IT0 = 1//注释同汇编
  EX0 = 1 EA = 1while (1) {
    ……
  }
}

// 中断处理程序
void int0() interrupt 0 {  // 外部中断INT0服务程序
  ……
}

定时/计数器

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的高半字节D4~D7用来控制定时/计数器1,低半字节D0~D3用来控制定时/计数器0。

位号D7HD6HD5HD4HD3HD2HD1HD0H
定义GATEC\TM1M0GATEC\TM1M0

* 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:工作方式控制位,用于设置定时/计数器的工作方式,如下表:

M0M1工作方式功能
00方式013位计数器
10方式116位计数器
01方式28位重装计数器
11方式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= 213 =8192,超过这个数字就会溢出,触发中断。工作方式为1下,为16位寄存器,M= 216 =65536。工作方式为2下,为8位寄存器,M= 28 =256。工作方式为3下,定时/计数器0分为高8位和低8位两个独立8位计数器,THi、TLi的M均为 28 =256。

不管是进行定时还是计数模式,其具体实现都是归结于计数。

计数模式下,是对外部脉冲数计数,初值X = M - 计数值。定时模式下,是对机器周期进行计数,初值X = M - 计数值 = M - TcTp = M - Tc×12

最后,中断中的相关寄存器也需要进行设置,设置TRi=1,来启动定时/计数器。

定时/计数程序编写

通过上面对定时/计数过程的分析,可知编写想关功能程序时,要先进行初始化,再根据公式计算出定时初值并装载。

定时/计数程序基本编写格式如下:

汇编:

                ;中断入口设置
                ORG 0000H   ;起始地址
                LJMP MAIN   ;跳转到主程序
                ORG 000BH   ;中断入口地址2
                LJMP INT2    ;跳转到定时器0中断服务程序
                ORG 001BH   ;中断入口地址4
                LJMP INT4    ;跳转到定时器1中断服务程序

                ;主程序
                ORG 0030H   ;起始地址
          MAIN: MOV TMOD, #xxH   ;设置工作模式,方式
                MOV TH0, #xxH   ;计数初值,高八位
                MOV TL0, #xxH   ;低八位
                SETB EA   ;EA=1 ,开启总中断
                SETB ET0   ;ET0=1,允许定时/计数器中断
                SETB TR0   ;TR0=1,启动定时/计数器
                ……
          LOOP: NOP
                LJMP LOOP   ;死循环

                ;中断服务程序
                ORG 0100H   ;起始地址
          INT2: PUSH ACC   ;保存原来状态,下同
                PUSH PSW  ;
                MOV TH0, #xxH   ;重新赋计数初值(非重装方式下)
                MOV TL0, #xxH   
                ……
          INT4: ……
                ……
                POP PSW   ;恢复原始状态,下同
                POP ACC   ;
                RETI            ;中断返回

                END            ;结束

C语言:

#include "reg51.h"

// 主程序
void main() {
  TMOD = 0xxx;  //注释同汇编
  TH0 = 0xxx;
  TL0 = 0xxx;
  EA = 1;
  ET0 = 1;
  TR0 = 1;
  while (1) {
    ……
  }
}

// 中断处理程序
void int2() interrupt 1{  // 定时器0中断服务程序
  TH0 = 0xxx;
  TL0 = 0xxx;
  ……
}

串口通信

通信相关概念

计算机通信方式可以分为并行(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),串行口控制寄存器,可位寻址,其各位定义如下:

位地址9FH9EH9DH9CH9BH9AH99H98H
定义SM0SM1SM2RENTB8RB8TIRI

* SM0和SM1(Serial Mode):串行口工作方式控制位,用于设置串行口工作方式,如下表:

SM0SM1工作方式功能波特率
00方式08位同步移位寄存器晶振频率/12
01方式110位UART可变
10方式211位UART晶振频率/64 或 /32
11方式311位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),电源控制寄存器,不可位寻址,其中只有一位与串口设置有关,其余都用于电源控制。其各位定义如下:

位号D7HD6HD5HD4HD3HD2HD1HD0H
定义SMOD---GF1GF0PDIDL

* SMOD(Serial Mode):波特率选择位。工作方式1、2、3下串行通信波特率与 2SMOD 成正比。也就是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工作时序图如下:

方式0工作时序

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

方式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下:

=fosc12

方式2下:

=2SMOD64fosc

方式1下及方式3下,波特率都由定时/计数器T1溢出率及PCON中的SMOD位共同决定。T1的溢出率又取决于计数速率和计数值。定时模式下,计数速率为晶振频率的1/12;计数模式下,计数速率取决于外部输入时钟频率,但不可超过晶振频率的1/24。作波特率发生器时,T1通常设置为定时模式,工作在工作方式2下,作8位重装寄存器,此时波特率计算公式为:

T1==12f_osc(256X)

T1=1T1

=2SMOD32T1=2SMODf_osc384(256X)

则T1的计数初值,也就是装载值为:

X=2562SMODf_osc384

串行通信程序编写

由串行通信的基本过程可知,在使用串行口之前需要对串行口进行初始化,确定使用的工作方式并进行相关配置。

串行通信程序基本编写格式如下:

汇编:

                ;中断入口设置
                ORG 0000H   ;起始地址
                LJMP MAIN   ;跳转到主程序
                ORG 0023H    ;中断入口地址5
                LJMP INT5    ;跳转到串口中断服务程序

                ;主程序
                ORG 0030H   ;起始地址
          MAIN: MOV TMOD, #20H   ;设置定时/计数器T1工作模式为定时,工作方式2
                MOV TH1, #F4H   ;计数初值,高八位,波特率2400
                MOV TL1, #F4H   ;低八位
                MOV SCON, #90H   ;设置串行口工作方式2,单机,允许接收
                MOV PCON, #00H   ;波特率不加倍
                SETB EA   ;EA=1 ,开启总中断
                SETB ES   ;ES=1,开启串口中断
                SETB TR1   ;TR1=1,启动定时/计数器
                ……
          SEND: MOV A, #xxH   ;待发送数据放入A,即刻生成了偶校验位放在P中
                MOV C, P   ;将偶校验位放入位寄存器C
                CPL C   ;奇校验则把P取反
                MOV TB8, C   ;将校验位放入TB8中
                MOV SUBF, A   ;发送数据
                JBC TI, xxx  ;发送完一帧数据后清除TI并进行下一步
          LOOP: NOP
                LJMP LOOP   ;死循环

                ;中断服务程序
                ORG 0100H   ;起始地址
          INT5: MOV A, SBUF    ;取出接收到的数据
                JB RB8, ERR   ;进行校验,不同则跳转到错误处理
                CLR RI   ;复位,准备下次接收
                ……
                RETI            ;中断返回
           ERR: ……
                ……
                END            ;结束

C语言:

#include "reg51.h"

// 主程序
void main() {
  TMOD = 0x20H;  //注释同汇编
  TH0 = 0xF4;
  TL0 = 0xF4;
  SCON = 0x90;
  PCON = 0x00;
  EA = 1;
  ES = 1;
  TR1 = 1;
  while (1) {
    send(data);
  }
}

//发送数据
void send(unsigned char data) {
  ACC = data;
  TB8 = P;
  SBUF = data;
  while(!TI == 0){
    ……
    TI = 0;
  }

}

// 中断处理程序,接收数据
void int5() interrupt 5{  // 定时器0中断服务程序
  ACC = SBUF;
  RI = 0;
  if (RB8 == p){
  ……
  }else{
  ……
  }
}

更新历史:
* 2017.11.27 完成初稿
原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值