江科大51单片机学习笔记之串口通信

一、串口介绍

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信,包括单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,这极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。

STC89C51RC/RD+系列单片机内部集成有一个功能很强的全双工串行通信口,与传统8051单片机的串口完全兼容。

51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信。

本开发板带有USB转TTL模块,使得我们可以直接使用USB来进行串口通信(从而无需使用DB9接口)

二、简单双向串口通信

•简单双向串口通信有两根通信线(发送端TXD(transmit exchange data)和接收端RXD(receive exchange data))

•TXD与RXD要交叉连接(一个发送,另一个接收)

•当只需单向的数据传输时,可以直接一根通信线

•当电平标准不一致时,需要加电平转换芯片

image-20230802151318834

补充:电平标准

电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:

•TTL电平:+5V表示1,0V表示0(单片机使用)

•RS232电平:-3~15V表示1,+3~+15V表示0

•RS485电平:两线压差+2~+6V表示1,-2~-6V表示0(差分信号)

三、常见通信接口
名称引脚定义通信方式特点
UARTTXD、RXD全双工、异步点对点通信
I²CSCL、SDA半双工、同步可挂载多个设备
SPISCLK、MOSI、MISO、CS全双工、同步可挂载多个设备
1-WireDQ半双工、异步可挂载多个设备

•此外还有:CAN、USB等

补充:相关术语(具体可在计算机网络或通信原理中学习)

全双工:通信双方可以在同一时刻互相传输数据

半双工:通信双方可以互相传输数据,但必须分时复用一根数据线(在同一时刻只能单向传输)

单工:通信只能有一方发送到另一方,不能反向传输

异步:通信双方各自约定通信速率(没有时钟线)

同步:通信双方靠一根时钟线来约定通信速率

总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)

四、51单片机的UART

STC89C52只有1个UART

STC89C52的UART有四种工作模式:

模式0:同步移位寄存器

模式1:8位UART,波特率可变(常用

模式2:9位UART,波特率固定

模式3:9位UART,波特率可变

如图:P3.0和P3.1用于串口的收发

image-20230802153048053
五、串口参数及时序图

•波特率:串口通信的速率(发送和接收各数据位的间隔时间)

•检验位:用于数据验证(检验数据是否正确)

•停止位:用于数据帧间隔(表示一帧数据发送完毕)

(具体可见通信原理或计算机组成原理或计算机网络)

image-20230802153559739
六、串口工作方式

如图,是串口的工作模式(简图)

image-20230701171405108

SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器

当要发送数据时,数据从总线传输到SBUF,通过控制门传输到TXD,将数据发送出去,控制门是一些控制逻辑电路,不用关心,发送数据由发送控制器来进行控制。接收数据时,数据从RXD接收到,通过接收控制器将数据送到移位寄存器,再送到SBUF。接收数据是由中断来进行的,数据传输速率由中间的逻辑电路(定时器1)来控制(波特率)

中断逻辑:

注:这里使用的中断系统图是传统51单片机的图,STC89C52的中断系统图可参考手册

image-20230802160111617

发送数据触发发送中断TI,接收到数据触发接收中断RI,两个用一个或门连接,占用同一个通道,即接收或者发送数据便可触发该中断,之后使能该中断,配置中断优先级后便可使用该中断。(本实验只使用这一个中断,故也可以不配置中断优先级)

七、串口相关寄存器
51-串口相关寄存器
SCON串行控制寄存器

用于选择串行通信的工作方式和某些控制功能。

51-SCON格式

SMO/FE:
当PCON寄存器中的SMOD0/PCON.6位为1时,该位用于帧错误检测。当检测到一个无效停止位时,通过UART接收器设置该位。它必须由软件清零。
当PCON寄存器中的SMOD0/PCON.6位为0时,该位和SM1一起指定串行通信的工作方式,如下表所示。

(本实验不用帧错误检测,用8位UART,故SM0为0,SM1为1)

51-串行通信工作方式的选择

SM2:
​ 允许方式2或方式3多机通信控制位。在方式2或方式3时,如SM2位为1,REN位为1,则从机处于只有接收到RB8位为1(地址帧)时才激活中断请求标志位RI为1,并向主机请求中断处理。被确认为寻址的丛机则复位SM2位为0,从而才接收RB8为0的数据帧。在方式1时,如果SM2位为1,则只有在接收到有效的停止位时才置位中断请求标志位RI为1;在方式0时,SM2应为0。(本实验方式1不用停止位,故SM2为0)
REN:
​ 允许/禁止串行接收控制位。由软件置位REN,即REN=1为允许串行接收状态,可启动串行接收器RxD,开始接收信息。软件复位REN,即REN=0,则禁止接收。(本实验1不需要接收数据,REN为0,实验2需要接收数据,REN为1)
TB8:
​ 在方式2或方式3,它为要发送的第9位数据,按需要由软件置位或清0。例如,可用作数据的校验位或多机通信中表示地址帧/数据帧的标志位。(本实验方式1,给0就行)
RB8:
​ 在方式2或方式3,是接收到的第9位数据。在方式1,若SM2=0,则RB8是接收到的停止位。方式0不用RB8。(本实验方式1,不需要停止位,给0就行)
TI:
发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,即TI=1,向主机请求中断,响应中断后必须用软件复位,即TI=0。在其他方式中,则在停止位开始发送时由内部硬件置位,必须用软件复位。
RI:
接收中断请求标志位。在方式0,当串行接收到第8位结束时由内部硬件自动置位RI=1,向主机请求中断,响应中断后必须用软件复位,即RI=0。在其他方式中,串行接收到停止位的中间时刻由内部硬件置位,即RI=1(例外情况见SM2说明),必须由软件复位,即RI=0。

(TI和RI先置为0)

PCON电源控制器
51-PCON格式

SMOD:
波特率选择位。当用软件置位SMOD,即SMOD=1,则使串行通信方式1、2、3的波特率加倍; SMOD=0,则各工作方式的波特率不加倍(参考手册上是错的)。复位时SMOD=0。
SMOD0:
帧错误检测有效控制位。当SMOD0=1,SCON寄存器中的SM0/FE位用于FE(帧错误检测)功能;当SMOD0=0,SCON寄存器中SM0/FE位用于SM0功能,和SM1一起指定串行口的工作方式。复位时SMOD0=0

八、实验1:串口向电脑发送数据

本实验使用模式一,并且数据没有停止位

配置SCON

SM0和SM1要配置成01(模式一),且SM2要配置为0(因为数据格式没有停止位),REN位无所谓(因为本实验是单片机发送数据,不需要接收,如果要接收数据,则需要置1),TB8和RB8直接置0即可(本实验是模式一),TI和RI也置0。

SCON = 0x40;//0100 0000
配置PCON

不加倍波特率,故SMOD置0,其余位也为0

PCON = 0;
定时器模式

之前使用定时器,是使用模式1(16位的定时器),即将两个8位的寄存器当成一个16位的大寄存器,但是每次进入中断时需要给寄存器赋初值,如果不赋初值,则计数器从0开始计数,而赋初值的语句的执行需要占用时间,这就导致定时器的精度不高。在串口中,传输数据是很快的,对时间精度要求较高,故使用定时器模式2(8位自动重装载模式)。具体见定时器章节江科大51单片机学习笔记之定时器与中断系统_rebened小橙的博客-CSDN博客

TMOD &= 0x0F;		//清除定时器1模式位
TMOD |= 0x20;		//设定定时器1为8位自动重装方式
定时器初值

定时器初值与波特率有关,可以用STC-ISP软件生成波特率,完成串口的配置

本单片机是11.0592MHz的频率,没有误差,所以在直接就用9600波特率,不需要波特率倍速来减小误差

image-20230802184803528
void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

实验1不需要接收数据,故SCON的REN位为0(当然为1也行),与江科大视频一致,改为0x40

STC89C52没有AUXR这个寄存器,直接将那两行删除就行

定时器1只用作波特率发生器,不需要其产生中断,故与中断相关的配置就不需要了

/**
  * @brief  串口初始化,9600bps@11.0592MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
	SCON = 0x40;
	PCON &= 0x7F;		//波特率不倍速
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}
发送数据

将数据写入SBUF寄存器中,即可自动发送数据(硬件逻辑)

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节数据
  * @retval 无
  */
void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;//将Byte写入SBUF中
	while(TI==0);//TI为1时,说明产生了发送中断,表示发送数据完成
	TI=0;//数据发送完了,软件将TI置0
}
测试
void main()
{
	UART_Init();
	UART_SendByte(0x11);
	while(1)
	{
		
	}
}

按下复位键,看见接收缓冲区收到数据,说明发送数据成功(与视频不同,波特率选择9600)(注意选择HEX模式,因为发送的时十六进制数)

image-20230802191544073
主函数

通过串口,向电脑发送连续的数(十六进制)

unsigned char Sec;

void main()
{
	UART_Init();			//串口初始化
	while(1)
	{
		UART_SendByte(Sec);	//串口发送一个字节
		Sec++;				//Sec自增
		Delayms(1000);		//延时1秒
	}
}
补充:模块化

UART.h

#ifndef _UART_H__
#define _UART_H__

void UART_Init();
void UART_SendByte(unsigned char Byte);

#endif

UART.c

#include <REGX52.H>

/**
  * @brief  串口初始化,9600bps@11.0592MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
	SCON = 0x40;
	PCON &= 0x7F;		//波特率不倍速
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节数据
  * @retval 无
  */
void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;//将Byte写入SBUF中
	while(TI==0);//TI为1时,说明产生了发送中断,表示发送数据完成
	TI=0;//数据发送完了,软件将TI置0
}

main.c

#include <REGX52.H>
#include "Delay.h"
#include "UART.h"

unsigned char Sec;

void main()
{
	UART_Init();			//串口初始化
	while(1)
	{
		UART_SendByte(Sec);	//串口发送一个字节
		Sec++;				//Sec自增
		Delayms(1000);		//延时1秒
	}
}
九、实验2:电脑通过串口控制LED
修改串口初始化

实验2需要接收数据,故SCON的REN位为1,与江科大视频一致,改为0x50

接收数据需要中断才能进行,所以需要中断使能(这个中断是串口中断,不是定时器1中断)

void UART_Init()
{
	SCON = 0x50;
	PCON &= 0x7F;		//波特率不倍速
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	EA=1;
	ES=1;
}
串口中断服务函数
void UART_Routine() interrupt 4
{
	if(RI==1)					//如果接收标志位为1,接收到了数据(因为发送和接收都会触发这个中断)
	{
		P2=~SBUF;				//读取数据,取反后输出到LED
		UART_SendByte(SBUF);	//将收到的数据发回串口
		RI=0;					//接收标志位清0,软件清零
	}
}
主函数
#include <REGX52.H>
#include "UART.h"

void main()
{
	UART_Init();			//串口初始化
	while(1)
	{
		
	}
}

void UART_Routine() interrupt 4
{
	if(RI==1)					//如果接收标志位为1,接收到了数据(因为发送和接收都会触发这个中断)
	{
		P2=~SBUF;				//读取数据,取反后输出到LED
		UART_SendByte(SBUF);	//将收到的数据发回串口
		RI=0;					//接收标志位清0,软件清零
	}
}
补充:数据显示模式

•HEX模式/十六进制模式/二进制模式:以原始数据的形式显示

•文本模式/字符模式:以原始数据编码(ASCII码)后的形式显示

例如,发送数据为HEX模式,接收数据为文本模式,发送数据30则接收到0,因为数字0对应的ASCII码为0x30

​ 发送数据为文本模式,接收数据为HEX模式,发送数据A则接收到41,因为A对应的ASCII码为0x41

更多51单片机笔记见主页

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例
基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例 基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例基于51单片机开发的小程序学习资料,用于学习51单片机的嵌入式开发,应用案例

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值