uart串口中断会占用cpu吗_单片机:串口通信知识详解(下)

前文回顾↓↓↓

单片机:串口通信知识详解(上)

c3d398ba6b417c093ddff09e4820b4f4.gif

我们接着上节的内容来给讲一下51单片机串口的使用方法,好的,直接开始我们今天的内容。

串行口结构

串行口的结构,如图1所示。

4db63e67fa748cdf5eb6d9ff1aba0c2a.png

图1 串行口的结构

这里有两个物理上独立的接收、发送寄存器SBUF,它们占用同一内存(99H)。

在程序逻辑上,SBUF只有一个,既代表发送寄存器,又代表接收寄存器,具有同一单元地址,但在物理结构上,则有两个完全独立的SBUF,一个发送寄存器SBUF和一个接收寄存器SBUF。如果CPU写SBUF,数据会被存入发送寄存器准备发送;如果CPU读SBUF,则读入的数据一定来自接收寄存器SBUF。(a=SBUF;SBUF=a;)。

串口相关的寄存器

接下来讲一下与串口有关的寄存器。

1 SCON寄存器

首先是SCON寄存器。

22d2a8a0e8235d97c4cb98b041a820f7.png

这里我简单说一下每一位的功能。

SM0:当PCON寄存器中SMOD0位为1时,该位用于帧错误检测。为0时,该位与SM1一起控制串口通信的工作方式。(这里一般用于控制工作方式)

SM0、SM1控制串口通信工作方式,如图2所示。

0d43568a075a8dae2db923068bfc06d7.png

图2 SM0、SM1控制串口通信工作方式

这里的SYSclk是晶振频率,方式0和方式2是比波特率固定的,具体大家可以自己算一下。方式1和方式3通过配置定时器1来改变波特率,SMOD是PCON寄存器中可以配置的,配置为1时可以将波特率提升1倍,后边会再介绍。

我们一般使用方式1,发送/接收8位数据,波特率可变。

SM2:多机通信控制位,主要用在方式2和方式3,为0时双机通信,为1时多机通信。

REN:串行接收允许位,REN=0时禁止接收,REN=1时允许接收

TB8/TR8:在方式2和方式3时分别用于存放发送/接收的第9位数据。

TI:发送中断请求标志位,数据发送结束时,标志位被自动置1并向CPU请求中断,需通过程序置0。

RI:接收中断请求标志位,数据接收结束时,标志位被自动置1并向CPU请求中断,需通过程序置0。

2 PCON寄存器

接下来是PCON寄存器。

093273195852932ce48dcb76090e7a59.png

SMOD:波特率选择位,SMOD=1时,工作方式1、2、3中波特率加倍。

3 IE寄存器

最后还是我们熟悉的IE寄存器。

e3dea5c5ebfa1c7588d48b270bbdc31c.png

这里与串口相关的位有:

  • EA,CPU总中断允许控制位,前边多次介绍过的,不多说了。

  • ES,串行口中断允许位,ES=1,允许串行口中断;ES=0,禁止串行口中断。

我们配置好串口工作模式、打开串口中断后,CPU接收到串口的中断请求时就会相应串口中断执行串口中断服务函数。

波特率计算

当串口工作在方式1时,波特率由定时器1的溢出率决定,此时定时器1通常选用定时器初值自动重装的工作模式(工作模式2,TMOD=0x20;)此时仅用低8位来计数,溢出以后高8位的存放的数据会放入低8位中重新计时,无需再通过程序重放初值。

因此,

波特率=(2^SMOD/32)*(单片机时钟频率/(256-X))

X是初值。

在实际应用中,通常是选确定波特率,再根据波特率算出TI的定时初值,因此:

X=256-(2^SMOD/32)*(单片机时钟频率/波特率)

举例

波特率为9600时,求T1存放的初值(晶振频率为11.0592MHZ):

SMOD=0

(2^SMOD/32)=1/32

(单片机时钟频率/波特率)=((11.0592MHZ/12)/9600)=96

X=253

因此T1存放初值为253(TH1=0xfd;TL1=0xfd;)。

寄存器配置步骤

在使用串口前,我们要把上边讲到的寄存器进行配置,设定好工作方式。

  1. 设置T1工作方式(编程TMOD寄存器);

  2. 计算T1的初值,装载TH1、TL1;

  3. 启动T1(编程TCON中的TR1位);

  4. 确定串行口控制(编程SCON寄存器);

  5. 如需串口在中断方式工作时,要进行中断设置编程IE寄存器。

串口初始化

好的,现在用代码来对串口进行初始化:

void uart_init()

{

    TMOD = 0x20;   //T1工作模式2  8位自动重装

    TH1 = 0xfd;

    TL1 = 0xfd;  //比特率9600

    TR1 = 1;  //启动T1定时器

    SM0 = 0;

    SM1 = 1;   //串口工作方式1 10位异步

    REN = 1;  //串口允许接收

    EA  = 1;  //开总中断

    ES  = 1;  //串口中断打开

}

←左右滑动,查看全部代码→

举个栗子

下边用一个例子来带大家了解一下。

串口收发数据,设置波特率为9600,把接收到的数据用P1端口的LED灯以二进制的形式显示(灭为0,亮为1),在把接收到的数据加1并发出。

#include 

#define u8 unsigned char

#define u16  unsigned int

u8 num;    //用于存放接收/发送数据

void delay(u16 z)

{

  u16 x,y;

  for(x = z; x > 0; x--)

    for(y = 114; y > 0 ; y--);

}

void UART_init()

{

  TMOD = 0x20;    //T1工作模式2  8位自动重装

  TH1 = 0xfd;

  TL1 = 0xfd;    //比特率9600

  TR1 = 1;    //启动T1定时器

  SM0 = 0;  

  SM1 = 1;    //串口工作方式1 10位异步

  REN = 1;    //串口允许接收

  EA  = 1;    //开总中断

  ES  = 1;    //串口中断打开

}

void main()

{

  UART_init(); //串口初始化

  while(1);

}

void UART() interrupt 4

{

  if(RI)    //检测是否接收完成

  {

    num = SBUF;    //采集接收到的数据

    P1 = SBUF;

    num++;    //把接收的数据加1并发送

    RI = 0;

    SBUF = num;

    while(!TI);    //等待发送完成

    TI = 0;

  }

}

←左右滑动,查看全部代码→

当我们使用串口发送字符串时,可以直接添加头文件“#include ”,这个就是我们学习C语言时常用到了,我们可以直接调用其中的“printf”、“putchar”等函数来通过串口发送数据,这里要注意的是:在发送前要通过程序来把“TI”置1,因为在这些函数开头就会通过“while(!TI);”来判断数据是否发送完成。

/*********************************************

void putchar (unsigned char sbyte)

{

    while(!TI);    //等待数据发送完成

    //如果没有置1,程序会卡在这里

    SBUF = sbyte;

}

*********************************************/

好的,现在用程序来实现一下:

#include 

#define u8 unsigned char

#define u16  unsigned int

u8 num;    //用于存放接收/发送数据

void Delay(u16 n)

{

  u8 j;

  while(n--)

    for(j=113;j>0;j--);

}

void UART_init()

{

  TMOD = 0x20;    //T1工作模式2  8位自动重装

  TH1 = 0xfd;

  TL1 = 0xfd;    //比特率9600

  TR1 = 1;    //启动T1定时器

  SM0 = 0;

  SM1 = 1;    //串口工作方式1 10位异步

}//这里没有使用中断和接收功能,可以不配置

void main()

{

  UART_init();    //串口初始化

  while(1)

  {

    TI = 1;

    printf("欢迎大家使用串口通信!\n");

    while(!TI);    //等待发送完成

    TI = 0;

    Delay(1000);    //每隔1S发送一次

  }

}

←左右滑动,查看全部代码→

调试串口时,可以使用“STC-ISP(V6.85)”(其它版本应该也可以)。

8bda88ba989f0ea5dde09cb2b2235203.png

好的,本节内容就先到这里啦。

▼ 更多蓝桥杯文章 ▼

蓝桥杯·单片机竞赛备赛之串口通信(上)

蓝桥杯·单片机竞赛备赛之定时器

蓝桥杯·单片机竞赛备赛之外部中断

蓝桥杯·单片机竞赛备赛之机械按键

b0e2ce23267d27c450381574adac16df.png dca540e8e411767c12989a47b9a14688.png 扫码入群 扫码添加管理员微信

加入“电子产品世界”粉丝交流群

↓↓↓↓点击,查看更多新闻

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值