项目文档
本项目使用 ESP32C3 主控,结合 ML307C LTE模组实现的基于LTE网络的寻呼机/传呼机/BB机。系统通过 LTE 控制信令与 IMS 通道接收短消息,实现 短信的接收、存储、显示及转发 等功能,支持 SMS over NAS 与 SMS over IP(IMS) 两种短信承载方式,具备良好的网络兼容性与可靠性。
固件功能
✅ 验证码内容自动识别并显示服务商
✅ 支持接收设备关机期间的短信
✅ 对于长短信内容实现自动组合
✅ 接收显示日期,时间,电话,短信内容自动滚屏播放
✅ 支持将接收到的短信内容转发到HTTP网络中,借助API实现微信推送,邮箱推送等(需要网络)
✅ 支持将接收到的短信内容借助SMS转发到另一号码中(无需网络)
✅ 接收界面可通过按键打断自动滚屏,改为手动滚屏和接收确认
✅ 开机时播放音效,来信时提醒
✅ 收到消息时开启背光,消息已读后关闭
✅ 支持RNDIS网卡,随时4G上网
✅ 联网后进入192.168.4.1进入后台管理页
✅ 支持对转发的功能配置
✅ 支持对提示音的功能配置
✅ 支持对背光的功能配置
✅ 支持收件箱功能,显示接收历史消息
项目参数
✅ ESP32C3 系列主控,内置 WiFi 功能,实现HTTP转发服务
✅ 采用ML307C LTE模组,实现SMS接收及转发,实现获取实时时间
✅ 使用ST7920驱动的128x32 LCD模组,5V供电,使用U8G2驱动,实现中文显示
✅ 采用IP5306、JM5359及ME6217C33M5G,实现对屏幕,LTE模组及MCU的供电
硬件设计
主控选用 ESP32C3系列 模组,集成 WiFi 功能,提供丰富的 GPIO 接口。 板载 USB 转串口芯片,方便程序下载和调试。
本项目的烧录方式是USB烧录,因为硬件串口需要完全用于LTE模组通讯。如果采用全新的ESP32C3模组,首次烧录时需要先按住BOOT键-点击RST键-松开BOOT键即可进入烧录模式,否则串口会一直跳。本项目选用USB烧录方案,但此方案需要注意布局布线、信号干扰及等长类差分问题,好处是无需烧录器,无需USB转串口模块,直接使用TypeC线上电后即可出现端口号。
MCU部分采用ME6217C33M5G LDO供电,上游电源来自IP5306升压输出的5V 2.4A,足矣驱动ESP32C3。
LTE模组选用ML307C,此模组功能很多,除了LTE功能外,也可做IO扩展功能,带有ADC,PWM等功能,模组PWR部分已配置4.7K上拉实现开机自启动,USIM的IO连接SIM卡座,USIM1还可接个ESIM来切卡,但本项目考虑布局和焊接问题所以去除。考虑到ML307C封装的焊接问题,非必要焊盘均以替换成丝印,方便走线同时也能避免新手焊接造成底部连锡,仅需焊接最外围邮票孔即可。
ML307C系列模组支持PPP拨号通讯协议,可通过USB走RNDIS实现4G网卡上网功能,通过接入TYPEC后主机设备会识别成有线网卡,如未识别需手动在设备管理器切换驱动。需要注意的是使用此功能则必须焊接模组底部USB信号线焊盘,建议使用加热台或风枪。
LTE模组电源供电依照数据手册要求供应3.9V电路,因电路较大所以选用DCDC降压电路,最大供应电流2A,符合数据手册要求。
屏幕部分选用LCD 128X32 ST7920驱动,背光部分通过MOS管控制,使用SPI协议驱动,所以中间DB的IO没有使用,封装上留空用于走线。
选用IP5306管理芯片,支持升压,路径管理等功能的充放一体芯片,为器件提供电源及为电池充电。此IC需要注意,必须焊接底部EPAD,PCB设计中已为底部开插件焊盘孔,可使用烙铁锡丝焊接。 电源键按键对应PCB中右下角按键中最右侧的按键,单击开机,双击关机。
三个按键分别对应PCB中右下角按键从左往右的三个功能键,最右侧的按键是IP5306的电源键。扬声器这里实际用的是无源蜂鸣器,使用扬声器也可以。
软件开发
完整源码请在附件查看
本项目采用功能模块化。
- config_manager.h/.cpp: 数据存储器类
- config.h: IO定义及软件配置
- display.h/.cpp: 屏幕显示类
- lte_module.h/.cpp: 步态运动类定义和接口声明
- http_client.h/.cpp: HTTP请求类
- sms_types.h: 短信的数据接口定义
- speaker.h/.cpp: speakerle类定义
- web_server.h/.cpp: web服务器类
- wifi_manager.h/.cpp: wifi管理类
- main.cpp: 程序主入口
config_manager
此类用于将配置数据存储进非易失存储器,避免断电后掉电
#ifndef CONFIG_MANAGER_H
#define CONFIG_MANAGER_H
#include
#include
// 配置管理类
class ConfigManager {
public:
ConfigManager();
// 加载配置
void load();
// 保存配置
void save();
// 检查是否已配置
bool isConfigured() const;
// 设置配置完成标志
void setConfigured(bool configured);
// WiFi配置
String wifiSSID;
String wifiPassword;
// HTTP配置
String httpMethod;
String httpUrl;
bool httpForwardEnabled;
// 短信转发配置
bool smsForwardEnabled;
String smsForwardNumber;
// 显示配置
int backlightBrightness;
int backlightMode; // 0=关闭, 1=常亮, 2=收到消息时开启
private:
Preferences preferences;
};
#endif
config.h
板级配置文件,用于配置IO引脚定义及其他自定义配置
class #ifndef CONFIG_H
#define CONFIG_H
// 硬件引脚定义
// ST7920显示屏引脚
#define LCD_CLK 4 // IO4 - 时钟
#define LCD_MOSI 6 // IO6 - 数据
#define LCD_CS 7 // IO7 - 片选
// 按键引脚
#define BTN_LEFT 1 // IO1 - 收信模式按键
#define BTN_MID 2 // IO2 - 确定按键
#define BTN_RIGHT 3 // IO3 - 转发模式按键
// 蜂鸣器引脚
#define BTN_SPK 5 // IO5 - 蜂鸣器
// 背光引脚
#define LCD_BACKLIGHT 0 // IO0 - 背光控制
// 背光模式
enum BacklightMode {
BACKLIGHT_OFF = 0, // 关闭
BACKLIGHT_ALWAYS_ON = 1, // 常亮
BACKLIGHT_ON_MESSAGE = 2 // 收到消息时开启
};
// 显示配置
#define MAX_DISPLAY_WIDTH 128
#define SCROLL_DELAY 150
#define SCROLL_STEP 2
// 通信配置
#define SERIAL_BAUD 115200
#define AT_TIMEOUT 2000
// HTTP配置
#define MIN_SEND_INTERVAL 5000 // 最小发送间隔(ms)
// 时间同步配置
#define TIME_SYNC_INTERVAL 60000 // 时间同步间隔(1分钟)
// WiFi配置
#define AP_SSID "EDA-Pager"
#define AP_PASSWORD "12345678"
#define WEB_SERVER_PORT 80
#endif
display.h
定义了一些屏幕显示部分的功能
#ifndef DISPLAY_H
#define DISPLAY_H
#include
#include "sms_types.h"
// 显示管理类
class Display {
public:
Display();
// 初始化显示屏
void begin();
// 显示短信内容(带滚动)
void showSms(const SmsData& sms);
// 手动滚动控制
void scrollLeft(int step = 10); // 向左滚动(文本向左移动)
void scrollRight(int step = 10); // 向右滚动(文本向右移动)
void enableAutoScroll(); // 启用自动滚动
void disableAutoScroll(); // 禁用自动滚动
bool isAutoScrollEnabled(); // 检查是否启用自动滚动
// 显示等待消息
void showWaiting(WorkMode mode, const String& date, const String& time);
// 显示文本消息
void showMessage(const String& line1, const String& line2 = "", const String& line3 = "");
// 显示配置信息
void showConfigInfo(const String& apIP, const String& staIP, bool wifiConnected);
// 显示验证码
void showVerificationCode(const String& code, const String& sender);
// 背光控制
void setBacklightMode(int mode);
void updateBacklight();
void turnOnBacklight();
void turnOffBacklight();
private:
U8G2_ST7920_128X64_F_SW_SPI u8g2;
int scrollOffset;
unsigned long lastScrollTime;
int backlightBrightness;
bool autoScrollEnabled; // 自动滚动开关
int maxScrollOffset; // 最大滚动偏移量
int backlightMode; // 背光模式
unsigned long backlightOnTime; // 背光开启时间
bool backlightOn; // 背光状态
};
#endif
http_client.h
项目构建配置文件,定义目标平台、分区表和编译选项。
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
#include
#include
// HTTP客户端类
class HttpClient {
public:
HttpClient();
// 发送HTTP请求
bool sendRequest(const String& url, const String& method, const String& smsContent);
// 获取最后一次错误信息
String getLastError() const { return lastError; }
// 获取最后一次HTTP状态码
int getLastHttpCode() const { return lastHttpCode; }
private:
String lastError;
int lastHttpCode;
unsigned long lastSendTime;
// 替换URL中的占位符
String replacePlaceholder(const String& url, const String& smsContent);
// URL编码
String urlEncode(const String& str);
// URL解码
String urlDecode(const String& str);
// JSON字符串转义
String escapeJsonString(const String& str);
// 解析查询参数并转换为JSON
String parseQueryParamsToJson(const String& queryParams, const String& smsContent);
// 发送GET请求
bool sendGetRequest(const String& url);
// 发送POST请求
bool sendPostRequest(const String& url, const String& smsContent);
};
#endif
lte_module.h
项目构建配置文件,定义目标平台、分区表和编译选项。
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
#include
#include
// HTTP客户端类
class HttpClient {
public:
HttpClient();
// 发送HTTP请求
bool sendRequest(const String& url, const String& method, const String& smsContent);
// 获取最后一次错误信息
String getLastError() const { return lastError; }
// 获取最后一次HTTP状态码
int getLastHttpCode() const { return lastHttpCode; }
private:
String lastError;
int lastHttpCode;
unsigned long lastSendTime;
// 替换URL中的占位符
String replacePlaceholder(const String& url, const String& smsContent);
// URL编码
String urlEncode(const String& str);
// URL解码
String urlDecode(const String& str);
// JSON字符串转义
String escapeJsonString(const String& str);
// 解析查询参数并转换为JSON
String parseQueryParamsToJson(const String& queryParams, const String& smsContent);
// 发送GET请求
bool sendGetRequest(const String& url);
// 发送POST请求
bool sendPostRequest(const String& url, const String& smsContent);
};
#endif
sms_types.h
项目构建配置文件,定义目标平台、分区表和编译选项。
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
#include
#include
// HTTP客户端类
class HttpClient {
public:
HttpClient();
// 发送HTTP请求
bool sendRequest(const String& url, const String& method, const String& smsContent);
// 获取最后一次错误信息
String getLastError() const { return lastError; }
// 获取最后一次HTTP状态码
int getLastHttpCode() const { return lastHttpCode; }
private:
String lastError;
int lastHttpCode;
unsigned long lastSendTime;
// 替换URL中的占位符
String replacePlaceholder(const String& url, const String& smsContent);
// URL编码
String urlEncode(const String& str);
// URL解码
String urlDecode(const String& str);
// JSON字符串转义
String escapeJsonString(const String& str);
// 解析查询参数并转换为JSON
String parseQueryParamsToJson(const String& queryParams, const String& smsContent);
// 发送GET请求
bool sendGetRequest(const String& url);
// 发送POST请求
bool sendPostRequest(const String& url, const String& smsContent);
};
#endif
speaker.h
项目构建配置文件,定义目标平台、分区表和编译选项。
#ifndef SPEAKER_H
#define SPEAKER_H
#include
class Speaker {
public:
Speaker(uint8_t pin);
void begin();
void speak(uint16_t freq, uint16_t duration);
void beep(uint16_t duration = 100);
void speakStart();
void speakNotify();
void mute();
void unmute();
bool isMuted() const { return _muted; }
private:
uint8_t _pin;
bool _muted;
};
#endif
web_server.h
项目构建配置文件,定义目标平台、分区表和编译选项。
#include "config_manager.h"
#include "http_client.h"
#include "display.h"
#include "sms_types.h"
#include "speaker.h"
// Web服务器类
class WebServer {
public:
WebServer(ConfigManager& config, HttpClient& httpClient, Display& display,
SmsData* smsHistory, int* smsHistoryCount, Speaker& speaker);
// 启动Web服务器
void begin();
// 检查配置是否完成
bool isConfigCompleted() const { return configCompleted; }
// 获取WiFi连接状态
bool isWiFiConnected() const { return wifiConnected; }
// 设置WiFi连接状态
void setWiFiConnected(bool connected) { wifiConnected = connected; }
private:
AsyncWebServer server;
ConfigManager& configManager;
HttpClient& httpClient;
Display& display;
Speaker& speaker;
SmsData* smsHistory;
int* smsHistoryCount;
bool configCompleted;
bool wifiConnected
void setupRoutes();
};
#endif
wifi_manager.h
项目构建配置文件,定义目标平台、分区表和编译选项。
// WiFi管理类
class WiFiManager {
public:
WiFiManager();
// 启动AP模式
void startAP(const char* ssid, const char* password);
// 连接到WiFi
bool connect(const String& ssid, const String& password);
// 检查是否已连接
bool isConnected() const;
// 获取AP IP地址
String getAPIP() const;
// 获取STA IP地址
String getSTAIP() const;
private:
bool connected;
};
#endif
安装结构
项目采用双外壳结构,包含前壳及后壳。
- 屏幕部分采用限位孔固定,先装入屏幕后压入主板
- 按钮及扬声器和侧面TypeC均已开孔
- 突出部分加入倒角加强
- 后盖较简单,压入限位使用
RNDIS 4G USB网卡测试

拓展方向
本项目提供了一个基础的LTE寻呼机方案,你可以基于此项目进行以下拓展:
- 增加MQTT功能,组成自建
- 增加蓝牙通知功能,将手机通知推送到寻呼机上
- 增加GPS功能,获取当前位置信息
- 增加SOS紧急联系人报告功能
注意事项
立创商城采购物料清单
| 数量 | 器件 | 商城编号 |
|---|---|---|
| 4 | 19-217/GHC-YR1S2/6T | C2986059 |
| 1 | 2.7kΩ | C96256 |
| 2 | 22uF | C6119901 |
| 1 | 1nF | C46653 |
| 4 | 100nF | C28233 |
| 4 | 10uF | C15850 |
| 5 | 22uF | C45783 |
| 2 | 100nF | C5137467 |
| 1 | SMN-303 | C266888 |
| 1 | 4.7uH | C167208 |
| 1 | 1uH | C167203 |
| 1 | TS665CJ | C393938 |
| 1 | AO3400A | C347475 |
| 8 | 10kΩ | C17414 |
| 1 | 100kΩ | C149504 |
| 1 | 20kΩ | C4328 |
| 1 | 82kΩ | C17840 |
| 1 | 2Ω | C17606 |
| 1 | 500mΩ | C28319 |
| 4 | 5.1kΩ | C27834 |
| 1 | 4.7kΩ | C2907326 |
| 1 | BWIPX-1-001E | C496552 |
| 3 | KH-6X6X9H-TJ | C2837519 |
| 4 | TS3425BA | C2681476 |
| 1 | ME6217C33M5G | C427602 |
| 1 | ML307C-DC-CN | C48982539 |
| 1 | JW5359MSOTB#TR | C42685544 |
| 1 | 2.4GHz 天线 | C2934560 |
| 1 | IP5306 | C181692 |
| 2 | TYPE-C 16PIN 2MD(073) | C2765186 |
非商城物料采购清单
| 数量 | 器件 |
|---|---|
| 1 | 3.7V聚合物电池 |
💡 提示:部分通用元件可选择等效型号,重点关注封装及电气参数一致性。
下表列出了本项目 ESP32C3 未合并固件烧录时的分区布局,地址与文件路径对应关系如下,可直接用于命令行烧录或 Flash 工具导入配置。
| 烧录地址 | 文件路径 | 说明 |
|---|---|---|
| 0x0 | bootloader.bin | Bootloader 启动加载程序 |
| 0x8000 | partition-table.bin | 分区表 |
| 0xe000 | boot_app0.bin | 二级Boot |
| 0x10000 | firmware.bin | 主程序固件 |
💡 提示:使用 esptool.py 可执行如下命令进行烧录:
esptool.py write_flash 0x0 bootloader.bin 0x8000 partition-table.bin 0xe000 boot_app0.bin 0x10000 firmware.bin
