明珠的个人博客

是谁告诉你,你是赤裸的?

0%

串口通信

51单片机串口通信

通信简介

通信方式

通信的方式可以分为多种,按照数据传送方式可分为串行通信和并行通信。按照通信的数据同步方式,可分为异同通信和同步通信。按照数据的传输方向又可分为单工、半双工和全双工通信。

串行通信

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

并行通信

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

异步通信

异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。
异步通信是以字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“位间隔”的整数倍。

同步通信

同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。

单工通信

单工是指数据传输仅能沿一个方向,不能实现反向传输。(只能接收数据或只能发送)

半双工通信

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

全双工通信

全双工是指数据可以同时进行双向传输。

半双工通信

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

通信速率

衡量通信性能的一个非常重要的参数就是通信速率,通常以比特率、波特率等来表示。

比特率

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

波特率

每秒钟传输了多少个码元。而码元是通信信号调制的概念,通信中常用时间间隔相同的符号来表示一个二进制数字,这样的信号称为码元。如常见的通信传输中,用0V 表示数字0,5V表示数字 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 接口规定使用 25 针连接器,简称 DB25,连接器的尺寸及每个插针的排列位置都有明确的定义。
RS-232C 还有一种 9 针的非标准连接器接口,简称DB9。串口通信使用的大多都是 DB9 接口。DB25 和 DB9 接头有公头和母头之分,其中带针状的接头是公头,而带孔状的接头是母头。
在串口通信中,通常我们只使用 2、3、5 三个管脚,即TXD、RXD、SGND。
RS-232C 对逻辑电平也做了规定,在 TXD 和 RXD 数据线上:
1.逻辑 1 为-3至-15V 之间的电压
2.逻辑 0 为 3至15V 之间的电压
在 RTS、CTS、DSR、DTR 和 DCD 等控制线上:
1.信号有效( ON 状态) 为 3至15V 之间的电压
2.信号无效( OFF 状态) 为-3至-15V 之间的电压
由此可见,RS-232C 是用正负电压来表示逻辑状态,与晶体管-晶体管逻辑集成电路(TTL)以高低电平表示逻辑状态的规定正好相反。而51 单片机使用的就是 TTL 电平,所以要实现 51 单片机与计算机的串口通信,需要进行TTL与 RS-232C 电平转换,通常使用的电平转换芯片是 MAX232。
注意:串口数据收发线要交叉连接,计算机的TXD要对应单片机的 RXD,计算机的 RXD 要对应单片机的TXD,并且共GND。

通信协议

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 的数据位表示,只要双方约定一致即可。

串口工作方式1(51单片机通常使用)

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

51单片机串口的使用方法

波特率计算

方式 0 的波特率 = fosc/12
方式 2 的波特率 =(2SMOD/64)· fosc
方式 1 的波特率 =(2SMOD/32)·(T1 溢出率)
方式 3 的波特率 =(2SMOD/32)·(T1 溢出率)
注:T1 溢出率 = fosc /{12×[256 -(TH1)]}
SMOD软件设置为0或1,分别代表波特率不变和加倍。

串口初始化步骤

1、确定 T1 的工作方式(TMOD 寄存器);
2、确定串口工作方式(SCON 寄存器);
3、计算 T1 的初值(设定波特率),装载 TH1、TL1;
4、启动 T1(TCON 中的 TR1 位);
5、如果使用中断,需开启串口中断控制位(IE 寄存器)。
栗,设置串口为工作方式 1、波特率为 4800、波特率加倍、使用中断。其配置程序如下:

1
2
3
4
5
6
7
8
9
10
void UsartInit()
{
SCON=0X50; //设置为工作方式 1
TMOD=0X20; //设置计数器工作方式 2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800 的TL1=0XF3;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}

和外部中断、定时器中断一样,中断时我们可以让单片机为我们服务:给引脚赋值控制、和其它设备通信(通信内容又可以达到控制目的)
注:一定要软件清除中断标志位!!!

1
2
3
4
5
6
7
void Usart() interrupt 4
{
u8 receiveData;
receiveData=SBUF;//出去接收到的数据
RI = 0;//清除接收中断标志位
执行所需功能
}
代码实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义typedef unsigned char u8;
/*******************************************************************************
* 函数名 :UsartInit()
* 函数功能 :设置串口
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void UsartInit()
{
SCON=0X50; //设置为工作方式 1
TMOD=0X20; //设置计数器工作方式 2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800 的TL1=0XF3;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
UsartInit(); // 串口初始化
while(1);
}
/*******************************************************************************
* 函数名 : Usart() interrupt 4
* 函数功能 : 串口通信中断函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Usart() interrupt 4
{
u8 receiveData;
receiveData=SBUF;//出去接收到的数据
RI = 0;//清除接收中断标志位
SBUF=receiveData;//将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}