本章概述思维导图:
51单片机实现串口模块教程
通信基本概念
通信,至少是需要两个对象,一个收一个发数据。
根据数据通信的传输时序协调方式,可分为:同步通信和异步通信;
根据数据通信的传输线路可分为:串行通信和并行通信;
根据数据通信的传输方向性及双向交互能力可分为:单工通信和双工通信(半双工通信和全双工通信);
串行通信和并行通信定义
串行通信:数据按位顺序传输,使用单条线路进行数据得传输。例如,发送字节 10110010
时,先传 1
,再传 0
,以此类推。
并行通信:数据的多个位(通常8位、16位等)同时通过多条线独立线路并行传输。如传输字节 10110010
,会使用8根数据线,每根线同时传1位。
串行和并行的区别;
串行通信指同一时刻,只能收或发一个bit位信息,因此只用一根数据信号线即可;并行通信指同一时刻,可以收或发多个bit位信息,因此需要多根数据信号线才行;
同步通信和异步通信定义
同步通信:发送方与接收方通过共享时钟线的时钟信号,确保数据按固定时间间隔传输,接收方能准确预测数据到达时间;
异步通信:发送方与接收方无共享时钟线,通过数据包或数据帧格式(如起始信号/停止位)协调传输数据;
同步和异步的区别:同步通讯需要有时钟信号控制,通过时钟线的高低电平控制数据的收发;异步通信没有时钟信号控制,通过数据帧格式控制数据的收发(大家约定好通信速度(波特率));
小心得:就是一个有时钟线提供时钟时序,一个没有时钟线;
单工和半双工、全双工定义
单工通信:数据仅能沿固定方向单向传输,发送端与接收端角色不可互换。
应用场景:广播系统(电台→听众、卫星数据下行)、传感器网络(如温湿度传感器→数据中心)等;
半双工通信:同一信道分时复用,双方交替发送和接收。就是指同一时刻只允许发送或者接收;
应用场景:对讲机、传统Wi-Fi;
全双工通信:双方可同时发送和接收数据;
应用场景:电话通话、以太网交换机等;
单工和半双工、全双工的区别:
单工通信:单工要么收要么发,只能做接收设备或者发送设备。接收器不能发送数据给 发送器。例如:收音机;
半双工通信:双发都可以发送数据,双方不能同时发送数据或接收数据;只有一根发送/接收数据信号线。(特点:可以收可以发,但是不能同时收发)例如:对讲机;
全双工通信:双方可以同时发送或者接收数据;有两根发送/接收数据信号线;(特点:可以同时即发送又接收数据)例如:手机
通信速率
通信速率(比特率)是衡量数据在信道中传输效率的核心指标,其本质是单位时间内传输的信息量。每秒传输的二进制比特数,单位为比特/秒(bps),是衡量信息量的直接指标。;例如1000bps表示每秒传输1000个二进制位(0或1);
波特率是每秒传输的符号(码元)数,是物理层信号变化的频率,用于描述UART串口通信时的通信速度,其单位(bps)即每秒钟传送的位(bit) 的数量
在二进制调制中(如UART),1符号=1比特,此时波特率=比特率
在多进制调制中(如QPSK、16QAM),1符号可携带多比特,波特率!=比特率
串口通信简介
串口(UART)通讯:异步通讯、全双工、串行通讯、总线协议;
UART通用同步异步收发器,是一种通用的串行、异步/同步通信总线。该总线有两条数据信号线,可以实现全双工的发送和接收;
上位机:就是连接串口的电脑或者手机上的APP软件;是在自动化控制系统中,用于监控 和控制下位机(如单片机、PLC等)的计算机。它可以直接发送操作指令给下位机, 并接收下位机的反馈数据,通过用户操作交互界面向用户展示数据。
51单片机串口相关寄存器
一、串口控制寄存器(SCON)
SCON用于控制串口工作模式,数据收发及状态指示,其各位定义如下:
位序 | 名称 | 功能描述 |
7 | SM0 | 串口工作模式选择位(与SM1组合) |
6 | SM1 | 串口工作模式选择位(与SM0组合) |
5 | SM2 | 多机通信控制位(模式2/3时启用) |
4 | REN | 接收允许位(1=允许接收,0=禁止接收) |
3 | TB8 | 模式2/3时发送的第9位数据 |
2 | RB8 | 模式2/3时接收的第9位数据 |
1 | TI | 发送中断标志(硬件置位,软件清零) |
0 | RI | 接收中断标志(硬件置位,软件清零) |
RI位:接收中断标志位。当数据接收完成后由硬件自动置1,响应完中断后必须软件复位写0;
TI位:发送中断标志位。当数据发送完成后由硬件自动置1,响应完中断后必须软件复位写0;
RB8位:模式2/3时接收的第9位数据;模式1,若SM2=0,则为接收到的停止位;
TB8位:模式2/3时发送的第9位数据,由软件写0/1;可用作于数据校验位或多机通信中表示地址帧/数据帧的标志位;
REN位:接收运行位,使用串口接收必须将改为置1(1=允许接收,0=禁止接收);
SM2位:多机通信控制位,模式2/3时,SM2位为1,REN位为1,则从机只有接收到RB8位为1(地址帧)时才会触发RI位为1。SM2为0时,从而接收RB8位为0的数据帧;
SM1位:串口模式选择位(与SM0组合);
SM2位:串联模式选择位(与SM1组合);
工作模式选择(SM0/SM1):
SM0 | SM1 | 模式 | 特点 |
0 | 0 | 模式0 | 同步移位寄存器(8位数据,波特率固定) |
0 | 1 | 模式1 | 8位UART,波特率可变 |
1 | 0 | 模式2 | 9位UART,波特率固定(PCON寄存器中SMOD位控制) |
1 | 1 | 模式3 | 9位UART,波特率可变 |
二、电源控制寄存器(PCON)
位序 | 名称 | 功能描述 |
7 | SMOD | 波特率倍增位(1=波特率加倍,仅模式1/2/3有效) |
6-0 | 保留 | 仅SMOD位有效,其他位为虚设或保留 |
三、串行口数据缓存寄存器SBUF
串行口数据缓存寄存器(SBUF)是串口通信中的核心寄存器,用于实现数据的发送和接收。
SBUF在物理上是一个寄存器,但在逻辑上分为发送缓冲区和接收缓冲器,两者通过同一地址访问,但功能独立:
发送缓冲器:写入SBUF的数据将被串口发送。
接收缓冲器:串口接收的数据将存入SBUF,供CPU读取。
SBUF寄存器操作方式:
数据发送方式步骤:
1、将待发送数据写入SBUF。
2、硬件自动将SBUF中的数据通过TXD引脚(P3.1)发送。
3、发送完成后,发送中断标志(TI)由硬件置位。
代码示例:
SBUF = 0x41; // 发送字符'A'(ASCII码0x41)
while(!TI); // 等待发送完成
TI = 0; // 清零TI标志(必须软件清零)
数据接收方式步骤:
1、启用串口接收(通过SCON的REN位设置)。
2、当RXD引脚(P3.0)检测到有效起始位时,硬件开始接收数据。
3、接收完成后,数据存入SBUF,接收中断标志(RI)由硬件置位。
代码示例:
if(RI) { // 检测接收标志char data = SBUF; // 读取接收数据RI = 0; // 清零RI标志(必须软件清零)
}
串口工作模式
1、模式0
模式0:同步移位寄存器模式
数据格式:8位同步移位寄存器,LSB优先,无起始/停止位。
波特率:固定为晶振频率(fosc)的1/12。
寄存器配置:
SCON寄存器:SM0=0,SM1=0。
数据通过RXD引脚(P3.0)输入输出,TXD引脚(P3.1)输出(移位脉冲)同步时钟。
如果设置中断的情况下,发送/接收完成,对应中断标志位TI/RI都会硬件置一,小伙伴们使用完中断标志位要记得软件清0呦!
2、模式1
模式1:8位UART模式(可变波特率)
数据格式:10位异步通信(1起始位+8数据位+1停止位)。
波特率:由定时器1的溢出率决定,计算公式为:
波特率=定时器时钟频率 / (12×(256−TH1初值))
定时器时钟频率通常为fosc/12(12时钟模式)或fosc/6(6时钟模式)。
寄存器配置:
SCON寄存器:SM0=0,SM1=1。
TMOD寄存器:定时器1设为模式2(自动重装载),TMOD=0x20。
TH1/TL1:设置波特率初值,例如9600bps时(fosc=11.0592MHz,SMOD=0),TH1=0xFD。
3、模式2
模式2:9位UART模式(固定波特率)
数据格式:11位异步通信(1起始位+9数据位+1停止位)。第9位为可编程位(TB8)。
波特率:由PCON寄存器的SMOD位控制:
SMOD=0时,波特率=fosc/64;
SMOD=1时,波特率=fosc/32。
寄存器配置:
SCON寄存器:SM0=1,SM1=0。
PCON寄存器:SMOD位根据需求设置(例如,波特率倍增时SMOD=1)。
应用场景:多机通信中,第9位可用于地址识别(如TB8=1表示地址帧)。
4、模式3
模式3:9位UART模式(可变波特率)
数据格式:与模式2相同,但波特率生成方式不同。
波特率:由定时器1的溢出率决定,计算公式与模式1一致,但支持更高波特率(因 SMOD可倍增)。
寄存器配置:
SCON寄存器:SM0=1,SM1=1。
TMOD/TH1/TL1配置与模式1相同,但需结合PCON的SMOD位优化波特率。
应用场景:需高波特率或多机通信的复杂场景,如工业控制网络。
串口计算波特率
计算波特率方法:
方式0:波特率(固定)=fosc / 12
方式1:波特率=(2的SMOD次方 / 32)* (T1溢出率)
方式2:波特率(固定)=(2的SMOD次方 / 64)* fosc
方式3:波特率=(2的SMOD 次方/ 32)* (T1溢出率)
其中T1溢出率=fosc / { 12 * [ 256 - ( TH1 )]}
在这里我使用串口波特率计算器进行计算,也会打包成文件方便大家使用哟!
51单片机串口配置步骤
配置步骤:
1、确定T1的工作方式(TMOD寄存器):选择定时器1的方式2,波特率的产生
2、确定串口工作方式(SCON寄存器):一般选择选择串口方式1
3、计算T1的初值(设定波特率),赋初值装载到TH1、TL1;
4、启动T1(TCON中的TR1位);
5、如果使用中断,需开启串口中断控制器位(IE寄存器),并开启总中断位EA位
代码示例:
Void UART_Init(u8 baud) //串口配置函数:形参为定时器计数的初值
{TMOD|=0x20; //设置计数器工作方式2SCON=0x50; //设置为工作方式1PCON=0x80; //波特率加倍TH1=baud; //赋初值TL1=baud;ES=1; //开启接收中断EA=1; //打开总中断TR1=1; //打开计数器
}
串口模块硬件电路原理图分析
小伙伴们看这个电路图是不是非常熟悉,是我们之前学习51开发板最小系统中的下载电路,它不仅是USB转TTF电路也是开发板与电脑上位机软件进行串口通信的电路,因为我们下载烧录程序的时也是用的是串口功能实现烧录的;同时我们要使用串口与电脑上位机软件实现通信功能需要将P5底座进行跳线帽的连接。
观察图中CH340G是一款USB转串口芯片,负责将PC的USB信号转换为TTL串口信号(RXD/TXD),从而与51单片机的串口通信模块(如STC89C52的P3.0/P3.1)对接。
电源引脚:
USB的5V(VCC)连接到CH340G的VCC引脚,为芯片供电。
USB的GND与CH340G的GND引脚连接,形成公共地。
数据引脚:
USB的D+和D-分别连接到CH340G的UD+和UD-引脚,实现USB通信。
串口引脚:
CH340G的TXD引脚 → 单片机的RXD(如P3.0),用于向单片机发送数据。
CH340G的RXD引脚 → 单片机的TXD(如P3.1),用于接收单片机发送的数据。
串口模块软件编程设计
实现三个主题任务:
任务一:实现串口助手(上位机)发送数据给单片机,单片机接收到后原封不动转发给串口助手(上位机)显示;
实现步骤:
1、我们首先要进行串口初始化函数的配置,配置内容有配置定时器1的工作模式3,这是为了生成波特率。在配置串口的工作模式,并开启定时器和串口中断
2、配置串口中断服务函数
代码示例:
#include "reg52.h"void UART_Init(u8 bps)//串口初始时化函数:形参为定时器1赋初值
{TMOD|=0x20; //配置定时器1工作模式3,用或运算是避免影响其他定时器初始化SCON=0x50; //配置串口工作模式1,开启接收允许位PCON=0x80; //波特率加倍TH1=bps; //赋初值TL1=bps;ES=1; //串口中断允许位开启EA=1; //总中断允许位开启TR1=1; //定时器1开启
}void UART_ISR() interrupt 4
{u8 dat=0;RI=0; //接收中断软件清零dat=SBUF; //从SBUF寄存器中取值SBUF=dat; //将数据发送给上位机while(!TI); //等待发送完成TI=0; //发送中断软件清零
}
int main()
{UART_Init(0xFA);while(1){}
}
效果展示:
任务二:实现串口发送数据给上位机,本任务是我们主动控制MCU利用串口发送数据给上位机
实现步骤:
1、在上面的基础上我们构建串口发送一字节数据函数
2、利用串口一字节数据发送函数实现串口数据包发生函数
代码示例:
#include "TYPEDEF.h"
#include "reg52.h"void UART_Init(u8 bps)//串口初始时化函数:形参为定时器1赋初值
{TMOD|=0x20; //配置定时器1工作模式3,用或运算是避免影响其他定时器初始化SCON=0x50; //配置串口工作模式1,开启接收允许位PCON=0x80; //波特率加倍TH1=bps; //赋初值TL1=bps;ES=1; //串口中断允许位开启EA=1; //总中断允许位开启TR1=1; //定时器1开启
}
void UART_TX(u8 temp)//串口发送一字节函数
{ES=0; //在串口初始化函数中我们开启了串口中断,在这里我们先关闭等数据发生完成在开启TI=0;SBUF=temp; //开始发送数据while(!TI); //等待数据发送完成TI=0; //软件请0ES=1; //开启串口中断
}
void USAR_TxPacket(u8 *temps)//串口发送数据包函数
{while(*temps){UART_TX(*temps++);Delay_10us(2); }}
void UART_ISR() interrupt 4
{u8 dat=0;RI=0; //接收中断软件清零}
int main()
{UART_Init(0xFA);USAR_TxPacket((u8*)"今晚夜色不错,抬头看看月光\n");while(1){}
}
效果展示:
任务三:上位机给串口发送控制指令,串口根据控制指令完成相应的步骤(模拟物联网控制)
实现步骤:
1、创建一个接收缓冲区数组,接收缓存区数组标志位,接收标志位。(判断接收完成要依靠\r\n标志符)
2、在串口中断服务函数中判断是否接收数据,接收到数据,放入到缓冲区数组中
3、在主函数中判断缓冲区数组的数据是否与控制指令相同,相同执行开灯,关灯指令;
代码示例:
#include "TYPEDEF.h"
#include "reg52.h"
#include "LED.h"
void UART_Init(u8 bps)//串口初始时化函数:形参为定时器1赋初值
{TMOD|=0x20; //配置定时器1工作模式3,用或运算是避免影响其他定时器初始化SCON=0x50; //配置串口工作模式1,开启接收允许位PCON=0x80; //波特率加倍TH1=bps; //赋初值TL1=bps;ES=1; //串口中断允许位开启EA=1; //总中断允许位开启TR1=1; //定时器1开启
}
void UART_TX(u8 temp)//串口发送一字节函数
{ES=0; //在串口初始化函数中我们开启了串口中断,在这里我们先关闭等数据发生完成在开启TI=0;SBUF=temp; //开始发送数据while(!TI); //等待数据发送完成TI=0; //软件请0ES=1; //开启串口中断
}
void USAR_TxPacket(u8 *temps)//串口发送数据包函数
{while(*temps){UART_TX(*temps++);Delay_10us(2); }}
u8 UART_buff[10]=0; //缓冲区接收数组
u8 UART_cnt=0; //缓存区数组下标
u8 UART_flag=0; //标志位
void UART_ISR() interrupt 4
{u8 dat=0;if(RI){RI=0; //接收dat=SBUF;if(UART_cnt>=9 || UART_buff[UART_cnt]=='\n' ){UART_buff[UART_cnt]='\0';UART_flag=1;}else{UART_buff[UART_cnt++]=dat;}}}
int main()
{UART_Init(0xFA);//USAR_TxPacket((u8*)"今晚夜色不错,抬头看看月光\n");while(1){if(UART_flag){if(!strcmp((char *)UART_buff,"LED_ON")){LED=0;UART_flag=0;UART_cnt=0;}if(!strcmp((char *)UART_buff,"LED_OFF")){LED=1;UART_flag=0;UART_cnt=0;}} }
}
制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴点个关注!有不懂的地方和需要的资源随时问我哟!