1
控制/MCU
中断(Interrupt)是指在计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
定时器/计数器(Timer/Counter)在实时控制系统中,实现对于外界事件的定时延时及计数功能。
串行通信(Serial Communicate)是计算机与外界交换信息的一种基本通信方式。
中断系统中断过程中,请求产生中断的事件称为中断源,中断源向CPU提出的请求为中断请求(Interrupt Requst,IRQ),CPU通过上下文切换保存好当前的工作状态后,转而去处理中断请求,也就是产生中断响应。直到处理完中断请求事件,才返回原来的工作状态,继续工作。整个过程如下图所示:
51单片机中断系统的结构图如下:
中断源51单片机中有5个中断源,如下表所示:
中断号 优先级 中断源 中断入口地址每个中断源都分配了对应的中断号及中断服务入口地址,在这个中断入口地址里,存放着跳转到相应中断服务程序的跳转指令。当多个中断源同时向CPU提出中断请求时,CPU将根据中断源的优先级来依次响应中断。
相关寄存器SFR中与中断有关的寄存器有:
IEIE(Interrupt Enable),中断允许寄存器,可位寻址,其各位定义如下:
位地址 AFH AEH ADH ACH ABH AAH A9H A8H* 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(Interrupt Priority),中断优先级寄存器,可位寻址,其各位定义如下。未设置时或复位后,IP各位均为”“则按照系统默认的优先级
位地址 BFH BEH BDH BCH BBH BAH B9H B8H* 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(Timer Control),定时/计数器控制寄存器,可位寻址,其各位定义如下:
位地址 8FH 8EH 8DH 8CH 8BH 8AH 89H 88H* 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 = 1; while (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中与定时/计数器有关的寄存器有:
TMODTMOD(Timer Mode),定时/计数器模式控制寄存器,不可位寻址,其各位定义如下。其中TMOD的高半字节D4~D7用来控制定时/计数器1,低半字节D0~D3用来控制定时/计数器0。
位号 D7H D6H D5H D4H D3H D2H D1H D0H* 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:工作方式控制位,用于设置定时/计数器的工作方式,如下表:
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 - 定时时间Tc机器周期Tp = 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中与串口通信相关的寄存器有:
SCONSCON(Serial Control),串行口控制寄存器,可位寻址,其各位定义如下:
位地址 9FH 9EH 9DH 9CH 9BH 9AH 99H 98H* SM0和SM1(Serial Mode):串行口工作方式控制位,用于设置串行口工作方式,如下表:
SM0 SM1 工作方式 功能 波特率* 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(Serial Data Buffer),串行数据缓冲器,不可位寻址。串行口两个SBUF,分别为发送寄存器和接收寄存器,它们在物理结构上是完全独立的,在SFR中的字节地址都是99H。这个重叠的地址靠读/写指令区分:串行发送时,CPU向SBUF写入数据,此时99H表示发送SBUF;串行接收时,CPU从SBUF读出数据,此时99H表示接收SBUF。
PCONPCON(Power Control),电源控制寄存器,不可位寻址,其中只有一位与串口设置有关,其余都用于电源控制。其各位定义如下:
位号 D7H D6H D5H D4H D3H D2H D1H D0H* 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工作时序图如下:
方式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下:
波特率=晶振频率fosc12
方式2下:
波特率=2SMOD64∗fosc
方式1下及方式3下,波特率都由定时/计数器T1溢出率及PCON中的SMOD位共同决定。T1的溢出率又取决于计数速率和计数值。定时模式下,计数速率为晶振频率的1/12;计数模式下,计数速率取决于外部输入时钟频率,但不可超过晶振频率的1/24。作波特率发生器时,T1通常设置为定时模式,工作在工作方式2下,作8位重装寄存器,此时波特率计算公式为:
T1溢出周期=定时时间=12f_osc∗(256−计数初值X)
T1溢出率=1T1溢出周期
波特率=2SMOD32∗T1溢出率=2SMOD∗f_osc384∗(256−X)
则T1的计数初值,也就是装载值为:
计数初值X=256−2SMOD∗f_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 完成初稿
原文链接
全部0条评论
快来发表一下你的评论吧 !