1. CMS32串口通信概述:串口通信基本原理、CMS32单片机UART模块特性、串口通信协议栈概览

1.1 串口通信,到底在聊什么?

串口通信,说白了就是两个设备之间,通过一根或两根数据线,一位一位地传数据。你想想看,单片机要跟传感器说话,要跟电脑上的串口助手聊天,靠的就是这个。

我刚开始做嵌入式那会儿,总觉得串口太简单了,不就是TX发、RX收嘛。直到有一次,一个设备在强干扰环境下死活收不到完整数据,我才意识到——看似简单的串口,坑其实不少。

串口通信的核心参数,就这几个:

  • 波特率:每秒传多少位。9600、115200最常见。两边必须一致,否则就是乱码。
  • 数据位:一般是8位,也有5、6、7位的,但8位是主流。
  • 停止位:1位或2位。告诉接收方“这包数据结束了”。
  • 校验位:奇校验、偶校验、或者无校验。我一般用无校验,省事。

关键点:串口是异步通信,没有时钟线。两边靠约定的波特率来同步。所以波特率不准,数据就全歪了。

1.2 CMS32的UART模块,有什么特别的?

中微CMS32系列单片机,内置了多个UART模块。我手头常用的CMS32M53xx系列,就有3路UART。嗯,这里要注意——不是所有引脚都能当UART用,得看数据手册的引脚复用表。

CMS32的UART模块特性,我列个表,你一看就明白:

特性 说明
支持波特率范围 300 ~ 115200 bps(实测可到230400,但稳定性看布线)
数据位 7位或8位
停止位 1位或2位
校验模式 无校验、奇校验、偶校验
FIFO深度 发送和接收各16字节硬件FIFO
中断支持 发送完成、接收完成、接收超时、错误中断
自动波特率检测 部分型号支持,我一般不用,手动设更稳

我个人习惯,只要项目不要求极端省电,就把FIFO打开。16字节的FIFO能大大减少CPU中断频率,尤其在高波特率下,效果很明显。

小技巧:CMS32的UART模块,接收FIFO触发阈值可以设成1、4、8、14字节。我一般设成8字节,这样既不会太频繁进中断,也不会等太久才收到数据。

1.3 串口通信协议栈,不只是“发数据”

很多人以为串口通信就是“发什么收什么”。其实不然。裸的UART只保证字节级别的传输,但你要传一个“温度值25.3℃”,怎么知道哪几个字节是一包?哪几个字节是校验?

这就需要一个通信协议栈。说白了,就是在原始字节上,加一层“包装规则”。

我参与过一个项目,两个设备之间用串口传控制指令。一开始没做协议栈,结果偶尔出现粘包、丢字节,整个系统就乱套了。后来老老实实加了帧头、帧尾、校验,问题全解决。

一个典型的串口协议栈,通常包含这几层:

  1. 物理层:就是UART硬件,负责电平转换、波特率、字节收发。
  2. 数据链路层:定义帧结构——帧头、数据长度、数据体、校验、帧尾。
  3. 应用层:解析数据体里的具体含义,比如“0x01代表读取温度”。

避坑指南:我曾经在一个产品里,帧头用了0xAA 0x55,结果数据体里也出现了0xAA,导致接收方误判帧头。后来我改用“帧头+帧头取反”的方式,才彻底解决误判问题。

下面这张图,是我自己总结的串口协议栈分层结构,你看一眼就清楚了:

串口通信协议栈分层结构图 串口通信协议栈分层结构 应用层 解析数据含义:指令ID、数据值、状态码 数据链路层 帧头 + 长度 + 数据体 + 校验 + 帧尾 物理层 UART硬件:波特率、电平、TX/RX引脚 每一层只关心自己的事,上层不关心下层怎么传,下层不关心上层传什么

1.4 帧结构,到底长什么样?

我常用的帧结构,是这样的:

帧头(2字节) + 数据长度(1字节) + 命令字(1字节) + 数据体(N字节) + 校验(1字节) + 帧尾(2字节)

举个例子:

AA 55 05 01 25 03 E8 0F 0D 0A
│   │  │  │  │   │   │  │   │
│   │  │  │  │   │   │  │   └─ 帧尾(0x0D 0x0A)
│   │  │  │  │   │   │  └─ 校验(累加和)
│   │  │  │  │   │   └─ 数据体(0x03 0xE8 = 1000)
│   │  │  │  │   └─ 数据体(0x25 = 37)
│   │  │  │  └─ 命令字(0x01 = 读取温度)
│   │  │  └─ 数据长度(0x05 = 5字节)
│   │  └─ 帧头(0x55)
│   └─ 帧头(0xAA)

这个结构,我在好几个项目里复用,稳定得很。你刚开始做串口协议,可以直接拿这个框架去改。

核心原则:帧头要足够特殊,帧尾要方便检测,校验要覆盖整个数据体。缺一个,就可能出问题。

1.5 波特率怎么选?我的经验

波特率的选择,其实是个权衡。我一般这么选:

  • 9600:抗干扰强,线长能到十几米。适合传感器、工业现场。
  • 115200:速度够快,但线长别超过2米。适合板级通信、调试。
  • 460800以上:除非你布线很好、距离很短,否则别轻易用。我吃过亏。

为什么会这样?因为波特率越高,每个bit的时间越短,对信号上升沿、下降沿的要求就越高。线一长,信号就变形了。

建议:调试阶段用115200,速度快,省时间。产品定型后,根据实际线长和干扰环境,再决定要不要降速。

1.6 本章小结

串口通信,说难不难,说简单也不简单。CMS32的UART模块功能挺全的,FIFO、多种中断、可调参数,基本能满足大部分场景。关键是要把协议栈搭好,别裸着发数据。

嗯,这一章就聊到这儿。你先把这些基础概念消化掉,后面我们就要动手写代码了。