通常人们将计算机与外界之间的数据交换传送称为通信。在51单片机中,不仅可以实现串口通信,还可以通过IO口模拟实现其他通信,例如:SPI、IIC。在前面章节我们就说过,学习 51 单片机重点及难点内容主要有中断、 定时/计数器、串口通信。这一章我们就来学习 51 单片机的串口通信。开发板上集成了 1 个串口通信电路,是 USB 转串口模块,它既可下载程序也可实现串口通信功能。
本节我们要实现的功能是:
1、利用51单片机的串口(UARTA)向电脑端发送数据;
2、利用电脑端通过串口控制LED模块;
目录
一、通信的基本概念
1.1串行通信与并行通信
1.2异步通信与同步通信
1.3 单工、半双工与全双工通信
1.4波特率
二、串口的介绍
2.1串口内部结构
2.2串口相关寄存器
2.2.1串口控制寄存器(SCON)
2.2.2电源控制寄存器
2.2.3串行口数据寄存器SBUF
2.2.4其他寄存器
2.3 波特率的设置
2.4使用串口的步骤
三、硬件设计
四、实验及源码
4.1串口向电脑发送数据
4.2电脑通过串口控制LED
(1)、串行通信
串行通信是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度;
特点:传输线少,长距离传送时成本低,但速度慢,适合大数据传输和远距离的数据通信;
(2)、并行通信
并行通信通常是将数据字节的各位用多条数据线同时进行传送,通常是 8 位、16 位、32 位等数据一起传输。
特点:速度快、效率高;但需要传送数据线多,传输成本大;
(1)、异步通信
异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程,为使双方的收发协调,通信双方应该各自约定通信速率;
异步通信是以字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“ 位间隔”的整数倍。
(2)、同步通信
同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。
(1)、单工通信
单工是指数据传输仅能沿一个方向,不能实现反向传输。
(2)、半双工通信
半双工是指数据传输可以沿两个方向,但需要分时进行。
(3)、全双工通信
全双工是指数据可以同时进行双向传输。
串行通信的传送速率是指数据传送的速度,一般用波特率进行表示。波特率定义为串行通信时每秒传送“位”的个数。例如:1s传送1bit,就是1波特,即n波特=n b/s。
串行通信(UART):是一种全双工的异步串行通信接口;
串口通信(Serial Communication),是指外设和计算机间通过数据信号线、 地线等按位进行传输数据的一种通信方式,属于串行通信方式。
如上图:为51单片机内部的串口结构;
串行口进行数据的收发流程是:
串口数据的接收:外部数据通过RXD输入,先进入移位寄存器,在进入SUBF(接受缓冲器);当一帧数据全部进入SUBF后,串口发出中断请求,通知CPU读取数据,CPU执行完读取SUBF中的数据,将其送入其他存储单元。同时接受端可接受下一帧数据。
串口数据的发送: CPU将数据通过内部数据总线传送的移位寄存器,经过控制门逐位的把数据通过引脚TXD发送出去。在发送时,由于CPU主动进行操作,在发送外后,中断发出中断请求,可发送下一帧数据。
在上述的数据收发过程中,会牵扯一些相关的概念:
1、波特率发生器:主要由定时器T0、T1以及内部的一些控制开关和分频器组成。它为串口提供时钟信号,从而控制信号的收发。 相关的寄存器有:TMOD、TCON、TL1、TH1、TL2、TH2(控制定时器所用,之前已经提及过)PCON(后面会讲);
2、串行数据缓冲寄存器SBUF:用于接收和发送数据的缓存器;
3、串行口控制寄存器TCON:用来控制串行通信接口的工作方式,并指示串行口的工作状态;
4、RXD:串行数据的输入引脚,对应单片机IO口的(P3.0);
5、TXD:串行数据的输出引脚,对应单片机IO口的(P3.1);
SM0、SM1:串口工作方式选择位;
SM2:多机通信控制位,主要用于方式 2 和方式 3。
REN:允许串行接收位。由软件置 REN=1,则启动串行口接收数据;若软件置 REN=0,则禁止接收。
TB8:在方式 2 或方式 3 中,是发送数据的第 9 位,可以用作数据的奇偶校验位,或在多机通信中,作为地址帧/数据帧的标志位。 在方式 0 和方式 1未用到。
RB8:在方式 2 或方式 3 中,是接收到数据的第 9 位,作为奇偶校验位或地 址帧/数据帧的标志位。在方式 1
TI:发送中断标志位。在方式 0 时,当串行发送第 8 位数据结束时,或在其它方式,串行发送停止位的开始时,由内部硬件使 TI 置 1,向 CPU 发中断申请。 在中断服务程序中,必须用软件将其清 0,取消此中断申请。
RI:接收中断标志位。在方式 0 时,当串行接收第 8 位数据结束时,或在其它方式,串行接收停止位的中间时,由内部硬件使 RI 置 1,向 CPU 发中断申请。 也必须在中断服务程序中,用软件将其清 0,取消此中断。
我们此次用到的串口的工作方式为方式1,只需要注意SCON中加粗的位,其余位默认为0即可。
SMOD:波特率倍增位。在串口方式 1、方式 2、方式 3 时,波特率与 SMOD 有关,当 SMOD=1 时,波特率提高一倍。复位时,SMOD=0;
SBUF是两个在物理上独立的发送、接收缓冲器,可同时发送、接收数据。两个缓存器共用一个字节地址,可通过指令对SBUF的读/写来进行区分;
SBUF=A;//SBUF在等号左边,是被赋值的,是发送缓存寄存器;若要通过串口发送数据,只需要往SBUF里写数据。
在使用串口通信时,还会涉及到中断(TCON、IE)、定时/计数器(TMOD、TH、TL)等相应的寄存器; 此处不在进行讲解,需要了解请看下面的博客;
CSDNhttps://mp.csdn.net/mp_blog/creation/editor/133919372
CSDNhttps://mp.csdn.net/mp_blog/creation/editor/133904885
在使用串口通信时,通信双方的波特率保持一致是十分重要的,简单来说,要保证发送一帧数据与接受一帧数据的速率保持相同。
如何设置单片机的波特率呢?首先,波特率的发生(产生)的相关电路是下面的部分;
和波特率有直接性关系的是定时器,需要确定时器的工作方式,最重要的是确定TH1以及TL1的初值(定时器1),此外,还要考虑串口的工作方式、晶振的大小以及电源控制寄存器中高位SMOD是否为(即波特率是否加倍);
下面推荐一款波特率自动生成的小工具:
链接:https://pan.baidu.com/s/1f9aeiNWycYVzCBsqXzo7dQ
提取码:1022
选择定时器工作方式,输入开发板上使用的晶振频率大小,选择所要使用波特率,SMOD 为是否倍频;点击确定后即会自 动生成定时/计数器 TH、TL 的初值;误差大小可以反映出通信时是否出现乱码。
如何使用串口,大家可以参考下面的步骤,进行配置;(无顺序排列);
1、设置定时器工作方式寄存器TMOD;(用于产生波特率);
2、设置定时器大小TH、TL(用于控制波特率大小);
3、设置串口的工作方式;
4、设置电源控制寄存器的最高位SMOD(用于波特率是否加倍);
5、设置启用定时器TCON寄存器TR1(用于打开定时器1);
6、如果需要使用中断,在进行中断相关寄存器的配置;
串口初始化程序:
void UART_Init(void)
{
TMOD =0X20;//设置定时器的工作方式:设置使用定时器1,工作方式为方式2;
SCON=0X40;//设置串口工作方式:设置为工作方式1;
PCON =0X80;//设置电源控制寄存器,波特率加倍;
//计算波特率,设置定时计数器的初值
TH1= 0xfa;
TL1= 0xfa;TR1=1;//打开计数器;TCON寄存器
//是否使用中断,如若使用,则打开中断配置;
EA=1;//打开中断总开关;
ET1=0;//打开串口的接受中断;
}
开发板上板载一个 USB 转串口模块。其硬件电路如下所示:
从上图中可以看出,通过 CH340 芯片把 51 单片机的串口与 PC 机的 USB 口 进行连接,不仅可以实现程序的烧入,还可实现串口通信功能 。使用 USB 转串口芯片,免去了一根串口线,使用普通 USB 数据线(支 持安卓手机数据线)就可以进行串口通信。
电脑端,使用串口助手进行设置,需要保证同单片机的波特率相同;
实验说明:利用串口实现单片机向串口助手(计算机)传送数据;
main.c文件
#include //包含51头文件
#include "uart.h"//包含串口函数头文件
#include "delay.h"//包含延迟函数头文件
unsigned char i;//定义变量
void main()//定义主函数
{
UART_Init();//串口初始化
for(i=1;i<100;i++)//使用循环,串口依次向计算机传送数据
{
UART_SendByte(i);
Delay100ms(10); //延迟1s
}
while(1)
{
}
}
uart.h文件
#include "uart.c"
void UART_Init(void);//声明串口函数
void UART_SendByte(unsigned char byte);//声明串口发送函数
uart.c文件
/**
*@breaf 串口初始化
*@param 无
*@retval 无
*/
void UART_Init(void)//波特率9600
{
TMOD =0X20;//设置定时器的工作方式:设置使用定时器1,工作方式为方式1;
SCON=0X40;//设置串口工作方式:设置为工作方式1;
PCON =0X80;//设置电源控制寄存器,波特率加倍;
//计算波特率,设置定时计数器的初值
TH1= 0xfa;
TL1= 0xfa;
//是否使用中断,如若使用,则打开中断配置;
EA=1;//打开中断总开关;
ET1=0;//关闭串口的接受中断;
TR1=1;//打开计数器;TCON寄存器
}
/**
*@breaf 串口发送一个字节数据函数
*@param byte 传送的一个字节
*@retval 无
*/
void UART_SendByte(unsigned char byte)
{
SBUF=byte;
while(TI==0);
TI=0;
}
delay.h文件
#include "delay.c"
void Delay100ms(unsigned char t);//声明延迟函数
delay.c文件
void Delay100ms(unsigned char t) //@11.0592MHz
{
unsigned char i, j;
while(t--)
{
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
}
}
实验现象:
串口向电脑助手发送数据
实验说明:利用串口实现计算机向单片机传递数据,进而改变LED灯的亮灭,此外,单片机向串口助手(计算机)返回传递的数据;
main.c文件
#include //包含51头文件
#include "uart.h"//包含串口函数头文件
void main()//定义主函数
{
UART_Init();串口函数初始化
while(1)
{
}
}
/**
*@breaf 串口中断服务子函数
*@param
*@retval
*/
void uart_routine() interrupt 4//当数据传递给单片机后,我们需要进入中断,要不然我们无法知道,数据是否由串口助手传递给单片机
{
if(RI==1)//如果接收数据标志位置1(即电脑发送的数据已经被单片机全部接收);防止由单片机发送数据完成也会进入中断。因为收发用的是同一个中断;
{
P2=~SBUF;//令接收的数据为点亮LED的模块
UART_SendByte(SBUF);//将接收的数据又发送给电脑助手
RI=0;
}
}
uart.c文件
/**
*@breaf 串口初始化
*@param 无
*@retval 无
*/
void UART_Init(void)
{
TMOD =0X20;//设置定时器的工作方式:设置使用定时器1,工作方式为方式1;
SCON=0X50;//设置串口工作方式:设置为工作方式1;打开接受ren=1;
PCON =0X80;//设置电源控制寄存器,波特率加倍;
//计算波特率,设置定时计数器的初值
TH1= 0xfa;
TL1= 0xfa;
//是否使用中断,如若使用,则打开中断配置;
EA=1;//打开中断总开关;
ES=1;//启动串口中断;
ET1=0;//关闭定时器1的中断
TR1=1;//打开计数器;TCON寄存器
}
/**
*@breaf 串口发送一个字节数据函数
*@param byte 传送的一个字节
*@retval 无
*/
void UART_SendByte(unsigned char byte)
{
SBUF=byte;
while(TI==0);
TI=0;
}
uart.h文件
#include "uart.c"
void UART_Init(void);//声明串口函数
void UART_SendByte(unsigned char byte);//声明串口发送函数
实验现象:
总结:本节讲述了通信的基本概念,对单片机的串口(UART)功能做了介绍,电路图、内部结构,相关寄存器的使用,初始化,利用串口进行单片机与电脑的数据传递。并且完成两个实验。1、串口向电脑发送数据;2、电脑通过串口控制单片机的LED灯。在学习完之后,大家一定一定要自己上手进行操作!!!
创作不易,还请大家多多点赞支持!!!