目录
- 1.通信的基本概念
-
- 1.1串行通信与并行通信
-
- [1.1.1 串行通信](#1.1.1 串行通信)
- [1.1.2 并行通信](#1.1.2 并行通信)
- [1.2 异步通信和同步通信](#1.2 异步通信和同步通信)
-
- [1.2.1 异步通信](#1.2.1 异步通信)
- [1.2.2 同步通信](#1.2.2 同步通信)
- [1.3 单工、半双工与全双工通信](#1.3 单工、半双工与全双工通信)
-
- [1.3.1 单工通信](#1.3.1 单工通信)
- [1.3.2 半双工通信](#1.3.2 半双工通信)
- [1.3.3 全双工通信](#1.3.3 全双工通信)
- [1.4 通信速率](#1.4 通信速率)
- 2.51单片机串口介绍
-
- [2.1 串口通信简介](#2.1 串口通信简介)
-
- [2.1.1 接口标准](#2.1.1 接口标准)
- [2.1.2 通信协议](#2.1.2 通信协议)
- 2.1.3串口通信内部结构
- [2.2 串口相关寄存器](#2.2 串口相关寄存器)
-
- [2.2.1 串口控制寄存器SCON](#2.2.1 串口控制寄存器SCON)
- [2.2.2 电源控制寄存器PCON](#2.2.2 电源控制寄存器PCON)
- [2.3 串口工作方式](#2.3 串口工作方式)
-
- [2.3.1 方式0](#2.3.1 方式0)
- [2.3.2 方式1](#2.3.2 方式1)
- [2.3.3 方式2和方式3](#2.3.3 方式2和方式3)
- [2.4 串口的使用方法](#2.4 串口的使用方法)
-
- [2.4.1 如何计算波特率](#2.4.1 如何计算波特率)
- [2.4.2 串口的使用](#2.4.2 串口的使用)
- 3.硬件设计
- [4. 软件设计](#4. 软件设计)
1.通信的基本概念
按照数据的传送方式可以分位:串行通信和并行通信。
按照数据同步方式可以分为:同步通信和异步通信。
按照数据传输方向可分为:单工通信,半双工通信,全双工通信。
1.1串行通信与并行通信
1.1.1 串行通信

使用一条数据线,进行传输,将数据字节分成一位一位的形式。先传输低位,后传输高位,从低位到高位,这样一位一位的将一个字节八位传输过去。
特点:串行通信传输线少,长距离传输时成本低,且可以利用电话网等现成设备,但数据的传输控制比并行通信复杂。
1.1.2 并行通信

要想传送一个数据,需要八根线,每一根线传输一位数据,
特点:控制简单,传输速度快,但由于传输线比较多,长距离传输时成本高,接,收方存在困难,抗干扰能力差。
1.2 异步通信和同步通信
1.2.1 异步通信

异步通信要求:发送设备与接收设备的时钟尽可能保持一致,因为如果发送设备与接收设备的时钟不是一致的话,那么发送设备发送的数据在接收设备接收的数据可能是一个错误的可能是一个乱码。
异步通信是以字符为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的。
比如第一次传输的是01001第二次传输的是0101001001,这两个传输的字符间隔时间是任意的。
但是同一个字符内的各个位之间存在位间隔的整数倍。
就比如第二个数据0101001001,各个位之间间隔的距离是整数倍,第一个数据与第二个间隔是2,第二个与第三个间隔是4,这样的,存在一个整数倍的间隔的距离。

异步通信传输一个字符的格式,开始是起始位,然后是8个数据位,后面是一个校验位,停止位,一共就是11位
特点:不要求收发方时钟严格一致,就比如说,发送设备的频率是11.0592M,并不会一定要求接收数据的设备的时钟也是11.0592M,有一点点误差也是允许的,实现容易,设备开销小,但是每一个字符附加2~3位,用于起始位,校验位,停止位,各帧之间还有间隔,因此传输数据效率不是很高。因为数据与数据之间存在间隙,这个间隙的时间是任意的,因此传输的效率就不会很高。
1.2.2 同步通信

同步通信时,要建立发送方时钟对接收方时钟的直接控制,让双方的时钟完全相同,进行同步。传输数据的位之间的距离均为"位间隔"的整数倍,同时传输的字符间不留间隙,就是保持同步的关系。
以上两张图是外同步和自同步,外同步是发送方对接收方时钟的控制
1.3 单工、半双工与全双工通信
1.3.1 单工通信

单工通信是指:数据传输仅能沿一个方向,不能实现反向传输。
1.3.2 半双工通信

半双工通信是指:数据传输传输可以沿两个方向,但是需要分时进行。就是在发送设备对接收设备发送数据是一个时间,接收设备对发送设备发送数据又是一个时间,两次发送的数据时间不同。
1.3.3 全双工通信

全双工通信指:数据可以同时进行双向传输。就是发送的数据同时可以接收数据,同时进行的。
1.4 通信速率
通信速率也叫比特率。
比特率是每秒传输二进制的位数,单位:位/秒(bps)
例如每秒传输240个字符。
一个字符的格式:起始位,八位数据,停止位
那么比特率就是 240 * 10 /s就是2400bps
比特率是每秒传输的多少位,而波特率是每秒传输的是码元。在数字通信中常常用时间间隔相同的符号来表示一个二进制数字,这样的时间间隔内的信号称为(二进制)码元。
比如在常见的中,0v表示0,5v表示1,一个码元可以表示两种状态,0和1。
2.51单片机串口介绍
2.1 串口通信简介
串口通信是指计算机与外接设备的接口
如:数据信号线,地线
串口:接口标准。
接口标准如:RS-232c,RS-232,RS-42A,RS-485
常用的接口RS-232,RS-485
RS-232c定义是"数据终端设备(DTE)和数据通讯设备(DCE)之间物理接口标准。
RS-232c接口标准规定使用25帧的连接器简称为DB25
2.1.1 接口标准

左边是DB25接口标准连接图,右边是DB9接口连接图

接口有公头和母头之分,其中带针状的是公头,带孔状的是母头。

这里带括号的是DB9的一个脚位,没有带括号的是DB25的一个脚位。通常中用到的脚位是,RXD(发送数据),TXD(接收数据),GND,在TXD和RXD数据线上的数据逻辑"1"的电压范围是-3~15伏,逻辑"0"的电压范围是3 ~ 15伏的电压。在单片机中通常是TTL的一个电平,而逻辑1和逻辑0电平是232的一个电平,所以在使用单片机的时候TTL的一个电平要跟232的电平进行转换的化,那么需要一个转换的东西,可以通过MAX232的一个转换芯片进行转换,这样就可以实现一个通信了。

在串口通信的时候还需要注意的一件事情,串口发送方的发送引脚要连接接收方的接收引脚上,同样的接收方的发送引脚要连接发送方的接收引脚,所以这是一个交叉连接,并且两个设备还需要共用一个GND。
2.1.2 通信协议
RS232的通信协议比较简单,通常遵循96-N-8-1格式。
96表示9600波特率(bps),每秒传输数据的位数。
在串口通信中,两个设备通信必须保证波特率一致,就比如发送方使用的波特率的值是9600,同样的接收方使用的波特率也是9600。
N表示无校验位。
而校验方法可以有奇校验,偶校验,0校验,通常使用的校验方法就是无校验,就是N表示
8表示传输的数据位,通常是8位
传输数据位有5位,6位,8位,通常使用的是8位,表示一个字节
1表示停止位
串口通信的一个数据包从起始信号开始到停止信号结束,数据包起始信号同逻辑0表示,数据包的停止位,可以是0.5,1,1.5,2,通常使用的是1个停止位。
2.1.3串口通信内部结构


RXD在单片机中是P3.0引脚,TXD在单片机中是P3.1引脚,SBUF是数据缓存区,要接收数据是读取SBUF中的数据,要发送数据也是将数据存在SBUF中,由对应的寄存器发送出去。
串口通信它是一个异步的通信,它有一个波特率,这个波特率是通过TH1和TL1产生的,TH1和TL1是定时器1的一个功能,当使用串口通信的时候也需要配置TH1和TL1的工作方式,通常情况下工作在方式2(自动重载模式)。
SMOD通过对应的寄存器控制它的倍频,如果不倍频开关打到1状态,如果是倍频则开关打到0的位置上,对应的值除以2, 在传送到我们对应的接收和发送控制器中,接收和传输控制器,是通过SBUF控制控制门和移位寄存器。
如果是接收的话,通过移位寄存器,接收到SBUF中,然后接收寄存器将对应的RI设置1,然后接收中断发送请求执行中断,也就是说当RI或者TI任意一个置1的时候,它就会发送串口中断请求。
如果是发送的话,会通过SBUF将数据传输到控制门,由发送控制器控制,通过TXD引脚,发送出去。
2.2 串口相关寄存器
2.2.1 串口控制寄存器SCON


SCON寄存器中有8位,前面两位SM0和SM1用来确定串口的工作方式,它有四种方式,通常是使用方式1,。
SM2设置1的时候:
SM2是用来多机通信控制位,比如说,一个主设备,它可以连接多个设备,它是依靠SM2来控制,使用多机控制,一般是使用方式2和方式3,这两种方式,当SM2设置1的时候,可以利用收到的数据RB8,这个RB8位是否激活RI,当激活了RI那就是开启了接收数据的中断了,当RB8等于0时候,表示不激活RI,收到的信息就丢弃,当RB8等于1的时候,收到的信息,就会进入到SBUF中去,并且激活RI,从而接收这个数据,这就是通过SM2来决定RB8是否激活。
比如当有一个主设备,然后总线上连接了两个设备,A设备和B设备,当B设备配置的RB8设置0,当A设备配置的RB8设置1的,当RB8为1的这个设备就可以读取SBUF里面的数据,RB8等于0的设备就不会读取主机发送的数据,那表示主机发送的数据被A设备读取到了,B设备没有读取到。
当SM2设置0的时候:
不论收到的RB8等于0还是等于1, 均可以使用收到的数据进入到SBUF,这时候就是使用串口方式1,不进行多机通信的时候,可以将SM2设置为0。
REN是允许接收位, 由软件置1,设置1后由串行口接收数据,,如果REN设置0,就禁止接收数据,在串口通信的时候,是需要数据接收的,通常情况下是设置1的,就是允许接收数据。
TB8和RB8是工作在方式2和方式3的时候,是用来发送数据的第九位,可以用作数据的奇偶校验位,在多机通信的时候用作地址帧和数据帧的一个标志位,在方式0和方式1的时候,TB8和RB8是没有用到的,因为它是一个8位的数据,所以我们在串口通信的时候,TB8和RB8不管它。
TI是发送数据中断的标志位,在方式0的时候,当串行发送第八位数据结束的时候,或者串行发送停止位的时候,内部硬件就会自动置1, 当TI设置1的时候,就会向中断发送请求,在中断服务软件中,需要用软件清零,来取消中断申请,等待下一次中断。
RI是接收数据中断的标志位,在方式0的时候,当串行接收到第八位数据结束的时候,或者串行接收停止位的时候,由内部硬件设置1,当RI设置1的时候,就会向CPU发送中断请求,在中断服务软件中,需要用软件清零,用来取消中断申请,等待下一次中断申请。
所以我们在使用SCON寄存中,通常将SM0和SM1, 使用方式1,SM0设置0,SM1设置1,SM2通常设置0, 因为没有使用多机通信,或者说没有 使用9位数据,REN中,我们需要允许接收数据,通常设置1,TB8和RB8没用到默认设置0,TI和RI是自动完成的,当进入中断的时候才需要软件我们手动设置0,所以我们也可以不管它,默认设置0,这样的话SCON寄存器我们设置的值:01010000
2.2.2 电源控制寄存器PCON

电源寄存器PCON也是8位,当它只是用到了最高位,后面的7位没用用到,这个寄存器主要用来对波特率倍频的选择。

像之前看到的SMOD中里面波特率是否是倍频,如果SMOD等于0的时候,那么它不进行倍频,如果是等于1的时候,它就会进行倍频,在方式1,方式2,方式3,波特率与这个倍频有关,当SMOD设置1的时候,波特率提高了1倍,复位的时候SMOD等于0,向如果是在方式1的时候,可以对倍频进行设置,如果是倍频需要将SMOD设置1,如果不需要倍频则将SMOD设置0。
2.3 串口工作方式
2.3.1 方式0

同步移位寄存器输入输出方式,主要用于扩展并行输入输出口,数据主要有RXD也就是P3.0这个引脚进行输入的,同步移位脉冲是由TXD也就是P3.1这个引脚进行输出的,发送和接收均为八位数据,低位在前,高位在后,波特率固定是foc/12,foc主要是外部晶振的频率。
方式0输出,写入数据到SBUF中,然后数据发送和接收依靠RXD引脚进行传输的,先从低位到高位,然后按照TXD移位脉冲,一位一位的传输,从D0到D7八位数据,传输完成TI就会置1,也就是中断标志位置1,如果我们开启中断,就会进入到中断,中断进入之后需要我们手动清除TI,手动设置0。
方式0输入,也是依靠RXD数据接收的,当吧REN设置1的时候,是一个接收允许,那么数据在TXD移位脉冲情况下,数据会一位一位的进行接收,接收同样是从低位到高位进行接收,接收完成后,RI自动设置1,然后发送中断请求,进入中断函数后,需要我们手动将RI设置0,等待下一次接收。
2.3.2 方式1


TXD是发送数据引脚,RXD接收数据引脚。
传送一帧数据格式:起始位,八位数据,停止位,一共是10位。
输出:当我们吧数据写入到SBUF中,根据TXD发送引脚,首先发送低电平的起始位,然后发送八位数据,发送八位数也是按照从低位到高位的发送,发送完成后,还有一个高电平的停止位,发送完成后,TI由硬件置1,发送中断请求,进入中断后,需要我们手动将TI设置0。
输入:通过RXD进行接收的,在脉冲采样上面一个接收,首先接收一个低电平,然后八位数据,从低位到高位,最后是高电平的停止位,接收完成后,RI由硬件设置1,发送中断请求,进入中断,需要我们手动将RI设置0。
在接收的时候需要将REN设置1,波特率是一个16倍采样。

在RXD引脚下降沿的时候,有效开始接收一帧数据的信息,一帧的信息就是8位数据,输入到移位寄存器的右边, 最终将八位输入移位寄存器的左边,当RI等于0并且SM2等于0,这时候将接收到的前8位数据装到SBUF中,这个过程是单片机内部自动完成的。
2.3.3 方式2和方式3


方式2和方式3工作的时候处于11位的通信。
TXD是发送引脚,RXD是接收引脚。和方式1不同的是它是11位的,它有9位数据。
一帧数据的格式:起始位,9为数据,停止位,一共11位。其中起始位和停止位和方式1类似,不同的区别就是数据多了一位,增加了一位,它是9位,最后第九位数据是,RB8/TB8。

输出:开始时候将起始位,低电平输出到TXD引脚,然后发送移位寄存器从D0到TXD引脚,每一个移位脉冲,右移动一位,并由TXD引脚输出,也就是说从低位一个一个的移位,一直到高位,当停止位移出输出位的时候,左边其余全部为0,并将TI设置1,向CPU发送中断请求。
输入:由于RXD引脚接收数据,根据采用脉冲一位一位的接收,开始接收一个下降沿开始,然后接收对应的数据,如果将SM2设置0,并且RI等于0,接收到的数据会接收到SBUF当中,以及RB8也会装如SBUF当中,RB8是保存的第9位数据,并且接收完成后RI会自动设置1,向CPU发出中断请求,如果条件不满足则数据丢弃。
2.4 串口的使用方法
2.4.1 如何计算波特率
方式0的波特率=fosc/12
方式2的波特率=(2SMOD/64)·fosc
方式1的波特率=(2SMOD/32)·(T1溢出率)
方式3的波特率=(2SMOD/32)·(T1溢出率)
其中T1 溢出率=fosc/{12×[256-(TH1])
方式0波特率是固定的,方式2波特率也是固定的,方式1和方式3的波特率可以更改的,其中我们使用的串口通信通常的是方式1,至于方式0,方式2,方式3很少使用。
方式1的波特率 = 2的SMOD次方 / 32 * T1溢出率,其中T1是定时器的八位重载的一个模式。

当晶振频率是11.0592MHZ,串口方式1,定时器1方式2,波特率是9600分别计算倍频和不倍频举例:

0XFA的十进制是250,0XFD的十进制是253。
2.4.2 串口的使用


①确定T1的工作方式(TMOD寄存器);
使用定时器1,工作方式2,八位自动重载模式。



②确定串口工作方式(SCON寄存器);
使用方式1,还需要对REN设置1,允许接收。


③计算T1的初值(设定波特率),装载TH1、TL1;
通过TL1进行计数,TH1进行重载。利用计算波特率公式计算初值,然后将初始值传递到TH1和TL1当中。
例如当我们使用波特率9600,使用倍频,计算结果是0xFA,然后TH1 = 0xFA,TL1 = 0xFA。
0XFA的十进制是250,重新装载的意思是,每次TL1从,250开始,一直计数到255,然后加1后就会溢出,此时通过TH1对TL1重新赋值,此时TL1又变成250,这样不断循环,不断装载,当TL1溢出后,通过TH1重新对TL1赋予新的值TL1又变成250。

④启动T1(TCON中的TR1位);

⑤如果使用中断,需开启串口中断控制位(IE寄存器)
EA 设置1。总中断开关开启
ES设置1。串口中断开关开启
串口初始化步骤
c
void uart_init(u8 baud) //参数用来传递波特率的值
{
TMOD|=0X20; //设置计数器工作方式2
SCON=0X50; //设置为工作方式1
PCON=0X80; //波特率加倍
THl=baud; //计数器初始值设置
TLl=baud;
ES=1; //打开接收中断
EA=l; //打开总中断
TR1=1: //打开计数器
}
3.硬件设计

RS232逻辑电平-3V~15V 还有3V ~ 15V需要电平转换芯片MAX232芯片,但是在图中并没有看到,而是使用了USB转换芯片,CH340芯片,跟串口进行转换。
4. 软件设计
实现的功能是:当串口助手发送数据给单片机,单片机原封不动转发给串口助手显示。
c
#include <reg51.h>
#define u16 int
#define u8 char
sbit LED = P2^0;
void delay_50ms(u16 us) {
while(us--);
}
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 = 0;
RI = 0;
rec_data = SBUF;
SBUF = rec_data;
while(!TI);
TI = 0;
}

工作原理
首先通过PC端向单片机发送数据,通过移位寄存器移位接收数据,最终当数据接收完成,数据会存储在SBUF中,同时RI会置1,进入中断,需要手动清零。
通过变量rec_data = SBUF取出PC端发送过来的数据
当需要从单片机发送数据到PC端,SBUF = rec_data,将接收过来的数据重新赋值给SBUF,当数据正在发送过程中TI一直处于0状态,当发送完成TI自动变成1,所以通过while(!TI);这一条语句等待数据发送,当正在发送会一直等待中,当发送完成就会跳出,然后手动将TI设置0,等待下一次发送。