最近看了下 nanopb

作者:Felix(Haro 协作整理)

这两天顺手了解了一下 nanopb,感觉它挺适合嵌入式通信场景,尤其是那种既想把消息结构整理清楚,又不想把通信实现做得太重的项目。

做设备通信时,大家经常会接触到 ModbusCANopen 这类成熟方案。它们的优势一直都很明确:标准化程度高、生态成熟、很多场景里可以直接落地。尤其在工业环境里,这类协议最大的价值就是“大家都认”,设备之间也更容易互通。
所以如果项目目标本身就是和现有工业系统兼容,或者希望尽量采用成熟标准,那 ModbusCANopen 依然是很稳的选择。

但如果换一个角度看,nanopb 走的是另一条路。
它本质上是一个面向嵌入式系统的 Protobuf 轻量级 C 实现,重点在于小代码体积、低内存占用,更适合微控制器和其他资源受限环境。它不像 Modbus、CANopen 那样是一整套完整协议,而更像是在解决“消息怎么定义、怎么编码、怎么跨平台处理”这件事。

我觉得这里一个很有意思的区别是:
Modbus 更像寄存器思维,nanopb 更像消息思维。

用 Modbus 时,很多数据最终都要被拆成寄存器,遇到 32-bit 整数、浮点数、字符串或者更复杂的结构时,往往就得自己约定高低字节、高低字、地址映射这些细节。这样做当然没问题,而且工业里已经非常成熟,但代价就是不同平台之间经常要来回转换。
nanopb 的思路更直接一些:消息里有哪些字段、字段是什么类型,都在定义里写清楚,编码规则也统一。这样在 MCU、上位机、网关甚至云端之间处理数据时,通常会更自然,跨平台也更轻松一些。

当然,这不代表 nanopb 就能替代 Modbus 或 CANopen。
它们解决的问题层次并不完全一样:

  • Modbus:偏向通用、成熟、寄存器式工业通信;
  • CANopen:偏向完整设备模型和更系统化的总线协议;
  • nanopb:偏向结构化消息表达和轻量级跨平台编码。

所以如果项目更在意的是工业兼容性和标准化接入,那 Modbus、CANopen 还是很有优势;
但如果项目更看重的是通信内容本身的结构化表达、跨平台处理的自然性,以及资源占用控制,那 nanopb 就会显得很顺手。

我自己的感觉是,后面如果是做一套偏自定义、需要和上位机或多端系统协同的通信方案,我会更愿意认真考虑 nanopb 这种思路。它不一定是最省事的,也不是现成生态最强的,但在“表达清晰”和“跨平台处理舒服”这件事上,确实有它自己的优势。
至于 ModbusCANopen,我反而会把它们看成另一类更偏工程标准化的选择:当场景需要兼容现有体系时,它们依然很强;只是如果通信模型本身就是自己定义的,那 nanopb 这种方式看起来会更合胃口一些。

项目地址:
https://github.com/nanopb/nanopb