51单片机采用中断进行串口通信


51单片机采用中断方式的串口通信过程及程序分析:

所谓中断方式,就是串口收/发标志位出发中断后,在中断中执行既定操作,可通过函数调用来实现。

接收数据时: 等待中断->然后在中断中接收数据

发送数据时: 发送数据->等待中断->然后在中断中发送数据

具体步骤如下:

  • 确定T1的工作方式(编程TMOD寄存器);
  • 计算T1的初值,装载TH1、TL1;
  • 启动T1(编程TCON中的TR1位);
  • 确定串行口控制(编程SCON寄存器);
  • 串行口在中断方式工作时,要进行中断设置(编程IE、IP寄存器)。

注:SCON 是一个特殊功能寄存器,用以设定串行口的工作方式、接收/发送控制以及设置状态标志:

有关波特率的计算方法:

在串行通信中,收发双方对发送或接收数据的速率要有约定。通过软件可对单片机串行口编程为四种工作方式,其中方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由定时器T1的溢出率来决定。

串行口的四种工作方式对应三种波特率。由于输入的移位时钟的来源不同,所以,各种方式的波特率计算公式也不相同。

  • 方式0的波特率 =  fosc/12
  • 方式2的波特率 =(2SMOD/64)· fosc
  • 方式1的波特率 =(2SMOD/32)·(T1溢出率)
  • 方式3的波特率 =(2SMOD/32)·(T1溢出率)

当T1作为波特率发生器时,最典型的用法是使T1工作在自动再装入的8位定时器方式(即方式2,且TCON的TR1=1,以启动定时器)。这时溢出率取决于TH1中的计数值。

  • T1 溢出率 = fosc /{12×[256 -(TH1)]}

注:PCON中只有一位SMOD与串行口工作有关, SMOD(PCON.7)  波特率倍增位。在串行口方式1、方式2、方式3时,波特率与SMOD有关,当SMOD=1时,波特率提高一倍。复位时,SMOD=0。     在单片机的应用中,常用的晶振频率为:12MHz和11.0592MHz。所以,选用的波特率也相对固定。常用的串行口波特率以及各参数的关系如表所示。

 

 

80C51串行口的工作方式1:

方式1是10位数据的异步通信口。TXD为数据发送引脚,RXD为数据接收引脚,传送一帧数据的格式如图所示。其中1位起始位,8位数据位,1位停止位。

  • (1) 方式1输出
  • (2) 方式1输入

  用软件置REN为1时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测到RXD引脚输入电平发生负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位。当RI=0,且SM2=0(或接收到的停止位为1)时,将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向CPU请求中断。

 

定时/计数器的结构与原理

定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器组成。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。

加1计数器输入的计数脉冲有两个来源,一个是由系统的时钟振荡器输出脉冲经12分频后送来;一个是T0或T1引脚输入的外部脉冲源。每来一个脉冲计数器加1,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使TCON中TF0或TF1置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。

可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。

设置为定时器模式时,加1计数器是对内部机器周期计数(1个机器周期等于12个振荡周期,振荡周期也叫时钟周期,时钟周期即晶振的单位时间发出的脉冲数,如12MHZ=12×10的6次方,即每秒发出12000000个脉冲信号,那么发出一个脉冲的时间就是时钟周期,即1/12微秒;如11.0592MHZ=11.0592×10的6次方,即每秒发出11059200个脉冲信号,那么发出一个脉冲的时间就是时钟周期,即1/11.0592微秒)。计数值N乘以机器周期Tcy就是定时时间t 。

定时/计数器的控制

80C51单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD用于设置其工作方式;TCON用于控制其启动和中断申请。

  • 工作方式寄存器TMOD

    工作方式寄存器TMOD用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。其格式如下:

    M1M0:工作方式设置位。定时/计数器有四种工作方式,由M1M0进行设置:

控制寄存器TCON

TCON的高4位用于控制定时/计数器的启动和中断申请。其格式如下:

  • TF1(TCON.7):T1溢出中断请求标志位。T1计数溢出时由硬件自动置TF1为1。CPU响应中断后TF1由硬件自动清0。T1工作时,CPU可随时查询TF1的状态。所以,TF1可用作查询测试的标志。TF1也可以用软件置1或清0,同硬件置1或清0的效果一样。
  • TR1(TCON.6):T1运行控制位。TR1置1时,T1开始工作;TR1置0时,T1停止工作。TR1由软件置1或清0。所以,用软件可控制定时/计数器的启动与停止。
  • TF0(TCON.5):T0溢出中断请求标志位,其功能与TF1类同。
  • TR0(TCON.4):T0运行控制位,其功能与TR1类同。

定时器1的工作方式2

方式2为自动重装初值的8位计数方式。

计数个数与计数初值的关系为:X = 2^8 - N

其中:X为要装的初值 N为要定时/记数的次数。

注:工作方式2特别适合于用作较精确的脉冲信号发生器。所以在进行串口通信时一般选用定时器1工作在方式2 这种经典模式。

  程序:

/*51单片机采用中断方式的串口通信程序分析:
接收数据时 等待中断->然后在中断中接收数据
发送数据时 发送数据->等待中断->然后在中断中发送数据
具体步骤如下:
确定T1的工作方式(编程TMOD寄存器);
计算T1的初值,装载TH1、TL1;
启动T1(编程TCON中的TR1位);
确定串行口控制(编程SCON寄存器);
串行口在中断方式工作时,要进行中断设置(编程IE、IP寄存器)。
*/

#include <reg52.h>
#define uchar unsigned char

uchar Temp,RIflag,TIflag;

//串口初始化函数

void serialportinit() {

    TMOD=0x20;//设置定时器1为工作方式2 8位自动重装载 作用是产生波特率
    TH1=0xfd;//设置波特率位9600bps
    TL1=0xfd;
    TR1=1;//开启定时器1

    //设置串口工作在方式1
    //方式1: 8位异步收发 波特率可变(由定时器控制) 收发一帧的数据为10位 一个起始位(0)8个数据位 1个停止位(1)
    //先发送或接收最低位
    SCON=0x50;//等价于 SM0=0; SM1=1; REN=1;

    //SM0=0;
    //SM1=1;
    //REN=1;//允许串行接收位 允许串行口接收数据
    PCON=0x00;//SMOD=0 波特率不加倍

    EA=1;//开总中断
    ES=1;//开串口中断  注意:如果使用查询方式进行串口通信时,要把串口中断ES关闭、
}



//定义数据发送函数
void sentTemp() {

    SBUF=Temp;//把Temp接收的数据再发送到发送缓冲器SBUF中

    //注意:51单片机内部有两个物理上独立的接收、发送缓冲器SBUF(属于特殊功能寄存器) 两个缓冲器共用一个特殊功能寄存器 字节地址(99H?
    while(!TI);//等待从机向主机发送数据完成
    TI=0;//若发送完成 把发送中断标志位软件清0 因为TI必须由软件清零
}

void main() {
    serialportinit();

    while(1) {

        if(RIflag==1) {
            ES=0;//关串口中断
            RIflag=0;//接收标志位清0
            sentTemp();//调用数据发送函数
            ES=1;//开串口中断
        }
    }
}

//串口中断服务函数
void serialportint() interrupt 4 { //串口中断函数

    if(RI) {
        RI=0;//接收中断标志位RI必须由软件清0
        Temp=SBUF;//把接收缓冲器中收到的数据赋值给led
        P1=Temp;//通过开发板监测是否接收到主机发送的数据
        RIflag=1;//接收标志位置1 表示从机接收收据完成
    }
}