【逗老师的无线电】BI1FQO手搓笔记:STM32直驱4G模组,打造极致精简MMDVM热点

📅 2026/7/15 4:15:36 👁️ 阅读次数 📝 编程学习
【逗老师的无线电】BI1FQO手搓笔记:STM32直驱4G模组,打造极致精简MMDVM热点

1. 从云DTU到硬核改造的进化之路

第一次接触MMDVM热点时,我用的是现成的4G DTU模块。这种"傻瓜式"方案确实省心——插上SIM卡,配置虚拟串口,五分钟就能让热点板联网。但用久了就发现痛点:DTU模块体积堪比火柴盒,额外供电线缆像蜘蛛网,整体功耗接近3W。最要命的是每次断电后,TCP连接配置都会丢失,必须重新用电脑发送AT指令。

后来尝试移远EC200模组直接对接热点板,尺寸缩小到邮票大小,功耗直降到1W以下。但AT指令配置流程依然繁琐:

  • 开机后手动发送AT+QICSGP=1,1,"UNINET"设置APN
  • AT+QIACT=1激活网络
  • 最后AT+QIOPEN建立TCP连接

某次野外通联时,我突然意识到:既然热点板主控是STM32F103,为什么不让它自己搞定这些操作?于是开始了这场"去掉中间商"的硬核改造。

2. STM32直驱4G模组的硬件魔术

2.1 引脚改造手术

大多数MMDVM热点板的UART1默认连接树莓派GPIO,我们需要将其改接到4G模组。以常见的HS_Hat热点板为例:

热点板引脚STM32F103引脚4G模组引脚
GPIO14(TXD)PA9UART_RX
GPIO15(RXD)PA10UART_TX
GNDGNDGND

实际操作时,建议用热风枪吹下排针,直接飞线连接。我曾因偷懒使用杜邦线,结果车辆颠簸导致接触不良,闹出"幽灵断网"的笑话。

2.2 电源优化方案

4G模组的瞬时电流可能超过500mA,推荐两种供电方案:

  • 方案A:改造热点板3.3V LDO,更换为SY8089等2A级DCDC
  • 方案B:从USB 5V直接取电,增加LC滤波电路(实测可降低射频干扰)

我的EC800模组在方案B下,通话时电压波动仅0.05V,比原厂设计更稳定。

3. 开发环境搭建的避坑指南

3.1 非典型Arduino配置

虽然使用Arduino IDE开发,但需要特殊配置:

  1. 安装STM32duino核心包
  2. 选择开发板类型:Generic STM32F1 series
  3. 具体参数设置:
    Board: STM32F103C8 Upload method: Serial CPU Speed: 72MHz Optimize: Smallest (default)

特别注意:必须勾选Upload Reset: Hardware Reset,否则刷机成功率不到50%。这个坑让我浪费了三小时查线路,最后发现是软件配置问题。

3.2 串口下载的玄学

热点板没有USB转串口芯片,需要外接USB-TTL工具。关键步骤:

  1. 将BOOT0引脚(热点板GPIO20)拉高
  2. 按复位键进入烧录模式
  3. 快速点击Arduino的上传按钮

如果总是超时,试试调整tools/Upload Speed为115200。我在Linux下实测57600更稳定,可能与驱动有关。

4. 固件魔改实战

4.1 MMDVM_HS代码解剖

juribeparada的原始固件中,关键流程在SerialPort.cpp

void CSerialPort::process() { // 原有串口数据处理 if (m_buffer[0] == 0xE0) handleHostFrame(); }

我们在IO.cpp的初始化阶段插入4G配置代码:

void CIO::startup() { // 新增4G初始化 g4G.init(); // 原有初始化 beginADF7021(); ... }

4.2 AT指令状态机实现

最核心的G4Module类实现:

class G4Module { public: void init() { m_state = STATE_INIT; m_lastCmdTime = millis(); } void process() { switch(m_state) { case STATE_INIT: if (sendAT("AT")) { m_state = STATE_CHECK_SIM; } break; case STATE_CHECK_SIM: if (sendAT("AT+CPIN?")) { if (strstr(m_buffer, "READY")) { m_state = STATE_SET_APN; } } break; // 更多状态处理... } } private: bool sendAT(const char* cmd) { Serial.print(cmd); Serial.print("\r\n"); m_lastCmdTime = millis(); return true; } enum States { STATE_INIT, STATE_CHECK_SIM, STATE_SET_APN, STATE_ACTIVATE, STATE_CONNECT, STATE_RUNNING }; char m_buffer[256]; States m_state; uint32_t m_lastCmdTime; };

实测发现移远模组启动需要3秒,因此每个状态需设置超时重试机制。我的方案是每秒重发指令,最多尝试5次。

5. 终极优化技巧

5.1 功耗控制黑科技

通过修改ADF7021.cpp的射频控制逻辑,在无通信时关闭射频前端:

void CADF7021::setIdle() { writeRegister(0x0C, 0x01); // 低功耗模式 digitalWrite(m_pttPin, LOW); }

配合4G模组的AT+QSCLK=1指令,整体待机功耗从1.2W降至0.3W。

5.2 看门狗增强稳定性

main.cpp中添加硬件看门狗:

void setup() { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); IWDG_SetPrescaler(IWDG_Prescaler_256); IWDG_SetReload(0xFFF); IWDG_ReloadCounter(); IWDG_Enable(); } void loop() { IWDG_ReloadCounter(); // 主循环代码 }

这个改进让我的热点在-20℃低温下连续运行30天无重启。记得在AT指令等待循环中也加入喂狗操作,否则网络差时会意外复位。

6. 成品实测数据

最终版性能指标:

  • 尺寸:48mm×32mm(不含天线)
  • 重量:18g
  • 工作电流:
    • 待机:80mA @3.7V
    • 通话峰值:300mA @3.7V
  • 建联时间:冷启动平均4.2秒
  • 通信延迟:DMR帧往返平均126ms

在北京市区实测,连续8小时DMR通话零掉线。最远在怀柔山顶与天津HAM通联,信号报告5/9。