目的/效果
实现单片机串口与电脑串口工具进行数据通讯,
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博客》