串口通讯🔌
计算机通信💻
- 计算机通信是指计算机与外部设备或计算机与计算机之间的信息交换。
- 通信有并行通信和串行通信两种方式。在多微机系统以及现代测控系统中信息的交换多采用串行通信方式。
- 并行通信通常是将数据字节的各位用多条数据线同时进行传送。
- 并行通信的特点控制简单、传输速度快;由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难。
- 串行通信是将数据字节分成一位一位的形式在一条传输线上逐个地传送。
- 串行通信的特点:传输线少,长距离传送时成本低,且可以利用电话网等现成的设备,但数据的传送控制比并行通信复杂。
串行通讯的基本概念📶
异步通信与同步通信
- 异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。(通信双方各自约定通信速率,需要设定一样的波特率)
- 异步通信的特点:不要求收发双方时钟的严格一致,实现容易,设备开销较小,但每个字符要附加 2~3 位用于起止位,各帧之间还有间隔,因此传输效率不高。
- 同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。发送方对接收方的同步可以通过两种方法实现。(左图:外同步;右图:自同步)(通过规定电平上升沿下降沿发送接收数据)
串行通信的传输方向
- 单工是指数据传输仅能沿一个方向,不能实现反向传输。
- 半双工是指数据传输可以沿两个方向,但需要分时进行。
- 全双工是指数据可以同时进行双向传输
传输速率
比特率:每秒钟传输二进制代码的位数
单位是:位/秒(bps)。如每秒钟传送 240 个字符,而每个字符格式包含 10 位( 1 个起始位、1 个停止位、8 个数据位),
这时的比特率为: 10位×240个/秒 = 2400 bps
波特率:波特率表示单位时间内传送的码元符号的个数(发送和接收各数据位的间隔时间)
每秒传送 240 个字符,波特率就是 240
波特率的计算
溢出率➗2(通过控制倍速与不倍速)➗16
以后面代码中4800为例
PCON &= 0x7F; //波特率不倍速 SCON = 0x50; //8位数据,可变波特率 TMOD &= 0x0F; //设置定时器模式 TMOD |= 0x20; //设置定时器模式 TL1 = 0xF3; //设置定时初始值 TH1 = 0xF3; //设置定时重载值不倍速,溢出率为1/13 us
波特率 1/13÷16*1000000 = 4800 Hz(存在误差)
传输距离与传输速率关系
串行接口或终端直接传送串行信息位流的最大距离与传输速率及传输线的电气特性有关。当传输线使用每 0.3m(约1英尺)有 50PF 电容的非平衡屏蔽双绞线时,传输距离随传输速率的增加而减小。当比特率超过 1000 bps 时,最大传输距离迅速下降,如 9600 bps 时最大距离下降到只有 76m (约 250 英尺)。
传输距离与传输速率成反比
总线(BUS)
- 总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线
- 连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)
常用通信接口比较
| 名称 | 引脚定义 | 通信方式 | 特点 |
|---|---|---|---|
| UART | TXD、RXD | 全双工、异步 | 点对点通信 |
| I²C | SCL、SDA | 半双工、同步 | 可挂载多个设备 |
| SPI | SCLK、MOSI、MISO、CS | 全双工、同步 | 可挂载多个设备 |
| 1-Wire | DQ | 半双工、异步 | 可挂载多个设备 |
- 此外还有:CAN、USB等
全双工:通信双方可以在同一时刻互相传输数据
半双工:通信双方可以互相传输数据,但必须分时复用一根数据线
单工:通信只能有一方发送到另一方,不能反向传输
异步:通信双方各自约定通信速率
同步:通信双方靠一根时钟线来约定通信速率
总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)
串行接口
串行接口简称串口,也称串行通信接口或串行通讯接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路]简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。
- 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
- 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
- 51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信。
接口划分标准
- RS-232
- RS-422
- RS-485
- 详细参考:串行接口
硬件电路
- 简单双向串口通信有两根通信线(发送端TXD和接收端RXD)
- TXD与RXD要交叉连接
- 当只需单向的数据传输时,可以直接一根通信线
- 当电平标准不一致时,需要加电平转换芯片
电平标准
- 电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
- TTL电平:+5V 表示 1,0V 表示 0
- RS232电平:-3 ~ 15V 表示 1,+3 ~ +15V 表示 0
- RS485电平:两线压差+2 ~ +6V 表示 1,-2 ~ -6V 表示 0(差分信号)
串口时序
*串行通信常见错误校验
奇偶校验
在发送数据时,数据位尾随的 1 位为奇偶校验位(1 或0 )。奇校验时,数据中“1”的个数与校验位“1”的个数之和应为奇数;偶校验时,数据中“1”的个数与校验位“1”的个数之和应为偶数。接收字符时,对“1”的个数进行校验,若发现不一致,则说明传输数据过程中出现了差错。
若为奇校验: 发送 1111 1100 1 第九位为“1”表示接收正确;“0”表示传输出现错误
若为偶校验: 发送 1111 1100 0 第九位为“0”表示接收正确;“1”表示传输出现错误
奇偶校验存在一定的局限性,若数据发生两位错误,如: 奇校验:发送1111 1100 1,传输成1111 0011 1 则校验仍然是成功的
0校验与1校验
设置为1校验,校验位始终为1,接收方接收到数据发现检验位为1就判断数据正确,这种方法简陋。
设置为0校验,校验位始终为0,接收方接收到数据发现检验位为0就判断数据正确,这种方法简陋。
代码和校验
代码和校验是发送方将所发数据块求和(或各字节异或),产生一个字节的校验字符(校验和)附加到数据块末尾。接收方接收数据同时对数据块(除校验字节外)求和(或各字节异或),将所得的结果与发送方的“校验和”进行比较,相符则无差错,否则即认为传送过程中出现了差错。
循环冗余校验
这种校验是通过某种数学运算实现有效信息与校验位之间的循环校验,常用于对磁盘信息的传输、存储区的完整性校验等。这种校验方法纠错能力强,广泛应用于同步通信中。
51单片机的UART
-
STC89C52有1个UART
-
STC89C52的UART有四种工作模式:
模式0:同步移位寄存器
模式1:8位UART,波特率可变(常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可变
- SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器。
串口与中断
相关寄存器
参考数据手册
代码示例
仅发送
#include <REGX52.H>
void UART_Init()
{
SCON=0x40;
PCON |= 0x80;
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设定定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);
TI=0;
}
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char Sec;
void main()
{
UART_Init(); //串口初始化
while(1)
{
UART_SendByte(Sec); //串口发送一个字节
Sec++; //Sec自增
Delay(1000); //延时1秒
}
}
接收/串口控制LED
#include <REGX52.H>
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
void UART_Init()
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设置定时初始值
TH1 = 0xF3; //设置定时重载值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
EA=1;
ES=1;
}
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);
TI=0;
}
/*串口中断函数模板
void UART_Routine() interrupt 4
{
if(RI==1)
{
RI=0;
}
}
*/
void main()
{
UART_Init(); //串口初始化
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI==1) //如果接收标志位为1,接收到了数据
{
P2=~SBUF; //读取数据,取反后输出到LED
UART_SendByte(SBUF); //将受到的数据发回串口
RI=0; //接收标志位清0
}
}
要如何发送汉字呢?因为汉字是GB2312编码,一个汉字占用两个字符,要先将字符转换
//发送以下内容,向串口发送“中国”
UART_SendByte(0xD6); //串口发送一个字节
UART_SendByte(0xD0);
UART_SendByte(0xB9);
UART_SendByte(0xFA);
注意:
关于串口通信这里只讲了点对点通信,关于多机通信以后有时间补上
关于定时器的12T与1T,关系到单片机的机器周期。在传统8051都是12T。可参考STC单片机 定时器时钟FOSC 1T 12T、定时器模式_