串行通信与并行通信

串行通信

​ 串行通信是指 使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。其只需要少数几条线就可以在系统间交换信息,特别适用于计算机与计算机、计算机与外设之间的远距离通信。如下图所示:

串行通信的特点: 传输线少,长距离传送时成本低,且可以利用电话网等现成的设备,但数据的传送控制比并行通信复杂。

并行通信

并行通信通常是将数据字节的各位用多条数据线同时进行传送,通常是 8 位、16 位、32 位等数据一起传输。如下图所示:

并行通信的特点:控制简单、传输速度快;由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难,抗干扰能力差。

异步通信与同步通信

异步通信

​ 异步通信是指 通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的 时钟尽可能一致

​ 异步通信是以 字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“位间隔”的整数倍。如下图所示:

异步通信的特点:不要求收发双方时钟的严格一致,实现容易,设备开销较小,但每个字符要附加 2 ~ 3 位用于起止位,各帧之间还有间隔, 因此传输效率不高。

同步通信

​ 同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。发送方对接收方的同步可以通过两种方法实现。如下图所示:

单工、半双工与全双工通信

单工通信

单工是指数据传输仅能沿一个方向,不能实现反向传输。如下图所示:

半双工通信

半双工是指数据传输可以沿两个方向,但需要分时进行。如下图所示:

全双工通信

全双工是指数据可以同时进行双向传输。如下图所示:

通信速率

比特率是 每秒钟传输二进制代码的位数,单位是:位/秒( bps)。如每秒钟传送 240 个字符,而每个字符格式包含 10 位(1 个起始位、1 个停止位、8 个数据位),这时的比特率为:

10×240个/秒=2400bps10 \text{位} ×240 \text{个/秒} = 2400 bps

波特率: 它表示每秒钟传输了多少个码元。通信中常用时间间隔相同的符号来表示一个二进制数字,这样的信号称为码元。用 0V 表示数字 05V 表示数字 1,那么 一个码元可以表示两种状态 0 和 1,所以一个码元等于一个二进制比特位,此时波特率的大小与比特率一致;如果在通信传输中,有 0V、 2V、4V 以及 6V 分别表示二进制数 00、 01、 10、 11,那么每个码元可以表示四种状态,即两个二进制比特位,所以码元数是二进制比特位数的一半,这个时候的波特率为比特率的一半。由于很多常见的通信中一个码元都是表示两种状态,所以我们常常直接以 波特率来表示比特率

串口通信介绍

介绍

串口通信(Serial Communication),是指外设和计算机间通过数据信号线、地线等按位进行传输数据的一种通信方式, 属于串行通信方式。串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。

接口标准

串口通信的接口标准有很多,有 RS-232C、 RS-232、 RS-422A、 RS-485 等。常用的是 RS-232 和 RS-485。RS-232 其实是 RS-232C 的改进,原理是一样的。RS-232C 还有一种 9 针的非标准连接器接口,简称 DB9

在串口通信中, 通常我们只使用 2、3、5 三个管脚,即 TXD、RXD、SGND

RS-232C 是用 正负电压 来表示逻辑状态;所以要实现 51 单片机与计算机的串口通信,需要进行 TTL 与 RS-232C 电平转换,通常使用的电平转换芯片是 MAX232

通信协议

RS232 的通信协议比较简单,通常遵循 96-N-8-1 格式

  • “96”表示的是通信波特率为 9600

串口通信中通常使用的是 异步串口通信,即没有时钟线,所以两个设备要通信,必须要保持一致的波特率,当然,波特率常用值还有 4800、 115200 等。。

  • “N”表示的是无校验位

由于串口通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有 奇校验(odd)、偶校验(even)、0 校验(space)、1 校验(mark)以及无校验(noparity)。

  • “8”表示的是数据位数为 8 位

当然数据位数还可以为 5、6、7 位长度

  • “1”表示的是 1 位停止位

串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由 一个逻辑 0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑 1 的数据位表示,只要双方约定一致即可。

串口内部结构

TXD 和 RXD 为单片机 IO 口, TXD 对应的是 P3.1 管脚RXD 对应的是 P3.0 管脚SBUF 是存放数据的,读取也是从这里读

串口相关寄存器

串口控制寄存器 SCON

  • SM0 和 SM1 为工作方式选择位:

  • SM2:多机通信控制位,主要用于方式 2 和方式 3
  • REN:允许串行接收位

由软件置 REN=1,则启动串行口接收数据;若软件置 REN=0,则禁止接收。

  • TB8:在方式 2 或方式 3 中,是发送数据的第 9 位,可以用软件规定其作用, 在方式 0 和方式 1 中,该位未用到
  • RB8:在方式 2 或方式 3 中,是接收到数据的第 9 位,作为奇偶校验位或地址帧/数据帧的标志位,在方式 1 时,若 SM2=0,则 RB8 是接收到的停止位
  • TI:发送中断标志位

在方式 0 时,当串行发送第 8 位数据结束时,或在其它方式,串行发送停止位的开始时,由内部硬件使 TI 置 1,向 CPU 发中断请。在中断服务程序中,必须用软件将其清 0, 取消此中断申请

  • RI:接收中断标志位

在方式 0 时,当串行接收第 8 位数据结束时,或在其它方式,串行接收停止位的中间时,由内部硬件使 RI 置 1,向 CPU 发中断申请。也必须在中断服务程序中,用软件将其清 0, 取消此中断申请

电源控制寄存器 PCON

SMOD:波特率倍增位。在串口方式 1、方式 2、方式 3 时,波特率与 SMOD 有关,当 SMOD=1 时,波特率提高一倍。复位时,SMOD=0

串口工作方式

方式 0

方式 0 时,串行口为 同步移位寄存器的输入输出方式。主要用于扩展并行输入或输出口。数据由 RXD(P3.0)引脚 输入或输出,同步移位脉冲由 TXD(P3.1)引脚 输出。发送和接收均为 8 位数据,低位在先,高位在后。波特率固定为

fosc/12fosc/12

对应的输入输出时序图如下所示:

  • 方式 0 输出

  • 方式 0 输入

方式 1

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

对应的输入输出时序图如下所示:

  • 方式 1 输出

  • 方式 1 输入

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

方式 2 和方式 3

方式 2 或方式 3 时为 11 位数据的 异步通信口。TXD 为数据发送引脚,RXD 为数据接收引脚。其数据格式如下所示:

对应的输入输出时序图如下所示:

  • 方式 2、方式 3 输出

发送开始时,先把 起始位 0 输出到 TXD 引脚,然后发送移位寄存器的输出位(D0)到 TXD 引脚。每一个移位脉冲都使输出移位寄存器的各位右移一位,并由 TXD 引脚输出。第一次移位时,停止位“1”移入输出移位寄存器的第 9 位上,以后每次移位,左边都移入 0。当停止位移至输出位时,左边其余位全为 0,检测电路检测到这一条件时,使控制电路进行最后一次移位,并置 TI=1,向 CPU请求中断。

  • 方式 2、方式 3 输入

接收时,数据从右边移入输入移位寄存器,在起始位 0 移到最左边时,控制电路进行最后一次移位。当 RI=0,且 SM2=0(或接收到的第 9 位数据为 1)时,接收到的数据装入接收缓冲器 SBUF 和 RB8(接收数据的第 9 位),置 RI=1,向 CPU 请求中断。如果条件不满足,则数据丢失,且不置位 RI,继续搜索 RXD 引脚的负跳变

串口的使用方法

如何计算波特率

方式0的波特率=fosc/12\text{方式0的波特率} = fosc/12

方式2的波特率=(2SMOD/64)×fosc\text{方式2的波特率} =(2^{SMOD}/64)\times fosc

方式1的波特率=(2SMOD/32)×(T1 溢出率)\text{方式1的波特率} =(2^{SMOD}/32)\times\text{(T1 溢出率)}

方式3的波特率=(2SMOD/32)×(T1 溢出率)\text{方式3的波特率} =(2^{SMOD}/32)\times\text{(T1 溢出率)}

其中 T1 溢出率 =

fosc/(12×(256(TH1)))fosc /(12×(256 - (TH1)))

也可以用小工具自动生成波特率。在做串口通信实验时, 一定要确认外部晶振是否是 11.0592M。因为当使用 12M 晶振时,波特率误差有 6.98%,会导致通信过程中出现乱码等错误信息。

串口初始化步骤

如何使用串口,大家可以按照以下几个步骤配置。

  • ① 确定 T1 的工作方式(TMOD 寄存器)
  • ② 确定串口工作方式(SCON 寄存器)
  • ③ 计算 T1 的初值(设定波特率),装载 TH1、TL1
  • ④ 启动 T1(TCON 中的 TR1 位)
  • ⑤ 如果使用中断,需开启串口中断控制位(IE 寄存器)
void uart_init(u8 baud)
{
TMOD|=0X20; //设置计数器工作方式 2
SCON=0X50; //设置为工作方式 1
PCON=0X80; //波特率加倍
TH1=baud; //计数器初始值设置
TL1=baud;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
//在主函数中调用该函数并传入OXFA 值即可
uart_init(0XFA);//波特率为 9600

代码:

# include "reg52.h"

typedef unsigned char u8;
typedef unsigned int u16;

void uart_init(u8 baud)
{
	TMOD|=0x20; //设置计数器工作方式2
	SCON=0x50; //设置为工作方式1
	PCON=0x80; //波特率加倍
	TH1=baud; //计数器初始值设置
	TL1=baud;
	ES=1; //打开接收中断
	EA=1; //打开总中断
	TR1=1;//打开计数器
}

void main()
{
	uart_init(0xFA);//波特率为9600
	while(1)
	{

	}
}
void uart() interrupt 4 //串口通信中断号
{
	u8 rec_data;
	RI=0; //清除接收中断标志位
	rec_data=SBUF; //存储接收的数据
	SBUF=rec_data; //将接收的数据放入到发送寄存器
	while(!TI); //等待发送数据完成,数据完成会变成1然后非一下就是0则退出循环
	TI=0; //清除发送完成标志位
}