一、串口通信基础:RS232/RS485/TTL电平标准、波特率、数据位、停止位、校验位详解

做嵌入式开发这么多年,串口通信是我打交道最多的接口之一。说它基础吧,确实基础;但要说坑多不多?我踩过的坑能写满一本小本子。今天咱们就把串口通信的底裤扒干净,从电平标准到帧格式,一个一个说透。

1.1 三种电平标准:TTL、RS232、RS485

先问个问题:为什么要有这么多种电平标准?直接统一用一种不好吗?嗯,这个问题我当年也问过师傅。答案很简单——应用场景不同,需求就不同。

TTL电平(3.3V / 5V)

这是单片机之间最常用的电平。逻辑1对应高电平(3.3V或5V),逻辑0对应低电平(0V)。说白了,就是芯片内部直接用的那种。

我记得刚入行时,拿一个5V的Arduino去接一个3.3V的ESP8266模块,结果烧了。后来才知道,TTL电平虽然简单,但电平不匹配会烧芯片。现在我做设计,凡是不同电压域之间通信,必加电平转换芯片。

⚠️ 避坑指南: 我曾经因为偷懒,直接用电阻分压代替电平转换,结果在高波特率下数据全是乱码。电平转换芯片(如TXS0108、74LVC4245)该用就得用,别省那几块钱。

RS232电平(±12V / ±5V)

RS232是老祖宗级别的串口标准。它的逻辑1是负电压(-3V ~ -15V),逻辑0是正电压(+3V ~ +15V)。为什么搞这么复杂?因为抗干扰。正负电压的摆幅大,噪声容限就高。

我最早接触RS232是在调试一台老式工控机时。那台机器距离电脑有15米,用TTL直接拉线根本不行,换成RS232后稳如老狗。不过现在RS232用得少了,主要是它速率低(最高115200bps),而且只能点对点通信。

RS485电平(差分信号)

RS485是我在工业现场用得最多的标准。它用两根线(A和B)的电压差来表示数据:A-B > 200mV 为逻辑1,A-B < -200mV 为逻辑0。

你想想看,差分信号有什么好处?共模抑制。两根线受到的干扰几乎一样,相减之后干扰就被抵消了。我在一个电机变频器旁边拉过300米的RS485总线,数据一点没丢。换成RS232?早废了。

📌 一句话总结:
TTL:板级通信,距离<1米
RS232:短距离(<15米),点对点
RS485:长距离(>100米),多节点(最多256个)

1.2 波特率:通信的节拍器

波特率就是每秒传输的符号数。说白了,就是通信双方约定好:每秒钟发多少个bit。

常见的波特率有:9600、19200、38400、115200、921600。为什么都是这些数?因为它们都是2的整数次幂的倍数,用晶振分频容易得到。

我习惯用115200作为默认波特率。为什么?因为9600太慢,传个固件要等半天;921600又太快,很多便宜的USB转串口芯片(比如CH340G)在高波特率下会丢包。115200是个折中,速度够用,稳定性也有保障。

💡 小技巧: 如果你不确定设备支持的最高波特率,可以从9600开始试,逐步往上加。我曾经调试一个国产GPS模块,标称支持115200,结果死活不通,降到38400就正常了。嗯,标称归标称,实测才是真理。

1.3 数据位:一次传多少数据

数据位就是每个数据帧中实际承载的数据位数。常见的有7位和8位。

  • 7位数据位:用于传输ASCII字符(0-127),老式设备常用
  • 8位数据位:现代设备的标准,可以传输0-255的任意字节

我个人建议:除非你确定对方只传ASCII,否则一律用8位。为什么?因为8位数据位可以传二进制数据,灵活性更高。我在项目中遇到过一台设备,手册上写的是7位数据位,结果传二进制文件时总是出错,后来发现是数据位设置不对。

1.4 停止位:帧结束的标志

停止位就是每个数据帧结束时的空闲时间。常见的有1位、1.5位和2位。

  • 1位停止位:最常用,效率最高
  • 1.5位停止位:很少见,某些老式电传打字机用
  • 2位停止位:用于时钟精度不高的场景,给接收端更多时间处理

我一般都用1位停止位。只有在通信距离特别长(比如RS485拉了几百米)或者时钟精度不够时,才会考虑用2位停止位。你想想看,停止位越长,传输效率越低,但容错性越好。这是个取舍问题。

1.5 校验位:数据正确性的保险

校验位是用来检测数据传输过程中是否出错的。常见的有三种:

校验方式 原理 适用场景
无校验(None) 不添加校验位 短距离、低干扰环境
奇校验(Odd) 数据位+校验位中1的个数为奇数 对数据完整性有一定要求
偶校验(Even) 数据位+校验位中1的个数为偶数 与奇校验类似,看协议要求

说实话,奇偶校验只能检测奇数个bit的错误,检测能力很有限。我在实际项目中,如果数据重要,我会在应用层加CRC校验,而不是依赖硬件校验位。比如Modbus协议就用了CRC16,比奇偶校验靠谱得多。

⚠️ 避坑指南: 我曾经遇到过一台设备,手册上写的是"无校验",但实际通信时必须设置成"偶校验"才能正常工作。后来发现是设备固件有bug。所以,不要完全相信手册,用逻辑分析仪抓一下波形最靠谱。

1.6 知识体系总览

下面这张图把串口通信的核心知识点串起来了。你可以把它当作一个快速参考图:

串口通信知识体系 串口通信 电平标准 TTL (3.3V/5V) RS232 (±12V) RS485 (差分) 帧格式参数 波特率 数据位 (7/8) 停止位 (1/1.5/2) 校验位 流控制 典型应用场景 单片机调试 GPS/蓝牙模块 工业总线 (Modbus)

1.7 实战中的参数配置

说了这么多理论,咱们来点实际的。下面是我常用的串口配置代码(以STM32 HAL库为例):

// 串口配置结构体
UART_HandleTypeDef huart1;

// 初始化函数
void MX_USART1_UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;      // 波特率
    huart1.Init.WordLength = UART_WORDLENGTH_8B;  // 8位数据位
    huart1.Init.StopBits = UART_STOPBITS_1;        // 1位停止位
    huart1.Init.Parity = UART_PARITY_NONE;         // 无校验
    huart1.Init.Mode = UART_MODE_TX_RX;            // 收发使能
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;   // 无硬件流控
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    
    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
        Error_Handler();  // 初始化失败,进入错误处理
    }
}

这个配置是我最常用的模板。8N1(8数据位、无校验、1停止位)是串口通信的"通用语言",绝大多数设备都支持。

💡 调试小技巧: 如果你用串口助手调试时发现数据全是乱码,先检查波特率对不对。如果波特率对了还是乱码,再检查数据位和校验位。我一般会先用逻辑分析仪抓一下波形,数一数每个字节的bit数,这样最直观。

好了,串口通信的基础知识就讲到这里。这些内容看着简单,但每一个参数背后都有它的设计考量。下次你配置串口时,不妨想想:为什么选这个波特率?为什么用8位数据位?想明白了,你就算真正入门了。

可可精品资料库