51单片机_串口
51单片机_串口
一、串行通信基础
通信是人们传递信息的方式。计算机通信是将计算机技术和通信技术相结合,完成计算机和外部设备或计算机和计算机之间的信息交换。这种信息交换可以分成两大类:并行通信与串行通信。
并行通信:将数据字节的各位用多条数据线同时进行传送。
特点:控制简单、传输速度快;由于传输线多,长距离传送时成本高且接收方的各位同时接收存在困难。
串行通信:将数据字节分成一位一位的形式在一条传输线上逐个地发送。串行通信时,数据发送设备先将数据代码由并行形式转换为串行形式,然后一位一位地放在传输线上进行传输。数据接收设备将接收到的串行形式数据转换成并行形式进行存储或处理。
特点:传输线少,长距离传送时成本低,且可以利用电话网络等现成设备,但数据的传送控制比并行通信复杂。

二、串行通信的基本概念
对于串行通信,数据信息、控制信息要按位在一条数据线上依次传送,为了对数据和控制信息进行区分,收发双方要事先约定共同遵守的通信协议。通信协议约定的内容包括数据格式、同步方式、传输速率、效验方式等。依发送与接收设备时钟的配置情况串行通信可以分为异步通信和同步通信。
1. 异步通信
异步通信是指通信的发送设备与接收设备使用各自的时钟控制数据的发送和接收的过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。

异步通信是以字符(构成的帧)为单位进行传输的,字符与字符之间间隙(时间间隔)任意,但每个字符中的各位是以固定的时间发送的,即字符之间是异步的(字符之间不一定有"位间隔"的整数倍关系),但同一字符内的各位是同步的(各位之间的距离均为"位间隔"的整数倍)。
为了实现异步传输字符的同步,采用的办法是使传送的每一位字符都以起始位"0"开始,以结束位"1"结束。这样,传送的每一个字符都用起始位来进行收发双方的同步。停止位和间隙作为时钟的频率偏差的缓冲,即使双方的时钟频率略有偏差,总的数据流也不会因偏差的积累而导致数据错位。
标准异步数据帧结构:
一个完整的数据帧由以下有序字段构成:
- 起始位:一个逻辑低电平(通常为0)比特,标志一个数据帧的开始,通知接收方启动采样时序。
- 数据位:紧接起始位之后的有效载荷数据。长度通常为5至9位,最常见为8位(1字节)。数据以LSB(最低有效位)在前的顺序发送。
- 校验位:可选的错误检测位,位于数据位之后。可分为:
- 奇校验:保证数据位与校验位中“1”的总数为奇数。
- 偶校验:保证数据位与校验位中“1”的总数为偶数。
- 停止位:一个或多个逻辑高电平(通常为1)比特,标志一帧数据的结束,并为接收方提供帧间恢复时间。
空闲状态下,通信线路保持为停止位电平(逻辑高)。
传送开始后,接收设备不断检测传输线,看是否有起始位到来。当接收到一系列的"1"(空闲位)之后,检测到"0",说明起始位出现,就开始接收所规定的数据位和奇偶校验位以及停止位。经过处理将停止为去掉,将数据位拼成一个并行字节,并且经效验无误后才算正确的接收到一个字符。一个字符接收完毕后,接收设备又继续测试传输线,监视"0"电平的到来(下一个字符的开始),直到全部数据接收完毕。
异步通信的特点:不要求收发双方时钟的严格一致,实现容易,设备开销较小,但每个字符要附加2~3位用于起止位,各帧之间还有间隔,因此传输效率不高。
2. 同步通信
同步通信时要建立发送方时钟对接收方时钟的直接控制,是双方达到完全同步。此时,传输数据的位之间的距离均为"位间隔"的整数倍,同时传送的字符间不留间隙,既保持位同步关系,也保持字符同步关系。发送方对接收方的同步通过两种方法实现:

同步通信的特点:以同步字符或特定的位组合"01111110"作为帧的开始,所传输的一帧数据可以是任意位。所以传输的效率较高,但实现的硬件设备比异步通信复杂。
三、串行通信的传输方向
串行通信依数据传输的方向及时间关系可分为:单工、半双工、全双工。


四、信号的调制与解调
计算机的通信要求传送的是数字信号。在远程数据通信时,通常要借用现存的公用电话网。但是电话网是为300~3400Hz的音频模拟信号设计的,对二进制数据的传输是不合适的。为此在发送时需要对二进制数据进行调制,使之适合在电话网上传输。在接收时,需要进行解调以将模拟信号还原为数字信号。
利用调制器(Modulator)把数字信号转换成模拟信号,然后送到通信线路上去,再由解调器(Demodulator)把从通信线路上收到的模拟信号转换成数字信号。由于通信是双向的,调制器和解调器合并在一个装置中,这就是调制解调器MODEM。

在图中,调制器和解调器是进行数据通信所需的设备,因此把它叫作数据通信设备(DCE)。计算机是终端设备(DTE),通信线路是电话线,也可以是专用线。
五、串行通信的错误效验
在通信过程中往往要对数据传送的正确与否进行效验。效验是保证准确无误地传输数据的关键。常用的效验方法有奇偶校验、代码和校验及循环冗余校验。
1. 奇偶校验
在发送数据时,数据位尾随的 1 位为奇偶校验为("1" 或 "0")。当约定为奇校验时,数据中"1"的个数与校验位"1"的个数之和应为奇数;当约定为偶校验时,数据中"1"的个数与校验位"1"的个数之和应为偶数。接收方与发送方的校验方式应一致。接收字符时、对"1"的个数进行校验,若发现不一致,则说明传输数据过程中出现了差错。
2. 代码和校验
代码和校验是发送方将所发数据块求和(或各字节异或),产生一个字节的校验字符(校验和)附加到数据块末尾。接收方接收数据同时对数据块(除校验字节外)求和(或各字节异或),将所得的结果与发送方的"校验和"进行比较,相符则无差错,否则即认为传送过程中出现了差错。
3. 循环冗余校验
这种校验是通过某种数学运算实现有效信息与校验位之间的循环校验,常用于对磁盘信息的传输、存储区的完整性校验等。这种校验方法纠错能力强,广泛应用于同步通信中。
六、传输速率与传输距离
1. 传输速率
数据的传输速率可以用比特率表示。比特率是每秒钟传输二进制代码的位数,单位是:位/秒(b/s)。如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位、1个停止位、8个数据位),这时的比特率为:
10位/个x240个/秒=2400b/s
应注意的是,在数据通信中常用波特率表示每秒钟调制信号变化的次数,单位是:波特(Baud)。波特率和比特率不总是相同的,如每个信号(码元)携带1个比特的信息,比特率和波特率就相同。如1个信号(码元)携带2个比特的信息,则比特率就是波特率的2倍。对于将数字信号"1"或"0"直接用两种不同电压表示的所谓基带传输,波特率和比特率是相同的。所以,我们也经常用波特率表示数据的传输速率。
2. 传输距离与传输速率的关系
串行接口或终端直接传送串行信息位流的最大距离与传输速率及传输线的电气特性有关。当传输线使用每0.3m(约1ft)有50 pF电容的非平衡屏蔽双绞线时,传输距离随传输速率的增加而减小。当比特率超过1 000 b/s时,最大传输距离迅速下降,如9600 b/s时最大距离下降到只有76 m(约250 f)。
七、串行通信RS-232C接口标准


八、80C51 单片机的串行接口
80CS1系列单片机有一个可编程的全双工串行通信口,它可作为UART(通用异步收发器),也可作同步移位寄存器。其帧格式可为8位、10位或11位,并可以设置多种不同的波特率。通过引脚RXD(P3.0串行数据接收引脚)和引脚TXD(P3.1串行数据发送引脚)与外界进行通信。

80C51 串行接口的内部简化结构图:

图中有两个物理上独立的接收、发送缓冲器SBUF,它们占用同一地址99H,可同时发送、接收数据。发送缓冲器只能写人,不能读出;接收缓冲器只能读出,不能写入。串行发送与接收的速率与移位时钟同步,定时器T1作为串行通信的波特率发生器,T1溢出率经2分频(或不分频)又经16分频作为串行发送或接收的移位时钟。移位时钟的速率即波特率。
接收器是双缓冲结构,由于在前一个字节从接收缓冲器读出之前,就开始接收第二个字节(串行输人至移位寄存器),若在第二个字节接收完毕而前一个字节未被读走时,就会丢失前一个字节的内容。串行接口的发送和接收都是以特殊功能寄存器SBUF的名称进行读或写的,当向SBUF发"写"命令时,即是向发送缓冲器SBUF装载并开始由TXD引脚向外发送-帧数据,发送完后便使发送中断标志TI=1;在串行接口接收中断标志RI(SCON.0)=0的条件下,置允许接收位REN(SCON.4) =1就会启动接收过程,一帧数据进入输人移位寄存器,并装载到接收SBUF中,同时使RI=1。执行读SBUF的命令,则可以由接收缓冲器SBUF取出信息并通过内部总线送CPU。
对于发送缓冲器,因为发送时CPU是主动的,不会产生重叠错误。
九、80C51 串行接口的控制寄存器




十、串口通信代码实践

1)单片机向电脑发送数据
main.c
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
unsigned char Sec;
void main()
{
UART_Init(); //串口初始化
while(1)
{
UART_SendByte(Sec); //串口发送一个字节
Sec++; //Sec自增
Delay(1000); //延时1秒
}
}
Delay.c
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
Delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
UART.c
#include <REGX52.H>
/**
* @brief 串口初始化,4800bps@12.000MHz
* @param 无
* @retval 无
*/
void UART_Init()
{
SCON=0x40; //配置串行控制寄存器 0100 0000
PCON |= 0x80; //使能波特率倍速位SMOD 0100 0000 | 1000 0000 -> 1100 0000
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设定定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
//笔记:
// TMOD &= 0x0F; //设置定时器模式 0000 1111
// TMOD |= 0x20; //设置定时器模式
// 第一行:TMOD &= 0x0F;
// 功能:清零TMOD寄存器的高4位(定时器1相关位)
// 效果:
// 0x0F的二进制是0000 1111
// 与运算(&)会将高4位清零,低4位保持不变
// 这相当于清除了定时器1的所有配置(GATE、C/T、M1、M0)
// 第二行:TMOD |= 0x20;
// 功能:设置定时器1为模式2(8位自动重装模式)
// 效果:
// 0x20的二进制是0010 0000
// 或运算(|)会设置第5位(从右0开始计)为1
// 对应TMOD中定时器1的M1=1, M0=0,即模式2
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte; //向SBUF写入数据
while(TI==0); //检测发送标志位是否置1,如果置1则说明发送完毕
TI=0; //重置发送中断请求标志位
}
UART.h
#ifndef __UART_H__
#define __UART_H__
void UART_Init();
void UART_SendByte(unsigned char Byte);
#endif
2)电脑通过串口控制LED

main.c
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
void main()
{
UART_Init(); //串口初始化
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI==1) //如果接收标志位为1,接收到了数据
{
P2=~SBUF; //读取数据,取反后输出到LED
UART_SendByte(SBUF); //将受到的数据发回串口
RI=0; //接收标志位清0
}
}
Delay.c
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
Delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
UART.c
#include <REGX52.H>
/**
* @brief 串口初始化,4800bps@12.000MHz
* @param 无
* @retval 无
*/
void UART_Init()
{
SCON=0x50;
PCON |= 0x80;
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设定定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA=1;
ES=1;
}
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);
TI=0;
}
/*串口中断函数模板
void UART_Routine() interrupt 4
{
if(RI==1)
{
RI=0;
}
}
*/
UART.h
#ifndef __UART_H__
#define __UART_H__
void UART_Init();
void UART_SendByte(unsigned char Byte);
#endif
波特率的计算:

重装值为:243
13us 后定时器溢出,频率为 1/13us = 0.07692MHz (倍频,不需要除2)
0.07692MHz/16 = 0.00480769MHz = 4807.69Hz (需要除16)


浙公网安备 33010602011771号