🌷1.串口介绍
串口是一种应用十分广泛的通讯接口,串口成本低,容易使用,通信线路简单,可以实现两个设备的互相通信。单片机的串口可以使单片机和单片机,单片机和电脑,单片机与各式各样的模块互相通信,极大的拓展了单片机的应用范围,增强了单片机系统的硬件实力。51单片机内部自带UAPT(通用异步收发器)
可以实现单片机的串口通信。

🌷2.通讯方式
单工模式:通信的数据传输是单向的。通信双方中,一方固定为发送端,一方则固定为接收端。信息只能沿一个方向传输,使用一根传输线。
半双工模式:通信使用同一根传输线,既可以发送数据又可以接收数据,但不能同时进行发送和接收。数据传输允许数据在两个方向上传输,但是,在任何时刻只能由其中的一方发送数据,另一方接收数据。因此半双工模式既可以使用一条数据线,也可以使用两条数据线。半双工通信中每端需有一个收发切换电子开关,通过切换来决定数据向哪个方向传输。因为有切换,所以会产生时间延迟,信息传输效率低些。
全双工模式:通信允许数据同时在两个方向上传输。因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。在全双工模式中,每一端都有发送器和接收器,有两条传输线,信息传输效率高。
显然,在其它参数都一样的情况下,全双工比半双工传输速度要快,效率要高


在单片机中就是UART这种全双工,异步的通信方式
🌷3.串口通讯的数据格式和参数
UART串口通信需要两根信号线来实现,一根用于串口发送,另外一根负责串口接收。UART在发送或接收过程中的一帧数据由4部分组成,起始位、数据位、奇偶校验位和停止位,如下图所示。其中,起始位标志着一帧数据的开始,停止位标志着一帧数据的结束,数据位是一帧数据中的有效数据。校验位分为奇校验和偶校验,用于检验数据在传输过程中是否出错。奇校验时,发送方应使数据位中1的个数与校验位中1的个数之和为奇数;接收方在接收数据时,对1的个数进行检查,若不为奇数,则说明数据在传输过程中出了差错。同样,偶校验则检查1的个数是否为偶数

UART通信过程中的数据格式及传输速率是可设置的,为了正确的通信,收发双方应约定并遵循同样的设置。数据位可选择为5、6、7、8位,其中8位数据位是最常用的,在实际应用中一般都选择8位数据位;校验位可选择奇校验、偶校验或者无校验位;停止位可选择1位(默认),1.5或2位。串口通信的速率用波特率表示,它表示每秒传输二进制数据的位数,单位是bps(位/秒),常用的波特率有9600、19200、38400、57600以及115200等。
🌷4.串口通信的配置
🍓4.1串口向电脑发送数据
🍆4.1.1串口相关寄存器

SCON是控制这个电路如何运转开关怎么拨。里面有很多位可以。控制这个电路
SBUF是串口数据缓存寄存器,发送的数据存储到这里。
PCON是电源管理寄存器其中有SMOD和SMOD0这两位是控制串口的,之所以放在电源这里可能是单片机当中资源有点紧张。然后串口又多了所以分配到电源管理寄存器当中去了。
IE是允许中断标志当种有EA和ES是这个中断控制的东西与串口有关。
🍆4.1.2 SM0和SM1工作模式

🍆4.1.3 SCON串行控制寄存器

注意:串行控制寄存器是可位寻址;可以单独对一位寄存器进行赋值
『模式1:8位UART[⒈个字节],波特率可变』— 最常用的一个模式。
B7→SM0 = 0(工作模式一就是SM0=0,SM1=1)
B6→SM1 = 1 [决定工作模式,在这里我们是工作模式⒈]
B5→SM2 = 0 [多机通信是方式⒉和方式⒊的,如果是这两个的话设置SM2 = 1反之SM2 = 0]
B4→REN = 1||0 [是否允许它进行接收RXD,如果REN = 0的话就是不允许接收 REN = 1的话就是允许接收。想让单片机接收数据的话就置为1,不想让单片机接收就置为0]
B3→TB8 = 0 [方式三和方式二置1用于发送第⑨位数据,方式一置0]
B2→RB8 = 0 [方式三和方式二置1用于发送第⑨位数据,方式一置0]
B1→TI = 0 [初始化配置给0]
B0→RI = 0 [初始化配置给0]

🍆4.1.4 PCON电源控制寄存器

注意:PCOD电源控制寄存器是不可寻位址,它的寄存器只能进行整体的赋值


注意:当串口向电脑发送数据的时候:单片机只是需要给电脑发送就行,所以没有必要开启中断
🍆4.1.5 定时器的工作模式二

这个串口只能对它配置定时器1这是它专用的

模式2→8位自动重装模式,这个算是第二个最常用的一个模式。第二种模式主要用于串口通信产生波特率来用的『在电子通信领域,波特(Baud)即调制速率,指的是有效数据讯号调制载波的速率,即单位时间内载波调制状态变化的次数』
🍆4.1.6 用STC_ISP来生成代码
利用这个软件调节各个参数就可以对波特率进行计算并且生成代码

在发送当中内部的移位的过程还是比较复杂的,但是在我们编写程序当中的操作还是比较容易的。我们只需要把数据写到SBUF当中去,一旦我们写进去的时候它就会发送出去。
当SBUF被赋值为左值的时候就带表它是写入SBUF被写入的话它就是发送的。
UART.c&h
//UART.c
#include <REGX52.H>
void UART_Init()
{
SCON = 0x40; //发送数据就不需要接受,所以REN=0
TMOD &= 0x0F;//0000 0000 & 0000 1111 定时器1的话高四位清0 定时器0的话低四位清0
TMOD |= 0x20;//0000 0000 | 0010 0000
TL1 = 0xFA;
TH1 = 0xFA;
ET1 = 0;
TR1 = 1;
}
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;//TX发送 SBUF被赋值为左值
while(TI==0);//发送到了数据置TI == 1
TI=0;//软件复位
}
//UART.h
#ifndef __UART_H__
#define __UART_H__
void UART_Init();
void UART_SendByte(unsigned char Byte);
#endif
Delay.c&h
//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
main.c
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
int main()
{
unsigned char Sec = 0;
UART_Init(); //串口初始化
while(1)
{
UART_SendByte(Sec); //串口发送一个字节
Sec++; //Sec自增
Delay(1000); //延时1秒 准确精准,防止有误差!
}
}
🍓4.2电脑通过串口控制led灯
接收
注:一般发送数据是不需要中断号的,但是接收数据的话是需要中断号的。
接收的话之所以要中断系统是因为我们并不清楚电脑什么时候发送过来,我们也不能一直检测所以我们就可以利用中断电脑发送过来的时候(单片机接收)触发这个中断在中断函数当中进行处理。
注→SCON串行控制寄存器当中REN现在我们是要进行接收了所以需要REN置1的值。
接收的时候需要中断所以我们需要在串口初始化当中加上ES = 1 和 EA = 1 的值,优先级默认。 其实无论在发送还是接收只要有一个条件满足了它就会触发中断。当中断使能[EA]之后程序会跳转到中断服务函数里面 — void UART_Routine interrupt4 表示(串口中断)


main.c
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
void main()
{
UART_Init(); //串口初始化
while(1)
{
}
}
//中断服务子函数
void UART_Routine() interrupt 4 // interrupt 4 中断的入口-中断服务子函数
{
if(RI==1) //如果接收标志位为1,接收到了数据.[之所以需要判断是因为我们要区分接收RI=TXD和发送TI=RXD]
{
P2=~SBUF; //读取数据,取反后输出到LED SBUF在等号的右边说明它是接收位
UART_SendByte(SBUF); //将接收到的数据发回串口
RI=0; //接收标志位清0 软件复位
}
}
Delay.c&h
//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&h
//UART.c
#include <REGX52.H>
void UART_Init(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES=1;
EA=1;
}
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;//发送-单片机向电脑发送数据
while(TI==0);
TI=0;
}
//UART.h
#ifndef __UART_H__
#define __UART_H__
void UART_Init();
void UART_SendByte(unsigned char Byte);
#endif