文章目录
前言
本文为笔者学习过程的笔记,主要内容为串口通信,使用的开发板为51单片机,后期会补充其他平台。提示:以下是本篇文章正文内容,下面案例可供参考
一、计算机通信简介
概念:计算机与外部设备或计算机与计算机之间的信息交换。
主要的通信形式有两种:并行通信和串行通信。
并行通信:将数据字节的多位用多根数据线连接同时进行传送。
优点:控制简单、传输速度快。
缺点:长距离通信时,成本高且接受方的各位同时接收存在困难。
串行通信:将数据字节分成一位一位的形式在一条传输线上进行数据传输。
优点:传输线少、长距离传输成本低。
缺点:传输控制相对并行困难。
二、串口通信简介
1、简介
串口是一种引用十分广泛的通讯接口,串口的成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
51单片机、树莓派、Wemos D1等开发板,都自带UART(通用异步收发器),可以实现串口通信。
2、同步通信和异步通信
串口通信可以分为同步通信和异步通信。
2.1 同步通信
同步通信:一种比特同步通信技术,要求发收双方具有同频同相的同步时钟信号,只需在传送报文的最前面附加特定的同步字符,使发收双方建立同步,此后便在同步时钟的控制下逐位发送/接收。
同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。发送方对接收方的同步可以通过两种方法实现
2.2 异步通信
异步通信:异步通信是指通信中两个字符(8位)之间的时间间隔是不固定的,而在一个字符内各位的时间间隔是固定的。
异步通信是以字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“位间隔”的整数倍。
通信的发送与接收设备使用格子的时钟控制数据的发送和接受过程。为了使双方的手法协调,要求发送和接收设备的时钟尽可能一致
异步通信特点:
1.不要求收发双方时钟的严格一致
2.容易实现
3.设备开销较小
4.每个字符需要附加2到3位用于起止位
5.各帧之间还有间隔
6.传输效率不高
3、串行通信的传输方式
传输方式有三种,分别为单工、半双工和全双工。
单工:数据传输仅能延一个方向,不能实现反向传输。
半双工:数据传输可以延两个方向,但是需要分时进行(不能同时进行通信)。
全双工:数据可以同时进行双向传输(不需要要分时)。
4、串口通信硬件电路
- 简单的串口通信有两根通信线(发送端TXD 和 接收端RXD)。
- TXD 和 RXD 需要交叉连接。
- 当只需要单向传输时,也可以只接一根传输线。
- 当电平标标准不一致时,需要加电平转换芯片。
图示:
5、常见接口介绍
名称 | 引脚定义 | 通信方式 | 特点 |
---|---|---|---|
UART | TXD、RXD | 全双工、异步 | 点对点通信 |
IIC | SCL、SDL | 半双工、同步 | 可挂载多个设备 |
SPI | SCLK、MOSI、MISO、CS | 全双工、同步 | 可挂载多个设备 |
1-write | DQ | 半双工、异步 | 可挂载多个设备 |
除此之外还有CAN、USB等。
三、串口相关寄存器详解
51单片机串口通信相关寄存器有SCON、SBUF、PCON、TMOD等
1、特殊功能寄存器SCON
SCON:用来设定串行口的工作方式、接受/发送控制以及设置状态指示。
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
地址:98H | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI | SCON |
SM2:多机通讯控制位。在方式0时,SM2一定要等于0。在方式1中,当(SM2)=1则只有接收到有效停止位时,RI才置1。在方式2或方式3当(SM2)=1且接收到的第九位数据RB8=0时,RI才置1。
REN:接收允许控制位。由软件置位以允许接收,又由软件清0来禁止接收。
TB8: 是要发送数据的第9位。在方式2或方式3中,要发送的第9位数据,根据需要由软件置1或清0。例如,可约定作为奇偶校验位,或在多机通讯中作为区别地址帧或数据帧的标志位。
RB8:接收到的数据的第9位。在方式0中不使用RB8。在方式1中,若(SM2)=0,RB8为接收到的停止位。在方式2或方式3中,RB8为接收到的第9位数据。
TI:发送中断标志。在方式0中,第8位发送结束时,由硬件置位。在其它方式的发送停止位前,由硬件置位。TI置位既表示一帧信息发送结束,同时也是申请中断,可根据需要,用软件查询的方法获得数据已发送完毕的信息,或用中断的方式来发送下一个数据。TI必须用软件清0。
RI:接收中断标志位。在方式0,当接收完第8位数据后,由硬件置位。在其它方式中,在接收到停止位的中间时刻由硬件置位(例外情况见于SM2的说明)。RI置位表示一帧数据接收完毕,可用查询的方法获知或者用中断的方法获知。RI也必须用软件清0。
SM1,SM0:串行工作方式:
SM0 | SM1 | 方式 | 说明 | 波特率 |
---|---|---|---|---|
0 | 0 | 0 | 移位寄存器 | fosc/12 |
0 | 1 | 1 | 10位异步收发器(8微数据) | 可变 |
1 | 0 | 2 | 11位异步收发器(9微数据) | fosc/64或fosc/32 |
1 | 1 | 3 | 11位异步收发器(9微数据) | 可变 |
2、PCON寄存器
注意:改寄存器中只有一位与串行口工作有关
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
地址:87H | SMOD | PCON |
SMOD:波特率倍增位。在串口工作在方式2、方式3,波特率与SMOD有关。
当SMOD = 1时,波特率提高一倍。
当SMOD = 0时,不加倍。
3、TMOD寄存器(定时器工作方式寄存器)
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
地址:89H | GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 | TMOD |
高四位为定时计数器1的设置,低四位是定时计数器0设置,串口通信波特率设置占用定时计数器1,这里主要说串口通信,不过多说定时计数器,只需要设置定时计数器1的工作方式即可
当GATE=1时,“与门”的输出信号K由INTx输入电平和TRx位的状态一起决定(即此时K=TRx·INTx),当且仅当TRx=1,INTx=1(高电平)时,计数启动;否则,计数停止。
当INT0引脚为高电平时且TR0置位,TR0=1;启动定时器T0;
当INT1引脚为高电平时且TR1置位,TR1=1;启动定时器T1。
当GATE=0时,“或门”输出恒为1,“与门”的输出信号K由TRx决定(即此时K=TRx),定时器不受INTx输入电平的影响,由TRx直接控制定时器的启动和停止。
当TR0=1,启动定时器T0。
当TR1=1,启动定时器T1。
C/T:定时器和计数器选择位,0为定时器,1为计数器
M1 | M0 | 工作方式 |
---|---|---|
0 | 0 | 工作方式0:为13位定时/计数器 |
0 | 1 | 工作方式1:为16位定时/计数器 |
1 | 0 | 工作方式2:8位初值自动重装定时/计数器 |
1 | 1 | 工作方式3:仅适用于T0,分成两个8位计数器,T1停止计数 |
4、代码演示(单片机和电脑通信)
main.c
#include "reg52.h"
#include "delay.h"
#include "UART.h"
#define uchar unsigned char
#define uint unsigned int
void main()
{
uart_Init();
while(1)
{
}
}
void uart() interrupt 4
{
uchar byte;
byte = uart_Receive();
uart_Send(byte);
}
uart.h
#ifndef __UART_H__
#define __UART_H_
void uart_Init();
void uart_Send(unsigned char send);
unsigned char uart_Receive();
#endif
uart,c
#include "reg52.h"
void uart_Init()
{
SCON = 0x50; //设置串口工作方式为1,也可以设置为0x50
PCON = 0x80; //设置波特率倍频
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; //设定定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //打开定时器1
ES = 1; //打开串行口中断
EA = 1; //打开总中断
}
void uart_Send(unsigned char send)
{
SBUF = send;
while(TI == 0); //发送中TI=1,当发送完成后TI=0,可以作为条件来判断是否发送完成
TI = 0; //软件清零
}
unsigned char uart_Receive()
{
unsigned char receive;
receive = SBUF;
RI = 0;
return receive;
}