diff --git a/V1.5/STM32F103_App1/HardWare/CAR/air780e.c b/V1.5/STM32F103_App1/HardWare/CAR/air780e.c
index 1bb274a..9c236f9 100644
--- a/V1.5/STM32F103_App1/HardWare/CAR/air780e.c
+++ b/V1.5/STM32F103_App1/HardWare/CAR/air780e.c
@@ -81,6 +81,7 @@ int Verify_Firmware_External(uint32_t ext_addr, uint32_t size)
/*==== 4G Reset Control ====*/
/*==== 4G Reset Control ====*/
static void cat_reset(void) {
+ g_net_ui_phase = NET_UI_4G_RESET;
log_info("> 4G: 复位...");
/* 关闭 NVIC 中断, 防止模块复位期间乱码触发中断风暴 */
@@ -196,6 +197,7 @@ static int cat_wait_cgatt_attached(int max_wait_s) {
U2_CopyIndex = 0;
U2_CopyBuff[0] = 0;
U2_CopyFlag = 0;
+ g_net_ui_phase = NET_UI_4G_ATTACH;
CAT1_printf("AT+CGATT?");
uint8_t t = 30; /* 单次查询等 3 秒 */
@@ -227,6 +229,7 @@ static int cat_wait_cgatt_attached(int max_wait_s) {
static int cat_connect_network(void) {
log_info("> 4G: 网络...");
+ g_net_ui_phase = NET_UI_4G_AT;
/* 波特率同步:永远先按 115200 探测(出厂/自适应模式的模块不能被
其他波特率的乱码干扰侦测窗口),通了就固定为 921600 并保存;
@@ -246,6 +249,7 @@ static int cat_connect_network(void) {
if (catSendCmd("AT", "OK", 3, 20) != 0) return -1;
if (catSendCmd("ATE0", "OK", 1, 10) != 0) return -1;
+ g_net_ui_phase = NET_UI_4G_SIM; /* AT 通过,开始检测 SIM/信号 */
/* 检测 SIM 卡:多次查询 AT+CPIN?,识别无 SIM 卡场景 */
int sim_retry = 3;
@@ -265,6 +269,7 @@ static int cat_connect_network(void) {
strstr((char *)U2_CopyBuff, "SIM NOT INSERTED") ||
strstr((char *)U2_CopyBuff, "+CME ERROR: 10")) {
log_warn("> 4G: 未检测到 SIM 卡");
+ g_net_ui_phase = NET_UI_4G_NOSIM;
g_no_sim_detected = 1;
return -2;
}
@@ -325,6 +330,7 @@ static int cat_connect_network(void) {
/*==== MQTT Connect ====*/
static int cat_connect_mqtt(void) {
+ g_net_ui_phase = NET_UI_4G_MQTT;
char b[120]; log_info("> 4G: MQTT...");
/* 复用 catSendCmd 等待 MCONNECT 的真正连接确认, 不清空已有缓冲区 */
diff --git a/V1.5/STM32F103_App1/HardWare/NETWORK/network.c b/V1.5/STM32F103_App1/HardWare/NETWORK/network.c
index b484883..2452f94 100644
--- a/V1.5/STM32F103_App1/HardWare/NETWORK/network.c
+++ b/V1.5/STM32F103_App1/HardWare/NETWORK/network.c
@@ -39,6 +39,9 @@ volatile uint8_t g_no_sim_detected = 0;
volatile uint8_t g_no_signal_detected = 0;
/* 当前激活的网络后端 */
+volatile net_ui_phase_t g_net_ui_phase = NET_UI_NONE;
+volatile int g_net_ui_countdown = 0;
+
static net_backend_t s_backend = NET_BACKEND_4G;
/* 上次成功联网方式(EEPROM 偏移 130,秤参数占用到 126,避开) */
diff --git a/V1.5/STM32F103_App1/HardWare/NETWORK/network.h b/V1.5/STM32F103_App1/HardWare/NETWORK/network.h
index 57fb31f..82287d0 100644
--- a/V1.5/STM32F103_App1/HardWare/NETWORK/network.h
+++ b/V1.5/STM32F103_App1/HardWare/NETWORK/network.h
@@ -29,6 +29,21 @@ void NET_SaveMode(uint8_t mode); /*
* 防止业务发布与进行中的 AT 指令在 USART3 上交织导致应答误判) */
extern volatile uint8_t g_net_tx_busy;
+/*===== OLED 联网进度显示(net 任务各阶段更新,sys_task 屏幕读取)=====*/
+typedef enum {
+ NET_UI_NONE = 0, /* 无进度/初始化中 */
+ NET_UI_4G_RESET, /* 4G 模块复位 */
+ NET_UI_4G_AT, /* AT 指令检测通过 */
+ NET_UI_4G_SIM, /* SIM 卡就绪 */
+ NET_UI_4G_ATTACH, /* 附着/激活网络成功 */
+ NET_UI_4G_MQTT, /* MQTT 连接中 */
+ NET_UI_4G_NOSIM, /* 无 SIM 卡 */
+ NET_UI_WIFI_FIXED, /* WiFi 固定热点搜索中(countdown 有效) */
+ NET_UI_WIFI_SMART, /* SmartConfig 配网中(countdown 有效) */
+} net_ui_phase_t;
+extern volatile net_ui_phase_t g_net_ui_phase;
+extern volatile int g_net_ui_countdown; /* WiFi 连接/配网剩余秒数 */
+
/*===== API =====*/
void NET_init(void);
void NET_process(void);
diff --git a/V1.5/STM32F103_App1/HardWare/OLED/oled.c b/V1.5/STM32F103_App1/HardWare/OLED/oled.c
index 77854a7..56a7a26 100644
--- a/V1.5/STM32F103_App1/HardWare/OLED/oled.c
+++ b/V1.5/STM32F103_App1/HardWare/OLED/oled.c
@@ -275,6 +275,12 @@ void oled_print(const char *s)
}
}
+/*==== 当前列右移 px 像素 ====*/
+void oled_xoff(uint8_t px)
+{
+ s_col += px;
+}
+
/*==== 整行显示:计算像素宽度,不足 128px 用空格补齐(覆盖上次内容)====*/
void oled_print_line(const char *s)
{
diff --git a/V1.5/STM32F103_App1/HardWare/OLED/oled.h b/V1.5/STM32F103_App1/HardWare/OLED/oled.h
index 9687b71..65f82cf 100644
--- a/V1.5/STM32F103_App1/HardWare/OLED/oled.h
+++ b/V1.5/STM32F103_App1/HardWare/OLED/oled.h
@@ -12,6 +12,7 @@
void oled_init(void); /* GPIO + 屏幕初始化(app_init 调用) */
void oled_clear(void); /* 全屏清屏 */
void oled_locate(uint8_t row, uint8_t col8); /* 定位:row 0~3,col8 为 8 像素单位 0~15 */
+void oled_xoff(uint8_t px); /* 在当前列基础上右移 px 像素(防烧屏偏移用) */
void oled_print(const char *gbk_str); /* 从当前位置显示 GBK 字符串 */
void oled_print_line(const char *gbk_str); /* 整行显示:不足 128px 用空格补齐覆盖旧内容 */
diff --git a/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c b/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c
index 2a6da46..c522f4c 100644
--- a/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c
+++ b/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c
@@ -198,31 +198,84 @@ static void app_task(void *arg)
}
}
-/*==== OLED 基础信息:电压/电流/功率/电能/继电器/网络,1s 刷新 ====*/
-static void oled_home_refresh(void)
+/*==== OLED 界面刷新(1s 一次)
+ * 已联网:电压电流/功率电能/开关状态/网络+运行时间
+ * 未联网:按 g_net_ui_phase 显示 4G/WiFi 联网进度(WiFi 带倒计时)
+ * 防烧屏:每 10s 内容整体右移 0/2/4px 轮换 ====*/
+static void oled_home_refresh(uint32_t up_ms)
{
char buf[24];
+ /* 防烧屏:每 10s 换一档水平偏移(0/2/4px) */
+ uint8_t xoff = (uint8_t)((HAL_GetTick() / 10000u) % 3u) * 2u;
- if (hlw8032_online()) {
- snprintf(buf, sizeof(buf), "%.1fV %.2fA",
- (double)hlw8032_get_voltage_v(), (double)hlw8032_get_current_a());
- oled_locate(0, 0); oled_print_line(buf);
- snprintf(buf, sizeof(buf), "%.1fW %.2fkWh",
- (double)hlw8032_get_power_w(), (double)hlw8032_get_energy_kwh());
- oled_locate(1, 0); oled_print_line(buf);
+ if (g_net_mqtt_ready) {
+ /*---- 已联网界面 ----*/
+ if (hlw8032_online()) {
+ snprintf(buf, sizeof(buf), "%.1fV %.2fA",
+ (double)hlw8032_get_voltage_v(), (double)hlw8032_get_current_a());
+ oled_locate(0, 0); oled_xoff(xoff); oled_print_line(buf);
+ snprintf(buf, sizeof(buf), "%.1fW %.2fkWh",
+ (double)hlw8032_get_power_w(), (double)hlw8032_get_energy_kwh());
+ oled_locate(1, 0); oled_xoff(xoff); oled_print_line(buf);
+ } else {
+ oled_locate(0, 0); oled_xoff(xoff); oled_print_line("计量芯片离线");
+ oled_locate(1, 0); oled_xoff(xoff); oled_print_line("");
+ }
+
+ snprintf(buf, sizeof(buf), "开关:%s%s%s%s",
+ MqttInfoStr.Relay_State[1] ? "开" : "关",
+ MqttInfoStr.Relay_State[2] ? "开" : "关",
+ MqttInfoStr.Relay_State[3] ? "开" : "关",
+ MqttInfoStr.Relay_State[4] ? "开" : "关");
+ oled_locate(2, 0); oled_xoff(xoff); oled_print_line(buf);
+
+ /* 网络 + 运行时间:满 1 天显示 "1天02时",否则 "27:35" */
+ uint32_t mins = up_ms / 60000u;
+ const char *nt = (NET_GetActiveBackend() == NET_BACKEND_WIFI) ? "WiFi" : "4G";
+ if (mins >= 1440u) {
+ snprintf(buf, sizeof(buf), "%s已连接%u天%02u时", nt,
+ (unsigned)(mins / 1440u), (unsigned)((mins % 1440u) / 60u));
+ } else {
+ snprintf(buf, sizeof(buf), "%s已连接%02u:%02u", nt,
+ (unsigned)(mins / 60u), (unsigned)(mins % 60u));
+ }
+ oled_locate(3, 0); oled_xoff(xoff); oled_print_line(buf);
} else {
- oled_locate(0, 0); oled_print_line("计量芯片离线");
- oled_locate(1, 0); oled_print_line("");
+ /*---- 未联网界面:联网进度 ----*/
+ net_ui_phase_t ph = g_net_ui_phase;
+ oled_locate(0, 0); oled_xoff(xoff); oled_print_line("");
+
+ if (ph == NET_UI_WIFI_FIXED || ph == NET_UI_WIFI_SMART ||
+ NET_GetActiveBackend() == NET_BACKEND_WIFI) {
+ if (ph == NET_UI_WIFI_FIXED) {
+ oled_locate(1, 0); oled_xoff(xoff); oled_print_line("WiFi固定模式");
+ oled_locate(2, 0); oled_xoff(xoff); oled_print_line("正在搜索热点");
+ } else if (ph == NET_UI_WIFI_SMART) {
+ oled_locate(1, 0); oled_xoff(xoff); oled_print_line("智能配网");
+ oled_locate(2, 0); oled_xoff(xoff); oled_print_line("请打开APP广播");
+ } else {
+ oled_locate(1, 0); oled_xoff(xoff); oled_print_line("WiFi模式");
+ oled_locate(2, 0); oled_xoff(xoff); oled_print_line("初始化中...");
+ }
+ snprintf(buf, sizeof(buf), "剩余 %ds", g_net_ui_countdown);
+ oled_locate(3, 0); oled_xoff(xoff); oled_print_line(g_net_ui_countdown > 0 ? buf : "");
+ } else {
+ /* 4G 进度:显示最近完成的阶段 */
+ const char *step = "初始化中";
+ switch (ph) {
+ case NET_UI_4G_RESET: step = "模块复位成功"; break;
+ case NET_UI_4G_AT: step = "AT指令成功"; break;
+ case NET_UI_4G_SIM: step = "SIM卡检测成功"; break;
+ case NET_UI_4G_ATTACH: step = "附着网络成功"; break;
+ case NET_UI_4G_MQTT: step = "连接服务器中"; break;
+ case NET_UI_4G_NOSIM: step = "无SIM卡!"; break;
+ default: break;
+ }
+ oled_locate(1, 0); oled_xoff(xoff); oled_print_line("正在等待4G联网");
+ oled_locate(2, 0); oled_xoff(xoff); oled_print_line(step);
+ oled_locate(3, 0); oled_xoff(xoff); oled_print_line("");
+ }
}
-
- snprintf(buf, sizeof(buf), "开关:%d%d%d%d",
- (int)MqttInfoStr.Relay_State[1], (int)MqttInfoStr.Relay_State[2],
- (int)MqttInfoStr.Relay_State[3], (int)MqttInfoStr.Relay_State[4]);
- oled_locate(2, 0); oled_print_line(buf);
-
- const char *net = !g_net_mqtt_ready ? "未联网" :
- (NET_GetActiveBackend() == NET_BACKEND_WIFI) ? "WiFi 已连接" : "4G 已连接";
- oled_locate(3, 0); oled_print_line(net);
}
/* 电能日志/上报间隔:想改频率就改这个宏(单位 ms) */
@@ -253,7 +306,7 @@ static void sys_task(void *arg)
batt_tick = HAL_GetTick();
update_batter();
hlw8032_tick(); /* 攒够约 0.1kWh 写一次 EEPROM */
- oled_home_refresh(); /* OLED 基础信息 1s 刷新 */
+ oled_home_refresh(up_ms); /* OLED 界面 1s 刷新 */
reset_log_tick((uint32_t)(up_ms / 1000)); /* 共享 RAM 更新运行秒数,热复位不丢 */
}
diff --git a/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.c b/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.c
index d9f35d7..e824a2e 100644
--- a/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.c
+++ b/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.c
@@ -10,6 +10,7 @@
#include "esp8266.h"
#include "air780e.h" /* U2_CopyBuff / bg_delay */
+#include "network.h"
#include "uart.h"
#include "log.h"
#include "led.h"
@@ -71,6 +72,7 @@ static int esp_wait_countdown(const char *expect, int timeout_s)
}
}
if (remain % 10 == 0 && sec > 0) {
+ g_net_ui_countdown = sec; /* OLED 显示用 */
log_info("> WiFi: 倒计时 %ds", sec--);
}
}
@@ -244,6 +246,8 @@ int esp_join_fixed_ap(void)
{
char cmd[96];
+ g_net_ui_phase = NET_UI_WIFI_FIXED;
+
log_info("> WiFi: 连接固定热点 '%s' (%ds)", WIFI_SSID, WIFI_JOIN_TIMEOUT_S);
/* 保持 CWAUTOCONN=1(默认):连接成功的AP会被模块保存,
@@ -267,6 +271,7 @@ int esp_join_fixed_ap(void)
int esp_smartconfig(void)
{
log_info("> WiFi: SmartConfig 开始 (%ds), 请用 ESP-Touch APP", WIFI_SMART_TIMEOUT_S);
+ g_net_ui_phase = NET_UI_WIFI_SMART;
g_net_led_smartconfig = 1; /* NET_LED 100ms 快闪提示配网模式 */
if (esp_send_cmd("AT+CWSTARTSMART", "OK", 5000) != 0) { g_net_led_smartconfig = 0; return -1; }
diff --git a/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.h b/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.h
index 06d1088..580ba93 100644
--- a/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.h
+++ b/V1.5/STM32F103_App1/HardWare/WIFI/esp8266.h
@@ -6,7 +6,7 @@
/*===== 用户配置区 =====*/
/* 固定 WiFi 凭据:优先尝试连接的热点;连不上(60s)则进 Smart Config 智能配网 */
-#define WIFI_SSID "TP_Link-01" /* TODO: 填入固定 WiFi 名称 */
+#define WIFI_SSID "TP_Link-02" /* TODO: 填入固定 WiFi 名称 */
#define WIFI_PASS "zxcvbnmm112" /* TODO: 填入固定 WiFi 密码 */
//#define WIFI_SSID "TP_Link" /* TODO: 填入固定 WiFi 名称 */
diff --git a/V1.5/STM32F103_App1/MDK-ARM/STM32F103rb_App1.uvoptx b/V1.5/STM32F103_App1/MDK-ARM/STM32F103rb_App1.uvoptx
index 9d1ae9b..0330f1f 100644
--- a/V1.5/STM32F103_App1/MDK-ARM/STM32F103rb_App1.uvoptx
+++ b/V1.5/STM32F103_App1/MDK-ARM/STM32F103rb_App1.uvoptx
@@ -77,7 +77,7 @@
0
1
- 18
+ 255
0
@@ -937,6 +937,19 @@
0
0
+
+ 7
+ 51
+ 1
+ 0
+ 0
+ 0
+ 0
+ ..\HardWare\OLED\oled.c
+ oled.c
+ 0
+ 0
+
@@ -947,7 +960,7 @@
0
8
- 51
+ 52
5
0
0
diff --git a/V1.5/STM32F103_App1/README.md b/V1.5/STM32F103_App1/README.md
index 752b95f..c29866f 100644
--- a/V1.5/STM32F103_App1/README.md
+++ b/V1.5/STM32F103_App1/README.md
@@ -122,7 +122,9 @@
- 绉绘鑷485妯℃嫙纾呯Г鏁版嵁甯RC銆嬬殑 oledisp 椹卞姩锛孏PIO 妯℃嫙 SPI锛堝睆骞 CS1 + 瀛楀簱 CS2 涓よ矾鐗囬夛紝瀛楀簱鏁版嵁浠 FSO 鑴氳鍥烇級
- 瀛楃涓茬洿鎺ュ啓涓枃锛堝伐绋嬫簮鏂囦欢鍗 GBK 缂栫爜锛屽瓧搴 IC 鎸 GB2312 鍦板潃鎹㈢畻鍙栧瓧妯★級
-- 鏄剧ず鍐呭锛坄oled_home_refresh()`锛宻ys_task 姣 1s 鍒锋柊锛夛細绗 0 琛 鐢靛帇/鐢垫祦锛岀 1 琛 鍔熺巼/鐢佃兘锛堣閲忚姱鐗囩绾挎椂鏄剧ず"璁¢噺鑺墖绂荤嚎"锛夛紝绗 2 琛 鍥涜矾缁х數鍣ㄧ姸鎬侊紙`寮鍏:1010`锛夛紝绗 3 琛 缃戠粶鐘舵侊紙WiFi 宸茶繛鎺/4G 宸茶繛鎺/鏈仈缃戯級
+- **宸茶仈缃戠晫闈**锛坰ys_task 姣 1s 鍒锋柊锛夛細绗 0 琛 鐢靛帇/鐢垫祦锛岀 1 琛 鍔熺巼/鐢佃兘锛堣閲忚姱鐗囩绾挎椂鏄剧ず"璁¢噺鑺墖绂荤嚎"锛夛紝绗 2 琛 缁х數鍣ㄧ姸鎬佷腑鏂囷紙`寮鍏:寮寮鍏冲叧`锛夛紝绗 3 琛 缃戠粶 + 杩愯鏃堕棿锛坄WiFi宸茶繛鎺02:35`锛屾弧 1 澶╂樉绀 `1澶02鏃禶锛
+- **鏈仈缃戠晫闈**锛氬彧鏄剧ず鑱旂綉杩涘害锛屼笉鏄剧ず鐢佃兘/寮鍏斥斺4G 妯″紡鏄剧ず"姝e湪绛夊緟4G鑱旂綉"+ 鏈杩戝畬鎴愰樁娈碉紙妯″潡澶嶄綅鎴愬姛/AT鎸囦护鎴愬姛/SIM鍗℃娴嬫垚鍔/闄勭潃缃戠粶鎴愬姛/杩炴帴鏈嶅姟鍣ㄤ腑/鏃燬IM鍗★紝鐘舵佺敱 `g_net_ui_phase` 浠 air780e.c 鍚勯樁娈垫洿鏂帮級锛沇iFi 鍥哄畾鐑偣鏄剧ず"WiFi鍥哄畾妯″紡 姝e湪鎼滅储鐑偣"+鍊掕鏃讹紝SmartConfig 鏄剧ず"鏅鸿兘閰嶇綉 璇锋墦寮APP骞挎挱"+鍊掕鏃讹紙鍊掕鏃剁敱 esp_wait_countdown 鍐欏叆 `g_net_ui_countdown`锛
+- **闃茬儳灞**锛氭瘡 10s 鍐呭鏁翠綋鍙崇Щ 0/2/4px 杞崲
- 寮鏈烘樉绀"鏅鸿兘鎺у埗鍣 + 鐗堟湰鍙"娆㈣繋椤碉紝棣栨鍒锋柊鍚庤繘鍏ュ父鎬佺晫闈
## 鍙岄氶亾缃戠粶锛4G 浼樺厛锛學iFi 鍏滃簳锛
diff --git a/V1.5/鐗堟湰璇存槑.md b/V1.5/鐗堟湰璇存槑.md
index 624c441..e3ae85a 100644
--- a/V1.5/鐗堟湰璇存槑.md
+++ b/V1.5/鐗堟湰璇存槑.md
@@ -118,3 +118,6 @@
- `BT_MODE`(PB0)锛氳摑鐗 AT/閫忎紶鍒囨崲锛屾鍓嶇増鏈凡瀹炵幇锛坆le_at.c 寮婕忔帶鍒讹級
- 鏂板 OLED 灞忓箷锛128x64 + 鏅惰仈璁 GB2312 瀛楀簱 IC锛宍HardWare/OLED/oled.c`锛孏PIO 妯℃嫙 SPI锛夛細
CLK=PC12 MOSI=PC9 DC=PC8 CS1=PC7 FSO=PC6 CS2=PB15锛1s 鍒锋柊鐢靛帇/鐢垫祦/鍔熺巼/鐢佃兘/缁х數鍣/缃戠粶鐘舵
+- OLED 鐣岄潰閲嶆瀯锛氭湭鑱旂綉鍙樉绀鸿仈缃戣繘搴︼紙4G 鍚勯樁娈典腑鏂囨彁绀 / WiFi 鍥哄畾鐑偣鎼滅储鍊掕鏃 /
+ SmartConfig"璇锋墦寮APP骞挎挱"鍊掕鏃讹級锛岃仈缃戝悗鎵嶆樉绀虹數鑳/寮鍏/缃戠粶/杩愯鏃堕棿锛
+ 寮鍏崇姸鎬佹敼涓枃锛堝紑鍏:寮寮鍏冲叧锛夛紱闃茬儳灞忔瘡 10s 鍐呭鍙崇Щ 0/2/4px 杞崲