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博客

相关推荐
m0_7482409122 分钟前
OpenMV与STM32通信全面指南
stm32·单片机·嵌入式硬件
Cchengzu2 小时前
阿里巴巴2017实习生笔试题(二)
stm32·单片机·嵌入式硬件
重生之我是数学王子6 小时前
单片机 STM32入门
stm32·单片机·嵌入式硬件
qq_459730039 小时前
4-3 MCU中ARM存储器的作用
arm开发·单片机·嵌入式硬件
重生之我是数学王子13 小时前
点亮核心板小灯 STM32U575
stm32·单片机·嵌入式硬件
end_SJ13 小时前
初学stm32 --- 定时器中断
stm32·单片机·嵌入式硬件
南城花随雪。13 小时前
单片机:实现数码管动态显示(0~99999999)74hc138驱动(附带源码)
单片机·嵌入式硬件
南城花随雪。15 小时前
单片机:实现信号发生器(附带源码)
单片机·嵌入式硬件
灵槐梦17 小时前
【速成51单片机】2.点亮LED
c语言·开发语言·经验分享·笔记·单片机·51单片机
三月七(爱看动漫的程序员)17 小时前
HiQA: A Hierarchical Contextual Augmentation RAG for Multi-Documents QA---附录
人工智能·单片机·嵌入式硬件·物联网·机器学习·语言模型·自然语言处理