首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

串口通信-实例9:串口双机通信

序:在嵌入式产品里,串口常用于程序调试、程序烧录和模块通信接口。本例首先介绍单片机串口的结构和原理,然后通过一个双机通信实例说明串口通信的应用编程。

一、实例目的

通过本实例,我们应:

1. 了解串口与并口通信的区别。

2. 掌握51单片机的串口结构与原理。

3. 掌握51单片机的串口编程。

二、串口与并口通信

在数字世界里,信息由0和1编码组成。一串数据对于不同模块,意义也不同。犹如点头在大多数国家表示YES,摇头表示NO,但在某些国家如保加利亚、斯里兰卡等正好相反。也就是说,在数字世界里,信息表示的意义,是由解码器解释的。一般来说,编码器与解码器都是专用的,是基于应用的。

那么,信息的传递,是如何实现的呢?通俗地说,信息是由0和1组成的一串数据(二进制流,每位(0或1)称为 比特(bit))。传递信息就是按照顺序向对端发送逐位比特或多位比特。逐位发送称为串行通信,多位同时发送称为并行通信,见图1。对于串行通信,发送比特流顺序有先发最高位(MSB First)和先发最低位(LSB First)。在电气上(物理层),一般用低电平表示0,高电平表示1。

图1 并行通信与串行通信

串口传输数据的基本单位为帧(Frame),一帧包括帧头、有效数据、校验位、帧尾等。有效数据称为有效载荷(Payload),帧头、校验位、帧尾等称为开销(overhead)。

51串口的帧有8位、10位和11位三种,见图2,先传最低位(MSB First)。

图2 51单片机的帧结构

三、51单片机串口结构

51单片机有一个全双工的串行接口,简称串口。图3给出了51单片机的串口内部结构图。

图3 51单片机串口内部结构框图

串口引脚有TXD(串行数据发送管脚)和RXD(串行数据接收管脚)。串口主要由发送缓冲SBUF、接收缓冲SBUF、移位寄存器、波特率发生器组成。相关模块的功能说明如下:

发送缓冲SBUF:把字节数据写到SBUF,串口自动逐位将数据通过TXD管脚输出,发送完毕后置TI中断标志位为1。如果串口中断允许,则触发串口中断处理函数。

接收缓冲SBUF:串口接收到一帧数据后,将8位有效载荷存到SBUF,并置RI中断标志位为1。如果串口中断允许,则触发串口中断处理函数。

移位寄存器:在波特率节拍控制下,采样RXD引脚上的电平,将接收到的0/1存到SBUF。

波特率发生器:串口数据发送和数据接收均在时钟的控制下进行,每秒发送的比特数称为波特率(baud rate),单位为bps。常见的波特率有2400bps,4800bps,9600bps,115200bps。波特率越高,数据传输速率越快。

注意:串口是异步通信,收发双方独立使用自己的时钟,要求双方波特率必须设置一致。一般来说,波特率相差不能超过2%,否则无法正确发送/收到数据,导致出现乱码。

RI/TI:接收/发送中断标志位。

RI用于指示是否接收到数据,1表示接收到一帧数据,如果串口中断是使能的,则触发串口中断。当接收到数据时,必须及时清零RI,否则无法接收到下一帧数据(自动丢弃)。

TI用于指示一帧数据是否发送完成,1表示一帧数据已经发送完毕,如果串口中断是使能的,则触发串口中断。

RI和TI均需软件清零。采用串口中断编程时,RI和TI用于判断是接收数据还是发送数据引起的串口中断。

三、51单片机串口编程接口

串口相关的寄存器包括:

SBUF——串行口数据缓冲器(99H)

共两个:一个发送寄存器SBUF,一个接收SBUF,二者共用一个地址99H。

写数据到SBUF,访问的是发送寄存器SBUF;读SBUF,访问的是接收SBUF。

SCON——串行口控制寄存器(98H)。

PCON——电源控制寄存器(87H)。PCON.SMOD是波特率倍增控制位。

IE ——中断控制寄存器。ES是串口中断允许控制位。

下面主要介绍SCON寄存器。

图4 SCON寄存器定义

SCON字节地址为98H,支持按位寻址。

SM0和SM1用于选择串口的工作方式。

对于串口双机通信,一般采用模式1或模式3。

例:设串行口工作在方式1,允许接收,则C51语句为:

SCON = 0x50;

SM2用于多机通信。SM2=1,从机处于多机模式。

REN为串口接收允许控制位,1有效。

TB8为11帧里发送的第9位数据,如奇偶校验位、多机通信地址/数据指示位等,RB9为11帧里接收到第9位数据。

RI/TI分别为接收中断标志和发送中断标志。

PCON——电源控制寄存器(87H)。PCON.SMOD是波特率倍增控制位。

四、51单片机串口应用编程

串行口的初始化编程:

设置串行口的工作方式( SCON :SM0、SM1 )。

2. 对于工作方式2或3,应根据需要在TB8中写入待发送的第9位数据(地址为1,数据为0)。

若选定的工作方式不是方式0,还需设定接收/发送的波特率。设定SMOD状态,以控制波特率是否加倍。

4. 若选定工作方式1或3,则应对定时器T1进行初始化以设定其溢出率。

(5)串行通信编程有两种方式:查询方式和中断方式,这两种方式中发送和接收数据后都用注意清TI和RI。一般来说,使用查询方式发生数据,使用中断方式接收串口数据。

下面以双机通信为例,介绍单片机的串口应用编程。设双机通信电路图如下所示。主机P1.0接一个独立按键K0,从机P1.0接一个红色LED。要求基于串口通信,实现通过主机K0控制从机的LED的亮灭。假设晶振频率为12MHz,波特率设置为4800bps。

图5 双机通信仿真电路图

编程思路:主机用一个标志位flag存储LED的状态,当按键K0闭合,更新flag状态,并将更新的flag发送到从机。从机根据主机发来的flag控制灯。flag为1时,控制LED亮,flag为0时,控制LED灭。初始化时,flag为0。

图6 主机流程图

图6 从机流程图

利用51波特率初值计算小工具,计算T1的初值。根据已知,晶振频率为12MHz,取T1为方式2(8位初值自动重装定时器),波特率倍增,则T1初值为0xF3。

图7 T1初值计算(fosc=12MHz, 波特率=4800bps)

注意:在使用串口的应用中,单片机晶振通常选择11.0592MHz,使常见波特率对应的T1初值没有误差。

编程步骤:

运行Keil,新建两个工程,MasterMCU和SlaveMCU,分别对应主机和从机程序。

编写相应程序。MasterMCU.c为主机程序,SlaveMCU.c为从机程序,代码如下。

//MasterMCU.c

#include

sbit key0 = P1^0; //K0接口为P1.0

bit flag = 0; //从机LED使能标志位,初始化为0

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

*函数:delayMS

*功能:ms级延时函数@12MHz主频

*参数:ms:unsinged int,延时时间,单位:ms

*返回值:无

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

void delayMS(unsigned int ms)

{

unsigned int i,j;

for(i=0;i

for(j=0;j

}

void main() //主程序

{

//初始化UART

SCON = 0x40; //设置串口为工作方式1,8位/帧,REN=0,不接收

PCON = 0x80; //PCON.SMOD=1,波特率倍增

TCON = 0x20; //设置T1为方式2 定时器

TH1 = 0xF3; //T1初值,串口波特率4800bps@12MHz

TL1 = 0xF3;

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

while(1)

{

//按键判断

if(key0 ==0) //按键闭合

{

delayMS(10); //软件去抖动

if(key0==0) //确认按键闭合

{

flag = ~flag; //LED使能位取反

while(key0==0); //等待按键松开

SBUF = flag; //通过串口发送flag到从机

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

TI = 0; //发送完成,软件清理TI

}

}

}

}

//SlaveMCU.c

#include

sbit led_red = P1^0; //LED接口为P1.0

bit flag = 0; //LED使能标志位,初始化为0

void main() //主程序

{

//初始化UART

SCON = 0x50; //设置串口为工作方式1,8位/帧,REN=1,允许接收

TCON = 0x20; //设置T1为方式2 定时器

PCON = 0x80; //PCON.SMOD=1,波特率倍增

EA = 1; //总中断使能

ES = 1; //串口中断使能

TH1 = 0xF3; //T1初值,串口波特率4800bps@12MHz

TL1 = 0xF3;

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

led_red = 1; //初始化LED灭

while(1); //主循环

}

//串口中断处理函数

//中断号为4

void ISR_Serial() interrupt 4

{

if(RI==1) //由接收引起串口中断,取数

{

led_red = 1;

flag = SBUF; //取flag

led_red = ~flag; // flag为1时,输出0,点亮LED;flag为0时,输出1,熄灭LED

RI = 0; //软件清零

}

}

分别生成主机和从机的.hex程序。

4.在proteus ISIS仿真电路图里,关联对应的.hex。

仿真验证,仿真结果如图8所示。

图8 串口编程

五、小结

本实例介绍了串口的结构与原理,通过一个简单实例介绍了串口的应用编程。在串口编程时,注意串口的初始化,特别是使用串口中断函数时,ES和EA别忘了置1。此外,不管采用软件查询法还是串口中断法,必须软件清零RI和TI。在下一个串口实例,我们将学习串口与PC通信编程。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180608G1C3ST00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券