一、串口通信基本概念

1.1串口通信是什么

        串口通信是单片机与外部设备(如PC、传感器、其他单片机)进行数据交换的常用方式。

1.2通信协议分类

        1.2.1按数据传输方式分串行通信和并行通信

串行通信:数据多位的进行发送和接收,速率高但传输线多,成本高。

并行通信:数据按一位一位的顺序进行发送和接收,速率慢但传输线少,成本低。

        1.2.2按数据传输方向分单工、半双工、全双工通信

单工通信:一条传输线,数据传输方向是单方向的,发送端与接收端也是固定的。

半双工通信:一条传输线,数据可以双向进行传输,但不能两个方向同时进行传输。

全双工通信:两条传输线,数据可以同时在两个方向进行传输。

        1.2.3按数据同步方式分异步通信和同步通信

同步通信:发送端传输数据同时还发送同步时钟信号,接收端根据时钟信号来同步接收数据。

异步通信:无同步时钟信号,依赖波特率和数据帧格式实现同步。

        1.2.4按电平标准分类

TTL电平:直接使用处理器电平(如5V或3.3V),+5v表示1,0v表示0

RS-232协议:-3~-15v表示1,+3v~+15v表示0,RS - 232的通信距离相对较短,一般在15米左右。

RS-485协议:一种用于多点通信的串口协议。它采用差分信号传输方式,即使用两根信号线来传输数据,这两根线上的信号极性相反。两线压差+2v~+6v表示1,-2v~-6v表示0

二、单片机的串口通信

2.1单片机常见通信接口

还有CAN,USB等。

2.2UART(Universal Asynchronous Receiver Transmitter,通用异步收发器)

51单片机有一个UART,共有四种工作模式:

数据帧格式:

  • 1位起始位(低电平)→ 5-9位数据位(通常8位)→ 1位校验位(可选)→ 1-2位停止位(高电平)。

        例如:起始位+数据位+无校验+停止位--->共10位构成一帧

波特率:每秒传输的码元(符号)数量(如9600、115200),波特率决定串口数据传输速度。

比特率:‌比特率 = 波特率 × 单个码元对应的二进制位数‌。

2.3串口相关的寄存器

2.3.1SCON串口寄存器(Serial Control,地址 0x98)

        控制串口工作模式和状态标志

配置SM0/SM1组合,形成四种工作模式(如2.2)。

2.3.2PCON电源寄存器(Power Control,地址 0x87)

        SMOD(PCON.7):波特率加倍位(1=波特率×2,仅模式1/3有效)。

2.3.3SBUF串口数据缓冲器(Serial Buffer,地址0x99)

        发送和接收共用,写入数据启动发送,读取数据获取接收内容。

2.4波特率的计算和配置

模式0:同步移位寄存器,波特率=SYSclk/12

模式2(波特率固定):SMOD 为0或1,波特率=SYSclk/64或SYSclk/32

模式1/3(波特率可变):要开启定时器1(一般使用模式2,8位自动重装工作),        

                                        波特率=(2^{SMOD}/32)x定时器1溢出率

 定时器1溢出率计算:

三、串口的配置流程

3.1写串口初始化函数

        配置SCON寄存器,选择串口工作模式和接收使能

        配置PCON寄存器,选择波特率是否加倍,0x80或0x00

        配置定时器1,启动定时器1,禁止定时器1中断(ET1=0)

        开启中断开关EA,ES

3.2写串口中断服务函数(也是用来接收数据)

中断响应时序:

1.接收完成 → 2. RI=1 → 3. 中断触发 → 4. 跳转到ISR → 5. 清除RI → 6. 读取数据 → 7. 返回主程序。

3.3写串口发送数据函数

3.4 示例

接下来模式1来配置串口:

#include<reg51.h>
void UART_init()  //串口初始化函数
{
 SCON = 0x50; //模式1,允许接收使能
 TMOD = 0x20; //开启定时器1模式2
 TH1 = 0xFD; //设置初始值
 TL1 = 0xFD; //设置重装值
 TR1 = 1;    //启动定时器1
 ET1 = 0;    //定时器1禁止中断
 ES = 1;     //开启串口中断
 EA = 1;     //开启总中断
}
void UART_send(unsigned char data)   //串口发送数据函数
{
 SBUF = data; //写入数据
 while(!TI);  //等待发送完成标志(TI=1)
 TI = 0;      //清除发送标志
}
void main()  //主函数
{
 UART_init();
   while(1)
    {
     UART_send(1);
     }
}
void UART_ISR() interrupt 4   //串口中断函数(用来接收数据)
{
   if(RI)  //等待接收标志
    {
     RI = 0;  //清除接收标志
     unsigned char rec = SBUF; //读取接收数据,写入SBUF
     UART_send(rec);  //处理数据,例如回显
     }
 

}

可以用stc-isp的串口助手来查看发送/接收数据,注意串口号和波特率要选择一致。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐