51单片机STC89C52RC——7.1 串口通信

目的/效果

实现单片机串口与电脑串口工具进行数据通讯,

1:设备向电脑串口发送HEX

2:让电脑串口工具控制单片机LED亮灭。同时让单片机反馈控制的结果。

一,STC单片机模块

二,串口通讯

2.1 串行通信与并行通信

(1)串行通信

(2)并行通信

2.2 异步通信与同步通信

(1)异步通信 :通信双方各自约定通信速率

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

分为外同步和内同步

2.3 单工、半双工与全双工通信

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

(2)半双工通信:通信双方可以互相传输数据,但必须分时复用一根数据线

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

2.4 串口通信协议

常用的串口通信协议有:

RS-232:用于计算机与外部设备通信的标准串口协议,传输距离短。它使用±3到±15V表示逻辑信号。

RS-422:定义了双绞线电缆上的差分信号传输标准,适用于长距离通信。它使用两对差分信号±2V~±6V表示逻辑1和0。

RS-485:在RS-422基础上增加了多点通信功能,支持多设备连接。它可以实现一主多从的通信结构。

USB:通用串行总线,可以实现高速串口通信。USB转串口芯片广泛应用于各种外部设备的连接。

Modbus:基于RS-485的半双工串行通信协议,应用在工业控制领域。它支持主从模式及广播模式,可靠简单。

CAN:控制器区域网络,是一种串行通信总线标准,主要用于汽车和工业控制系统。它通过差分信号实现差错检测。

I2C:两线式串行总线,由Philips公司提出,用于连接低速周边设备。它只需要两根线即可实现同步串口通信。

SPI:串行外设接口,由Motorola公司提出,主要用于短距离高速通信。它使用同步通信方式,速度更快。

2.5 串口通信应用

串口通信应用非常广泛,主要包括:

连接外设:打印机、扫描仪、RFID读写器、条码扫描枪等设备通常提供串口接口。计算机可以通过串口与这些外设进行通信。

工业控制:在工业自动化领域,PLC、传感器、执行器、驱动器等设备都提供串口接口,通过RS-485、Modbus连接构成工业现场总线,用于设备监控和控制。

嵌入式系统:嵌入式系统通过串口调试接口连接PC,用于系统调试。产品发布后,可通过串口扩展通信接口。

通信设备:串口广泛应用于通信设备中,用于设备管理、通信模块(如GSM模块)连接、调试等功能。

POS机:POS机连接条码扫描器、打印机等外设,都广泛采用串口通信。这保证了POS机的通用性和兼容性。

仪器仪表:大量仪器仪表提供串口接口用于数据采集和连接PC。使用串口可以方便测量参数的读取。

电力设备:智能电表、监控设备及电力自动化设备需要串口进行参数配置、状态监测等功能。

随着物联网的兴起,连接各种传感器和执行器的需求增多,串口通信仍然非常重要。另一方面,USB、以太网等新型通信接口也在取代传统串口,但串口通信仍然在很多应用场景中不可或缺。

2.6 串口通信接口电路

串口通信的物理层接口有多种实现方式,常见的有:

RS-232:RS-232电平信号范围为±3V到±15V,适合短距离通信。接口电路简单,直接通过MAX232芯片转换TTL电平。

RS-422:差分信号接口,抗干扰性强,适合长距离通信。需要线 driver 和 line receiver 进行转换。

RS-485:同RS-422,也是差分信号接口。支持多点连接,适合工业现场总线。需要收发转换电路。

USB转串口:通过USB转串口芯片实现串口功能。USB接口简单易用,提供更高的数据速率。

典型的RS-232串口接口电路主要包括:

RS-232线路保护、接收检测电路:保护电路可采用二极管夹压保护,接收端使用比较器检测信号。

收发驱动放大电路:采用高速运算放大器进行驱动放大,以获得足够的输出驱动能力。

电平转换电路:MAX232芯片用于实现TTL和RS-232电平之间的双向转换。

控制逻辑电路:处理串口控制信号,进行收发控制。

2.7 串口通信接口的选择

选择串口通信接口需要根据具体应用考虑以下因素:

通信距离:电气特性决定了接口的适用距离。RS-232适用于15m以内,RS-422/485可以达到1000m。

通信速率:RS-232速率低,最大115200bps;RS-422/485速率也较低;USB转串口可以达到Mbpps级别。

抗干扰性:RS-422和RS-485采用差分信号,抗干扰性强。RS-232信号容易受到干扰。

接口复杂度:RS-232和USB转串口简单易用;RS-422和RS-485需要精确的终端匹配电阻。

通信对象:RS-232多用于点对点通信;RS-485可以实现多点通信。

成本:USB转串口的单价较高;RS-232和RS-485的硬件成本较低。

因此,对于普通的调试连接,RS-232和USB转串口较常用;在工业现场,RS-485可以实现多点连接;对于电气参数苛刻的长距离通信,可选用RS-422。

波特率的选择

传输速度:波特率越高,传输速度越快,但也会增加传输错误的可能性。

传输距离:波特率越高,传输距离越短,因为高速传输会导致信号衰减。

硬件支持:串口波特率需要与硬件设备匹配,如果硬件设备不支持高速传输,则无法使用高波特率。

2.8 STC89C52RC 用到的串口

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

STC89C52有1个UART,有四种工作模式:

模式0:同步移位寄存器

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

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

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

TXD与RXD要交叉连接

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

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

方式1 :8位数据格式

波特率表示每秒钟传输码元的个数,是衡量数据传输速率的指标,单位Baud。另外有个名词叫比特率,比特率表示每秒钟传输二进制位bit的个数,单位 bit/s。

2.9 如何计算波特率

波特率

方式 0 的波特率 = fosc/12

方式 2 的波特率 =(2SMOD/64)× fosc

方式 1 的波特率 =(2SMOD/32)×(T1 溢出率)

方式 3 的波特率 =(2SMOD/32)×(T1 溢出率)

其中 T1 溢出率 = fosc /{12×[256 -(TH1)]}

我们我们这里采用方式1 由我们人为设置的波特率4800 和 系统的晶振周期12MHz,算出溢出率和时钟初始值

STC89C52RC 的 晶振为fosc=12MHz,计数工作方式采用的是方式2;TMOD=0x20

SMOD=1

我们设置波特率为4800(每秒传输4800个bit)

溢出率=4800*(2^1/32)=76800(每秒钟发生76800次中断)

再用晶振周期12000000/12/76800=13(13个时钟周期就发生一次中断)

256-13=243=0xF3 (TH1=TL1的初始值0xF3,晶振13次后256(8位自动重装)发生一次中断)

所以
TL1 = 0xF3; //设置定时初始值
TH1 = 0xF3; //设置定时重载值

2.10 STC89C52 配置串口相关计算器

模式图

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

配置寄存器 SCON = 0x50(8位重装,接收使能)

这里注意TI ,发送完后需要复位TI=0;

cpp 复制代码
/**
 * 函    数:串口发送一个字节数据
 * 参    数:Byte 要发送的一个字节数据
 * 返 回 值:无
 */
void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;		//向发送区写数据
	while(TI==0);	//等待其他发送结束
	TI=0;			//程序手动复位
}

每次中断发生后, 接收标志位RI 重置,RI=0;

cpp 复制代码
/**
 * 函    数:uart1中断函数
 * 参    数:无
 * 返 回 值:无
 */
void uart1_interrupt() interrupt 4 
{	
	if(RI==1)					//如果接收标志位为1,接收到了数据
	{
        /*这里从SUBF中接收数据*/
        P2=~SBUF;				//读取数据,取反后输出到LED
		RI=0;					//数据接收完后,接收标志位清0
	}	
}

配置寄存器PCON

配置定时器 TMOD=0x20(启用定时器1,8位自动重装模式)

需要才有8位重装模式TH1=TL1=0xF3

STC89C52RC 串口和中断系统

TMOD &= 0x0F; //清除定时器1之前配置的模式

TMOD |= 0x20; //重新设置定时器1模式

ET1 = 0; //禁止定时器中断

TR1 = 1; //定时器1开始计时

EA=1;//允许总中断

ES=1;//允许中断

开启UART1 中断

cpp 复制代码
/**
 * 函    数:uart1中断函数
 * 参    数:无
 * 返 回 值:无
 */
void uart1_interrupt() interrupt 4 
{
	 
}

当然我们也可以用工具进行生成这些配置

具体配置代码如下

cpp 复制代码
#include <REGX52.H>

/**
 * 函    数:UART1串口初始化
 * 参    数:无
 * 返 回 值:无
 */
void UART_Init(void)	//4800bps@12.000MHz
{
	PCON |= 0x80;		//使能波特率倍速位SMOD
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//清除定时器1之前配置的模式
	TMOD |= 0x20;		//重新设置定时器1模式
	TL1 = 0xF3;			//设置定时初始值
	TH1 = 0xF3;			//设置定时重载值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
	EA=1;				//允许总中断
	ES=1;				//打开IE、XCON寄存器
}

三,创建Keil项目

详细参考:51单片机STC89C52RC------创建Keil项目-CSDN博客

四,代码

UART.c

cpp 复制代码
#include <REGX52.H>

/**
 * 函    数:UART1串口初始化
 * 参    数:无
 * 返 回 值:无
 */
void UART_Init(void)	//4800bps@12.000MHz
{
	PCON |= 0x80;		//使能波特率倍速位SMOD
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//清除定时器1之前配置的模式
	TMOD |= 0x20;		//重新设置定时器1模式
	TL1 = 0xF3;			//设置定时初始值
	TH1 = 0xF3;			//设置定时重载值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
	EA=1;				//允许总中断
	ES=1;				//打开IE、XCON寄存器
}
/**
 * 函    数:串口发送一个字节数据
 * 参    数:Byte 要发送的一个字节数据
 * 返 回 值:无
 */
void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;		//向发送区写数据
	while(TI==0);	//等待其他发送结束
	TI=0;			//程序手动复位
}

UART.h

cpp 复制代码
#ifndef __UART_H__
#define __UART_H__

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

#endif

Delay.c

cpp 复制代码
/**
 * 函    数:延时函数 毫秒
 * 参    数:ms 延时多少毫秒
 * 返 回 值:无
 */
void Delay_ms(int ms)	//@12.000MHz
{
	unsigned char data i, j;
	while(ms--)
	{ 
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}
/**
 * 函    数:延时函数 毫秒
 * 参    数:ms 延时多少毫秒
 * 返 回 值:无
 */
void Delay_us(int ms)	//@12.000MHz
{
	unsigned char data i, j;
	while(ms--)
	{ 
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}
/**
 * 函    数:延时函数  10微秒
 * 参    数:无
 * 返 回 值:无
 */
void Delay_10us(int _10us)	//@11.0592MHz
{
	unsigned char data i;
	while(_10us--)
	{
		i = 2;
		while (--i);
	}
}

Delay.h

cpp 复制代码
#ifndef __DELAY_H_
#defind __DELAY_H_ 
void Delay_ms(int ms);
void Delay_10us(int _10us);
#endif

1:设备向电脑串口发送HEX main.c

cpp 复制代码
#include <REGX52.H>  
#include "UART.h"
#include "Delay.h"

/**
 * 函    数:主函数
 * 参    数:无
 * 返 回 值:无
 */
void main()
{	  
	char Byte=0x00;	//定义一个发送数据
	UART_Init();	//串口初始化
	while(1)
	{
		UART_SendByte(Byte);	//发送数据
		Delay_ms(1000);			//延时1秒
		Byte++;					//数据自动加1
	}
}


/**
 * 函    数:uart1中断函数
 * 参    数:无
 * 返 回 值:无
 */
void uart1_interrupt() interrupt 4 
{
	//暂时不处理接收数据
}

2:让电脑串口工具控制单片机LED亮灭。同时让单片机反馈控制的结果。 main.c

cpp 复制代码
#include <REGX52.H>  
#include "UART.h"
#include "Delay.h"

/**
 * 函    数:主函数
 * 参    数:无
 * 返 回 值:无
 */
void main()
{	  	
	UART_Init();	//串口初始化
	while(1);
}


/**
 * 函    数:uart1中断函数
 * 参    数:无
 * 返 回 值:无
 */
void uart1_interrupt() interrupt 4 
{	
	if(RI==1)					//如果接收标志位为1,接收到了数据
	{
		P2=~SBUF;				//读取数据,取反后输出到LED
		UART_SendByte(SBUF);	//将受到的数据发回串口
		RI=0;					//接收标志位清0
	}	
}

五,代码编译、下载到51单片机

代码编译请参考

51单片机STC89C52RC------代码编译-CSDN博客

代码下载请参考

《51单片机STC89C52RC------STCAI-ISP代码下载-CSDN博客

相关推荐
代码游侠1 小时前
ARM开发——阶段问题综述(二)
运维·arm开发·笔记·单片机·嵌入式硬件·学习
DLGXY2 小时前
STM32——旋转编码器计次(七)
stm32·单片机·嵌入式硬件
羽获飞2 小时前
从零开始学嵌入式之STM32——3.使用寄存器点亮一盏LED灯
单片机·嵌入式硬件
浩子智控3 小时前
商业航天计算机抗辐射设计
单片机·嵌入式硬件
独处东汉6 小时前
freertos开发空气检测仪之输入子系统结构体设计
数据结构·人工智能·stm32·单片机·嵌入式硬件·算法
czy87874757 小时前
机智云 MCU OTA可以对MCU程序进行无线远程升级。
单片机·嵌入式硬件
麦托团子8 小时前
51单片机学习笔记17-红外遥控(外部中断)
51单片机
A9better9 小时前
嵌入式开发学习日志52——二值与计数信号量
单片机·嵌入式硬件·学习
日更嵌入式的打工仔10 小时前
(实用向)中断服务程序(ISR)的优化方向
笔记·单片机
想放学的刺客11 小时前
单片机嵌入式试题(第25)嵌入式系统可靠性设计与外设驱动异常处理
stm32·单片机·嵌入式硬件·mcu·物联网