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 杞崲