简介:3DR Radio 固件源码是一套基于 Si1000 无线 MCU、C8051F930 控制芯片与 SI4432 射频收发器的 433MHz 数字电台开源实现,适合从事无线数传、嵌入式开发及无人机通信改造的学习者和工程师参考。压缩包共 82 个文件,以 C 源码与头文件(18 个 c、24 个 h)为主体,配合 Python 脚本、Makefile、CS 工程文件及上传工具等,完整覆盖固件构建与烧录流程,整体仅 230KB,轻量易读。目前已有 1058 人学习下载。源码中可深入研读无线协议栈、数据包封装与解析、错误检测与纠错算法,以及低功耗调度策略;同时附带的 SiKUploader 工具和 hex 文件也便于直接验证与二次开发。对想理解 3DR Radio 内部工作机制或基于 Si1000 系列做定制通信方案的学习者,这份开源资料提供了可运行的完整参考。 开始玩 3DR Radio 固件源码之前,我一直把它当成“一个能传数据的无线串口模块”来用。后来为了在一个果园巡检项目里做远距离无人机数传,不得不到源码层面改频点、改功率、改 MAVLink 处理逻辑,才真正把这套开源固件的底细摸了一遍。3DR Radio 的固件源码,核心就是基于 Arduino 平台跑的 SiK 协议栈,它把一颗 ATMega328P 单片机和一片 FSK 射频前端组合成一个完整的数传电台。这篇文章适合正在做无人机遥测、地面机器人通信、远程传感器回传的开发者,也适合想从源码层面理解“无线串口到底是怎么工作”的嵌入式入门者。我按自己踩坑后的顺序,把源码结构、编译烧录、参数定制和问题排查完整整理出来。
1. 先搞清楚这套源码到底跑在什么硬件上
1.1 3DR Radio 为什么值得自己编译固件
默认固件最大的优点是稳定,基本开箱即用。但默认固件的功能边界是固定的,遇到下面这些需求时,只靠 Mission Planner 的可视化配置页根本搞不定:想把中心频点切到自己当地合法频率段里的特定频点,想压低空中速率换取更远传输距离,想插入飞控私有协议或者自定义遥测帧,想在数据链路里加一层简单的认证加密逻辑。这些改动全部要落到固件源码上。3DR Radio 的源码基于 Arduino 工具链,门槛不算高,改起来风险也可控,再加上硬件本身很成熟,非常适合作为业余级无线通信项目的第一套可改造固件。我甚至见过有人用这套源码做农业环境监测站的数传回传,一台地面站轮询十几个节点,靠的就是改固件里的地址滤波和占空比策略。
1.2 源码对应的硬件平台与芯片参数
要改代码,先得知道它跑在什么硬件上。3DR Radio 的控制器是 ATmega328P,也就是 Arduino Uno 那颗 MCU,Flash 容量 32KB,SRAM 只有 2KB。射频前端用的是 RFM23 系列 FSK 收发芯片,常见工作在 433MHz 或 915MHz 频段。MCU 和射频芯片之间走 SPI,MCU 对外和飞控、地面站通信走串口。这套硬件方案和 Arduino Pro Mini 几乎同源,所以源码里大量直接调用 Arduino 的 Serial、SPI、EEPROM 库。必须提醒一点:ATmega328P 的 Flash 只有 32KB,而 SiK 固件编译出来通常占掉 25KB 到 30KB,意味着你加功能代码的空间非常有限。我自己曾经为加一个协议解析函数,反复精简字符串常量,最后还要靠 PROGMEM 把常量表搬进 Flash 才塞下。
1.3 我能拿来改出什么花样
源码级别能做的改动比想象中多。通信参数层面,可以改中心频率、发射功率、串口波特率、空中波特率,把这些值直接写死成自己项目的默认值,避免每次上电后再手工配置。协议层面,SiK 固件对 MAVLink 有专门的优化逻辑,可以根据流量自动调整无线占空比;如果你用的是私有协议,也能在数据帧处理函数里增加自己的帧类型。功能层面,可以在固件里加 RSSI 定时上报、信号质量指示灯逻辑,甚至做自动功率控制。工程层面,源码自带 Makefile 和 Arduino 工程两种构建方式,能接入团队的 CI 流程,烧录也可以通过脚本批量执行。对于做产品原型的人来说,这意味着你不用重新画板子,只要烧个自编译固件,就能把一个通用 3DR Radio 模块变成贴合自己项目需求的专用数传节点。
2. 固件源码目录结构与核心逻辑拆解
2.1 从仓库结构看工程布局
从 GitHub 拉下源码后,核心目录是 Arduino/Sik。主程序文件是 .ino 或 .pde 后缀,这是 Arduino 老式工程格式,说明整套代码最初就是围绕 Arduino IDE 构建的。工程里能看到几块核心代码:radio_process 负责无线收发状态机,uart_process 负责串口数据的收发缓冲,EEPROM 相关代码负责持久化保存配置,还有独立目录放置 MAVLink 协议库和射频芯片驱动。如果你是第一次打开这个工程,我建议不要从头读到尾,直接找到 setup、loop 两个入口,再顺着 radio_loop、uart_loop 这类子函数往下走。看源码时注意区分“配置逻辑”和“收发逻辑”:配置逻辑在 AT 模式下执行,收发逻辑在正常透传模式下执行,两者互相独立,理解这点之后整个代码脉络就清楚了。
2.2 AT 配置模式与 RT 透传模式的区别
这是刚接触源码时最容易混乱的点。AT 模式是配置模式,电台在启动后如果被特定引脚电平或按键触发,就会进入等待串口指令的状态,用户通过串口发送 ATI、ATP 之类的指令来读写内部参数,相当于电台化身为一个可交互的配置终端。RT 透传模式则是正常工作状态,电台把串口收到的数据封装成无线帧发送出去,另一端收到后再从串口输出,外部设备完全感知不到无线链路的存在。两个模式对应不同的代码分支,调试时如果发现发 AT 指令没反应,大概率是电台没成功进入 AT 模式。另一个相关概念是 AIR/GROUND 角色,空中端和地面端虽然运行同一套代码,但角色设置不同,避免两端同时占用发射通道。现场经常遇到“明明能连上但数据不通”的故障,查到最后往往是两端角色设成了同一个。
2.3 几个必须理解的源码关键模块
第一是数据缓冲管理。无线链路实际吞吐率低于串口速率,所以代码里维护了环形缓冲区,把来不及发的数据暂时存下来,缓冲区溢出标志位往往是排查丢包的起点。第二是收发状态机。无线收发不能同时进行,状态机负责在空闲、发射、接收之间切换,避免射频前端饱和。第三是自动功率控制。如果版本支持,代码会根据对端 RSSI 动态调整发射功率,这既省电又减少邻频干扰,但也带来了一个隐蔽问题:你以为发射功率恒定,实际它可能被算法压低了,后面排查故障时很容易忽略这一点。第四是看门狗。固件里启用了 watchdog 定时器,射频驱动一旦卡死会被强制复位,保证长期运行不进入死循环。把这四个模块读懂,你基本就掌握了这套数传固件的核心。
3. 本地编译 SiK 固件的完整流程
3.1 编译环境搭建:Arduino IDE 与 Makefile 二选一
我在 Windows 和 Ubuntu 上都编过,整体体验差别不大。最省心的组合是 Arduino IDE 1.8.x 搭配仓库自带 Makefile,因为 IDE 主要负责库管理和板型配置,Makefile 负责一键产出 HEX 文件。板型选择上,一定选“Arduino Pro or Pro Mini”,处理器选 ATmega328P (3.3V, 8MHz),这一步别选错。为什么强调 8MHz?因为 3DR Radio 板上的 328P 外接晶振一般是 8MHz,选成 16MHz 能编过但烧进去后串口波特率全部错乱,你根本找不到原因。如果你用 Makefile 方式,需要先把 arduino 的二进制路径配置好,然后 make 就能生成 HEX。编译过程中会看到大量警告,多数是“变量声明了但没用”这类,不影响生成结果,可以先忽略。
3.2 动手改源码:频率、功率、串口速率这些默认参数藏在哪
拿到源码后最常改的就是几个默认配置。在我的果园巡检项目里,433MHz 版本在城区周边使用,默认频点刚好和附近一个数传设备撞了,于是我把中心频率改到经过扫频确认的干扰较少频点。发射功率方面,短距测试时没必要满功率,我把默认发射功率从 20dBm 降到 10dBm,既省电又降低了底噪抬升。这些默认值通常在源码头文件里以宏定义形式出现,比如 DEFAULT_TXPOWER、DEFAULT_FREQUENCY、DEFAULT_SERIAL_BAUD,但也有的版本把配置集中在一张表里。改的时候要注意频率和空中波特率经常联动,改了中心频率就必须回看射频驱动里的分频系数,否则可能出现“频率对了、空中速率完全不对”的怪问题。改完重新编译烧录后,建议用配置工具回读确认,防止寄存器值被其他初始化逻辑覆盖。
3.3 把编译好的 HEX 写入模块:串口与 ICSP 两种方式
烧录方式分两种,我两种都用过。第一种是保留 bootloader 情况下的串口烧录,用 FTDI 模块把 TX、RX、GND 接到 3DR Radio 的调试口。这里有个几乎人人都犯的错:模块丝印上的 RX 是模块自己的接收脚,所以 FTDI 的 TX 必须接模块的 RX。进入 bootloader 的方式通常是按住模块上的按钮再上电,具体时机和版本有关,多试几次就能找到手感。第二种是 ICSP 烧录,用 USBasp 连接电路板上的编程口,不依赖 bootloader,量产时更可靠。上传完成后用配置工具读取固件版本,确认字符串变成你自编译版本的内容就说明烧录成功。还有一个重要细节:3DR Radio 是 3.3V 逻辑电平,FTDI 如果默认输出 5V,要改成 3.3V 模式,长期用 5V 会缩短射频前端寿命。
4. 实战:一套适用于远距离无人机的固件定制方案
4.1 需求确认与参数选型
拿我实际做过的项目举例:多旋翼在郊区果园巡检,飞行半径大概 3 到 5 公里,遥测数据不追求高带宽,但位置和控制数据要求低延时、高可靠。这个场景下,空中速率不需要太高,我把空中波特率设在 57600,让链路余量更大;串口对飞控和地面站的速率也保持 57600 与之一致。中心频率根据现场无线电环境扫频后,选在干扰最少的频段;发射功率设为 17dBm,既保证距离,又不至于长时间悬停时模块过热。这套参数如果只靠默认固件,能改的只有功率和串口速率,频率基本动不了,但通过源码修改后,整体抗干扰能力和距离都明显提升。
4.2 涉及源码改动的核心位置与理由
这个项目里我实际改了五处:默认频率、默认功率、默认空中波特率、MAVLink 消息透传优先级,以及开机自检的 RSSI 阈值指示灯提示。改频率、功率和波特率相对直接,关键是集中在配置文件里改,不要散落在各个函数里。改 MAVLink 透传优先级要动数据帧处理函数,这一步要非常小心,因为涉及队列重组和帧类型判断,改完必须做回环测试,确保没有丢包头或错帧。开机自检的 RSSI 阈值逻辑相对独立,只影响指示灯状态,不影响数据链路。我个人建议把每次修改记录到项目文档里,表格列清楚“改了哪个文件、哪个宏、为什么改”,否则半年后自己回来看代码都容易犯嘀咕。
下面是当时整理的一份参数速查表,你直接照着填自己的值就行:
| 参数项 | 默认值参考 | 定制注意事项 |
|---|---|---|
| 中心频率 | 433MHz / 915MHz | 服从当地无线电法规,扫频后确定 |
| 发射功率 | 20dBm | 城区短距可降到10dBm,兼顾散热 |
| 串口波特率 | 57600 / 115200 | 与飞控和地面站软件保持一致 |
| 空中波特率 | 57600 | 降低可提升距离,但增加传输时延 |
| Net ID | 25 | 地面端、空中端必须一致 |
| 角色设置 | AIR / GROUND | 两端不能相同,否则收发冲突 |
4.3 重新编译烧录与电台配置回读
改完代码后重新 make,生成的 HEX 文件用 USBasp 烧录。每次烧录前先把模块断电,避免热插拔导致芯片进不了 ISP 模式。烧录完成后,我用 Mission Planner 的 Radio Setup 页面或串口终端依次确认固件版本字符串、中心频率、发射功率、串口波特率、Net ID。确认无误后接上飞控和地面站,在户外做地面拉距测试。测试时记录不同距离下的 RSSI 和丢包率,比如 1 公里处 RSSI 大概多少、3 公里处是否还能稳定通信,这些数据后面再优化固件时非常有用。整个流程走下来,从改代码到落地测试,一个下午基本能完成。
5. 踩坑实录与常见问题排查
5.1 编译阶段:库版本冲突与 Flash 容量溢出
编译阶段最典型的问题是 MAVLink 库版本和源码不匹配,导致大量协议类型未定义。我的处理方式是直接用源码仓库里自带的 modules 目录,把它指定到 Arduino 库文件夹,而不是去网上下最新版,因为最新版 API 往往变了。另一个经典错误是添加自己功能代码后 Flash 溢出,链接器直接报错。这种时候需要精简功能,或者把字符串常量移进 PROGMEM。还有一次我改了默认频率,但没同步改射频驱动里的分频系数,结果空中速率完全不对,后来才意识到 SiK 源码里频率和波特率是联动配置的,改一必须查另一个,这个坑非常隐蔽。
5.2 烧录阶段:串口连不上与线序反向
烧录阶段最常见的问题是 FTDI 连上模块后,串口终端打不出任何字符。排查步骤建议这样走:先量 VCC 和 GND 是否正常,再确认 FTDI 的 TX 是否接了模块的 RX,因为 RX/TX 交叉是个经典错误。还有一个容易忽略的地方是调试口的 DTR 信号,AT 配置模式的进入可能依赖它,断了之后无论怎么发 AT 指令都没反应。如果一直无响应,可以按住模块上的按钮再插 USB,多试几次。如果走 ICSP 烧录,注意 USBasp 和模块之间的排针方向,方向反了有可能烧坏芯片,连接前务必对照针脚定义核实一遍。
5.3 上电后信号表现异常的排查方向
电台能连上但距离很差,我的排查顺序是:天线是否拧紧、天线频率是否匹配模块频段、发射功率设置是否被覆盖、空中波特率是否过高。3DR Radio 的发射功率如果被配置工具改成最低档,距离会骤降一半以上,但这往往不是硬件问题,纯粹是配置被覆盖了。另一个常见现象是两端指示灯规律闪烁,但地面站没有任何数据,这大概率是两端角色撞了,或者 Net ID 不一致。把空中端改成 AIR、地面端改成 GROUND,再把 Net ID 统一,问题基本就能解决。排查时建议先用短距离、低波特率建立基线,再逐步增加距离和速率,这样能快速定位是无线链路问题还是配置问题。
5.4 经验清单:哪些改动值得做,哪些别轻易碰
根据我的经验,值得做的改动按优先级排序:第一,把默认频点改成当地合法且干扰较少的频段;第二,把默认发射功率调到项目需要的合理值,避免每次手动配;第三,把串口调试信息开关做成编译宏,方便现场诊断;第四,针对私有协议增加特定数据帧解析。而射频芯片底层时序、看门狗复位逻辑、自动功率控制核心参数这三个模块,我建议没有充分把握不要轻易改。它们一旦改错,症状非常隐蔽,比如只在高温或长时间运行后出现随机断链,排查成本极高。如果实在要动,先在 git 里开分支备份,再做单变量测试,千万别同时改多个参数。
我个人在折腾完这套源码之后,最大的体会是:3DR Radio 的硬件方案本身已经很成熟,但把固件源码吃透之后,你得到的是一套可移植的无线数传设计思路——从串口缓冲管理到射频状态机,从 MAVLink 适配到 EEPROM 参数存储,这些设计在后续其他嵌入式项目里同样适用。最后再分享一个小习惯:每次编译完固件,把生成的 HEX 文件和源码 commit hash 打个压缩包存档,命名里带上日期和频点,避免半年后自己都分不清哪版固件带了什么功能。这个动作看着不起眼,但能让你在项目复现和故障回溯时省下半天时间。
本文还有配套的精品资源,点击获取