增加交流量和直流量显示页面框架

This commit is contained in:
2026-04-02 21:18:01 +08:00
parent df94630210
commit d19ce588b3
27 changed files with 1139 additions and 156 deletions

View File

@@ -41,6 +41,10 @@ add_executable(DTU-HMI
src/Drv/pages/AppInfo/model.c
src/Drv/pages/AppInfo/presenter.c
src/Drv/pages/AppInfo/view.c
src/Drv/pages/YC/page.c
src/Drv/pages/YC/model.c
src/Drv/pages/YC/presenter.c
src/Drv/pages/YC/view.c
src/Drv/lcd/lcd.c
src/Drv/lcd/lcd_draw.c
src/Drv/lcd/lcd_text.c

View File

@@ -2,21 +2,46 @@
#define __TYPES__H__
#include <stdio.h>
#define uint8_t unsigned char
#define uint16_t unsigned short
#define uint32_t unsigned int
#define uint64_t unsigned long long
#define int8_t char
#define int16_t short
#define int32_t int
#define int64_t long long
#define ptr_size_t unsigned long long
#include <stdint.h>
typedef int (*FUNCPTR) ( );
enum _MEA_TYPE_
{
EN_MEA_RLY,
EN_MEA_RLY2,
EN_MEA_RLY3,
EN_MEA_ANA,
EN_MEA_ANA2,
EN_MEA_ANA3,
EN_MEA_AC,
EN_MEA_DC,
EN_MEA_SYN,
EN_MEA_POWER,
EN_MEA_DD,
EN_MEA_JLYC,
EN_MEA_GEAR,
EN_MEA_TQ,
EN_MEA_INPUT1,
EN_MEA_INPUT2,
EN_MEA_INPUT3,
EN_INPUT_RLY_ALL,
EN_INPUT_RLY_FAULT,
EN_INPUT_RLY_OTHER,
EN_INPUT_BS_ALL,
EN_INPUT_BS_FAULT,
EN_INPUT_BS_OTHER,
EN_MEA_ADJ,
EN_MEA_YX,
EN_OUTPUT_TRIP,
EN_OUTPUT_SIGN,
EN_MEA_LS,
EN_MEA_SCRLY
};
// 调试模式断言
#ifdef DEBUG
#define ASSERT(expr) \

View File

@@ -128,7 +128,7 @@ static int8_t Lcd_Pub_UTF8(uint16_t x, uint16_t y, uint32_t unicode)
* - 与历史行为兼容,保留 -1/-2 两种错误码语义。
* - 内部会在渲染前做边界预判,并在底层写像素失败时转化为越界错误返回。
* ------------------------------------------------------------------------- */
int8_t Lcd_ShowStr(uint16_t x, uint16_t y, uint8_t *pcString)
int8_t Lcd_ShowStr(uint16_t x, uint16_t y, const uint8_t *pcString)
{
const textConfig *cfg = &text_cfg;
uint16_t bakx = x;

View File

@@ -16,7 +16,7 @@ typedef struct {
extern textConfig text_cfg;
int8_t Lcd_ShowStr(uint16_t x, uint16_t y, uint8_t *pcString);
int8_t Lcd_ShowStr(uint16_t x, uint16_t y, const uint8_t *pcString);
int8_t Lcd_ShowTest(uint16_t x, uint16_t y, uint8_t *pcString);
#endif

View File

@@ -32,7 +32,7 @@ void MenuProc_See_AppInfo(void)
void MenuProc_See_YC(void)
{
MenuPage_TriggerCurrentAction();
(void)PageManager_Navigate(PAGE_ID_YC);
}
void MenuProc_Set_Value(void) { MenuPage_TriggerCurrentAction(); }

View File

@@ -1,9 +0,0 @@
#ifndef APPINFO_def_H
#define APPINFO_def_H
#define CN_HEIGHT 12
#define CN_ROWSPACE 2
#define APPINFO_WITDTH 7
#endif

View File

@@ -4,6 +4,5 @@
#include "Drv/pages/page.h"
page_t *AppInfoPage_GetInstance(void);
void AppInfoPage_TriggerCurrentAction(void);
#endif

View File

@@ -2,64 +2,12 @@
#include "Drv/pages/AppInfo/view.h"
#include <stdio.h>
/* MSVC 对含多字节/中文格式串的静态分析可能误报 C4474/C4996。
* 本文件内的格式化输出均为受控 buffer并用于显示文本渲染。 */
#if defined(_MSC_VER)
#pragma warning(disable : 4474)
#pragma warning(disable : 4996)
#endif
static const PageRenderPort *s_port = NULL;
/* -------------------------------------------------------------------------
* 函数名: MenuView_DrawMeitou
* 功能:
* 绘制菜单标题装饰线(“眉头”样式):中间横线 + 左右两端斜线。
*
* 参数:
* view - 菜单视图对象,提供底层渲染端口
* yStart - 装饰线基准 Y 坐标(横线所在行)
* width - 线宽参数(传递给 line_h/line
*
* 边界处理:
* - 本函数不做空指针判定,调用方需保证 view 与 s_port 有效。
* - 坐标范围合法性由上层布局计算保证。
*
* 说明:
* - 颜色统一使用字体前景色get_color_font确保装饰与文字风格一致。
* - 绘制顺序:
* 1) 中间横线x:16~144
* 2) 左斜线8, yStart-8 -> 16, yStart
* 3) 右斜线144, yStart -> 152, yStart-8
* - 该函数用于视觉分隔与层次强调,不改变菜单状态数据。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void AppInfoView_DrawMeitou(uint16_t yStart, uint16_t width)
{
uint8_t fontColor = s_port->get_color_font();
s_port->line_h(16, 144, yStart, width, fontColor);
s_port->line(8, yStart - 8, 16, yStart, width, fontColor);
s_port->line(144, yStart, 152, yStart - 8, width, fontColor);
}
void AppInfoView_ShowInfoPage(uint16_t wPageNum, uint16_t wPageMax )
{
/* show_str 期望的是 '\0' 结尾的 UTF-8 字符串 */
char pbyTips[64];
uint16_t y = s_port->get_size_y() - 16;
/* 格式化字符串(用于 LCD 文本显示) */
#if defined(_MSC_VER)
(void)sprintf_s(pbyTips, sizeof(pbyTips), "第%4u 页 , 共%4u 页",
(unsigned)wPageNum, (unsigned)wPageMax);
#else
(void)snprintf(pbyTips, sizeof(pbyTips), "第%4u 页 , 共%4u 页",
(unsigned)wPageNum, (unsigned)wPageMax);
#endif
s_port->show_str(6, y, (uint8_t *)pbyTips);
}
void AppInfoView_ShowTerminalInfo(void)
{
@@ -85,9 +33,8 @@ void AppInfoView_ShowTopName(uint8_t *name)
s_port->fill_rect(0, 0, s_port->get_size_x() - 1, s_port->get_size_y() - 1, s_port->get_color_back());
/* 显示顶部名称,居中显示 */
s_port->show_str((s_port->get_size_x() - wLen) / 2, 3, name);
AppInfoView_DrawMeitou(18, 2);
AppInfoView_ShowInfoPage(10, 1);
s_port->draw_meitou(18, 2);
s_port->show_info_page(10, 1);
AppInfoView_ShowTerminalInfo();
}
void AppInfoView_Init(appinfo_view_t *view)

View File

@@ -2,7 +2,6 @@
#define APPINFO_VIEW_H
#include "types.h"
#include "Drv/pages/AppInfo/def.h"
#include "Drv/pages/global/renderer_lcd.h"
typedef struct appinfo_view_t appinfo_view_t;

367
src/Drv/pages/YC/model.c Normal file
View File

@@ -0,0 +1,367 @@
#include "Drv/pages/YC/model.h"
#include "../global/global_state.h"
#include <string.h>
#ifndef CN_PHASE_NAME_LEN
#define CN_PHASE_NAME_LEN (4)
#endif
/* YC 页面编译接入阶段的兼容常量(后续可替换为真实业务定义) */
#ifndef CN_RGB_YELLOW
#define CN_RGB_YELLOW (0x00FFFF00u)
#define CN_RGB_GREEN (0x0000FF00u)
#define CN_RGB_RED (0x00FF0000u)
#define CN_RGB_WHITE (0x00FFFFFFu)
#endif
enum
{
EN_UNIT01_A = 1, EN_UNIT01_B, EN_UNIT01_C,
EN_UNIT02_A, EN_UNIT02_B, EN_UNIT02_C,
EN_UNIT01_0, EN_VOL1_A, EN_VOL1_B, EN_VOL1_C,
EN_VOL2_A, EN_VOL2_B, EN_VOL2_C, EN_VOL1_0,
EN_VOL2_0, EN_VOL1_FR, EN_UNIT01_DC
};
// 定义单位类型常量
enum _UNIT_TYPE_
{
EN_UNIT_NULL=0, // 0 " "
EN_UNIT_A, // 1 "A"
EN_UNIT_V, // 2 "V"
EN_UNIT_S, // 3 "S"
EN_UNIT_HZ, // 4 "Hz"
EN_UNIT_HZPS, // 5 "Hz/s"
EN_UNIT_DGREE, // 6 "°"
EN_UNIT_OHM, // 7 "Ω"
EN_UNIT_KM, // 8 "kM"
EN_UNIT_M, // 9 "M"
EN_UNIT_VPS, // 0AH "V/S"
EN_UNIT_KV, // 0BH "kV"
EN_UNIT_W, // 0CH "W"
EN_UNIT_VAR, // 0DH "VAR"
EN_UNIT_MVA, // 0EH "MVA"
EN_UNIT_0F, // 0FH " "
EN_UNIT_PERCENT, // 10H ""
EN_UNIT_MW, // 11H "MW"
EN_UNIT_MV, // 12H "mV"
EN_UNIT_MA, // 13H "mA"
EN_UNIT_KOHM, // 14 "kΩ"
EN_UNIT_VA, // 15H "VA"
EN_UNIT_AKA, // 16H "A(kA)"
EN_UNIT_KA, // 17H "kA"
EN_UNIT_KVPS, // 18H "KV/S"
EN_UNIT_MVAR, // 19H "MVAR"
EN_UNIT_KW, // 1AH "KW"
EN_UNIT_KVAR, // 1BH "KVAR"
EN_UNIT_KVA, // 1CH "KVA"
EN_UNIT_KWH, // 1DH "kWh"
EN_UNIT_KVARH, // 1EH "kVarh"
EN_UNIT_IE, // 1AH "Ie"
EN_UNIT_1B, // 1BH "无"
EN_UNIT_1C, // 1CH "无"
EN_UNIT_1D, // 1DH "无"
EN_UNIT_1E, // 1EH "无"
EN_UNIT_1F, // 1FH "无"
EN_UNIT_20, // 20H "无"
EN_UNIT_PERUN, // 21H "Un"
};
//================================================================================
// 遥测量交流通道
//================================================================================
enum _YCMEA_INDEX_TYPE_
{
EN_YCMEA_ORI_START = 0,
EN_YCMEA_I_START = EN_YCMEA_ORI_START,
EN_YCMEA_IA01 = EN_YCMEA_I_START, // 遥测A相电流01
EN_YCMEA_IB01, // 遥测B相电流01
EN_YCMEA_IC01, // 遥测C相电流01
EN_YCMEA_IA02, // 遥测A相电流01
EN_YCMEA_IB02, // 遥测B相电流01
EN_YCMEA_IC02,
//------------------add by lc 为了功率计算能通过定值设置选择电压----------------
EN_YCMEA_I_END, // 遥测电流模拟量通道 END,本条不能修改 2
//================================================================================
// 遥测量电压通道
//================================================================================
EN_YCMEA_U_START = EN_YCMEA_I_END-1, // 遥测量电压通道 START,本条不能修改 1
//----------------------------------------------
//------------------add by lc 为了功率计算能通过定值设置选择电压----------------
// 以下部分添加格式必须是UA、UB、UC、UAB、UBC、UCA
EN_YCMEA_UA1, // 遥测A相电压1 2
EN_YCMEA_UB1, // 遥测B相电压1
EN_YCMEA_UC1, // 遥测C相电压1
EN_YCMEA_UA2, // 遥测A相电压2
EN_YCMEA_UB2, // 遥测B相电压2
EN_YCMEA_UC2, // 遥测C相电压2
EN_YCMEA_UAB1,
EN_YCMEA_UBC1,
EN_YCMEA_UCA1,
EN_YCMEA_UAB2,
EN_YCMEA_UBC2,
EN_YCMEA_UCA2,
//------------------add by lc 为了功率计算能通过定值设置选择电压----------------
EN_YCMEA_U_END, // 遥测电压模拟量通道 END,本条不能修改
//================================================================================
// 遥测量电压通道
//================================================================================
EN_YCMEA_3I0_START = EN_YCMEA_U_END-1, // 遥测量零序通道 START,本条不能修改
//----------------------------------------------
//------------------add by lc 为了功率计算能通过定值设置选择电压----------------
EN_YCMEA_3I01, // 3I01
EN_YCMEA_3I0_END,
EN_YCMEA_3U0_START = EN_YCMEA_3I0_END-1,
EN_YCMEA_3U01, // 3U01
EN_YCMEA_3U02, // 3U02
//----------------------------------------------
EN_YCMEA_3U0_END,
//================================================================================
// 频率测量通道
//================================================================================
EN_YCMEA_FR_START = EN_YCMEA_3U0_END-1,
EN_YCMEA_FR1,
//----------------------------------------------
EN_YCMEA_ANA_END, // 遥测交流模拟量通道 END,本条不能修改
//================================================================================
// 遥测量直流通道
//================================================================================
EN_YCMEA_DC_START = EN_YCMEA_ANA_END-1, // 遥测量直流通道 START,本条不能修改
//----------------------------------------------
EN_YCMEA_DC_01, // 直流01
EN_YCMEA_DC_02, // 直流02
//----------------------------------------------
EN_YCMEA_DC_END, // 遥测量直流通道 END,本条不能修改
//================================================================================
// 遥测量电度通道
//================================================================================
EN_YCMEA_P_START = EN_YCMEA_DC_END-1, // 遥测量电度通道 START,本条不能修改
//----------------------------------------------
EN_YCMEA_PA_1, // A相有功功率1
EN_YCMEA_PB_1, // B相有功功率1
EN_YCMEA_PC_1, // C相有功功率1
EN_YCMEA_P_1, // 有功功率1
EN_YCMEA_Q_1, // 无功功率1
EN_YCMEA_S_1, // 视在功率1
EN_YCMEA_COS_1, // 功率因素1
//----------------------------------------------
EN_YCMEA_P_END, // 遥测量电度通道 END,本条不能修改
//================================================================================
// 遥测量档位通道
//================================================================================
EN_YCMEA_DW_START = EN_YCMEA_P_END-1, // 遥测量档位通道 START,本条不能修改
//----------------------------------------------
//EN_YCMEA_DW_1, // 档位1
//----------------------------------------------
EN_YCMEA_DW_END, // 遥测量档位通道 END,本条不能修改
EN_YCMEA_END=EN_YCMEA_DW_END // 遥测量通道 END,本条不能修改
};
// BIT位定义
#define DB0 (0x01)
#define DB1 (0x02)
#define DB2 (0x04)
#define DB3 (0x08)
#define DB4 (0x10)
#define DB5 (0x20)
#define DB6 (0x40)
#define DB7 (0x80)
#define DB8 (0x100)
#define DB9 (0x200)
#define DB10 (0x400)
#define DB11 (0x800)
#define DB12 (0x1000)
#define DB13 (0x2000)
#define DB14 (0x4000)
#define DB15 (0x8000)
#define DB16 (0x10000)
#define DB17 (0x20000)
#define DB18 (0x40000)
#define DB19 (0x80000)
#define DB20 (0x100000)
#define DB21 (0x200000)
#define DB22 (0x400000)
#define DB23 (0x800000)
#define DB24 (0x1000000)
#define DB25 (0x2000000)
#define DB26 (0x4000000)
#define DB27 (0x8000000)
#define DB28 (0x10000000)
#define DB29 (0x20000000)
#define DB30 (0x40000000)
#define DB31 (0x80000000)
//============================================================================
//上送CPU定义
//============================================================================
enum _ANA_CPU_ { // 字节高三位分别表示
EN_CPU0 = 32, // bit5
EN_CPU1 = 64, // bit6
EN_CPU2 = 128 // bit7
};
//============================================================================
//模拟量常量表类型定义(应用于交流量常量表,及)
//============================================================================
enum _ANA_TYP_ { // 模拟量类型定义
EN_ANA_TYP_NULL = 0, // 未定义
EN_ANA_TYP_I, // 电流
EN_ANA_TYP_I0, // 电流
EN_ANA_TYP_U, // 电压
EN_ANA_TYP_Ux,
EN_ANA_TYP_U0, // 电压
EN_ANA_TYP_U_S, // 站用变电压
EN_ANA_TYP_P, // 有功功率
EN_ANA_TYP_Q, // 无功功率
EN_ANA_TYP_S, // 视在功率
EN_ANA_TYP_COS, // 功率因素
EN_ANA_TYP_DC_U, // 直流电压
EN_ANA_TYP_DC_I, // 直流电流
EN_ANA_TYP_GEAR, // 档位
EN_ANA_TYP_FR, // 频率
EN_ANA_TYP_T, // 温度
EN_ANA_TYP_DU, // 直流
EN_ANA_TYP_MC, // 脉冲
EN_ANA_TYP_AMP,
EN_ANA_TYP_ST, // 设备态
EN_ANA_TYP_IMP // 阻抗
};
#define CN_COE_YCMEA_I1A (1) // 遥测电流通道系数 1A ->
#define CN_COE_YCMEA_I1A_0
#define CN_COE_YCMEA_VOL (1) // 遥测电流通道系数 1V ->
// 条件成立常用标志
#define CN_FLAG_TRUE (0x5A) // 条件成立标志
#define CN_FLAG_FALSE (0xA5) // 条件不成立标志
#define CN_REC_ACTION (0x55) // 记录动作标志
#define CN_REC_RETURN (0xAA) // 记录返回标志
#define CN_REC_RETURN_YX (0x5500+CN_REC_RETURN) // 记录返回标志(表示不清除保护遥信)
// 遥测量常量信息表数据结构
typedef struct
{
uint16_t wIndex; // 模拟量虚端子号
uint8_t byPinName[32]; // 模拟量虚端子名称
uint8_t byUnit; // 二次模拟量单位索引号,字符串单位常量表中偏移地址
uint8_t byKiloUnit; // 一次模拟量单位索引号,字符串单位常量表中偏移地址
uint8_t byCpu; // 数据由哪一 CPU 上送
uint16_t wChanType; // 模拟量向量类型
uint8_t byName[8]; // 模拟量描述字符串
uint8_t byPhaseName[CN_PHASE_NAME_LEN]; // 模拟量相别
uint8_t byWidth; // 数据长度 (包含小数点长度)
uint8_t byDotBit; // 小数位数;
uint32_t dwRGB; // 显示颜色
uint16_t wCode; // 103 规约测量值代码
uint32_t dwChanCoe; // 通道系数
uint16_t wCapacity; // 遥测量的量程
uint32_t dwXuYcDflt; // 虚遥测的默认值
uint16_t wSamPinNO; // 遥测采样通道序号(仅原始采样通道及测频通道有效)
uint16_t wYcAdjFlg; // 遥测关联调节系数标志TRUE-带调节系数,否则 - 不带调节系数
uint16_t wHarmFlg; // 谐波计算标志TRUE-需要计算谐波,否则 - 不需要计算谐波
uint16_t wParIndex1; // 关联的遥测参数号,线电压关联相量虚端子,无关联为 0xAAAA
uint16_t wParIndex2; // 关联的遥测参数号,线电压关联相量虚端子,无关联为 0xAAAA
uint32_t dwCommAttr; // 通讯传输属性DB0 置位:103 上送DB1 置位调试规约上送DB2 置位:打印规约,DB3 置位显示上送DB4~DB31:未定义
uint32_t dwResePara; // 保留参数 (按照 bit 位使用)
}tagYcIndexTab;
const tagYcIndexTab g_tYcIndexTab[] =
{
//================================================================================
// 遥测量交流通道
//================================================================================
// wIndex byPinName byUnit byKiloUnit byCpu wChanType byName byPhase byWidth byDotBit dwRGB wCode wChanCoe wCapacity wXuYcDflt wSamPinNO wYcAdjFlg wHarmFlg wParIndex1 wParIndex2 dwCommAttr dwResePara
{EN_YCMEA_IA01, "EN_YCMEA_IA01", EN_UNIT_A, EN_UNIT_KA, EN_CPU0, EN_ANA_TYP_I, "Ia1", "A", 7, 3, CN_RGB_YELLOW, 92, CN_COE_YCMEA_I1A, 6, 1000, EN_UNIT01_A, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // A相测量电流
{EN_YCMEA_IB01, "EN_YCMEA_IB01", EN_UNIT_A, EN_UNIT_KA, EN_CPU0, EN_ANA_TYP_I, "Ib1", "B", 7, 3, CN_RGB_GREEN, 93, CN_COE_YCMEA_I1A, 6, 1000, EN_UNIT01_B, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // B相测量电流
{EN_YCMEA_IC01, "EN_YCMEA_IC01", EN_UNIT_A, EN_UNIT_KA, EN_CPU0, EN_ANA_TYP_I, "Ic1", "C", 7, 3, CN_RGB_RED, 94, CN_COE_YCMEA_I1A, 6, 1000, EN_UNIT01_C, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // C相测量电流
{EN_YCMEA_IA02, "EN_YCMEA_IA02", EN_UNIT_A, EN_UNIT_KA, EN_CPU0, EN_ANA_TYP_I, "Ia2", "A", 7, 3, CN_RGB_YELLOW, 95, CN_COE_YCMEA_I1A, 6, 1000, EN_UNIT02_A, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // A相测量电流
{EN_YCMEA_IB02, "EN_YCMEA_IB02", EN_UNIT_A, EN_UNIT_KA, EN_CPU0, EN_ANA_TYP_I, "Ib2", "B", 7, 3, CN_RGB_GREEN, 96, CN_COE_YCMEA_I1A, 6, 1000, EN_UNIT02_B, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // B相测量电流
{EN_YCMEA_IC02, "EN_YCMEA_IC02", EN_UNIT_A, EN_UNIT_KA, EN_CPU0, EN_ANA_TYP_I, "Ic2", "C", 7, 3, CN_RGB_RED, 97, CN_COE_YCMEA_I1A, 6, 1000, EN_UNIT02_C, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // C相测量电流
{EN_YCMEA_UA1, "EN_YCMEA_UA1", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Ua1", "A", 6, 2, CN_RGB_YELLOW, 98, CN_COE_YCMEA_VOL, 120, 6000, EN_VOL1_A, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, DB5},
{EN_YCMEA_UB1, "EN_YCMEA_UB1", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Ub1", "B", 6, 2, CN_RGB_GREEN, 99, CN_COE_YCMEA_VOL, 120, 6000, EN_VOL1_B, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, DB5},
{EN_YCMEA_UC1, "EN_YCMEA_UC1", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Uc1", "C", 6, 2, CN_RGB_RED, 100, CN_COE_YCMEA_VOL, 120, 6000, EN_VOL1_C, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, DB5},
{EN_YCMEA_UA2, "EN_YCMEA_UA2", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Ua2", "A", 6, 2, CN_RGB_YELLOW, 101, CN_COE_YCMEA_VOL, 120, 6000, EN_VOL2_A, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, DB5},
{EN_YCMEA_UB2, "EN_YCMEA_UB2", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Ub2", "B", 6, 2, CN_RGB_GREEN, 102, CN_COE_YCMEA_VOL, 120, 6000, EN_VOL2_B, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, DB5},
{EN_YCMEA_UC2, "EN_YCMEA_UC2", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Uc2", "C", 6, 2, CN_RGB_RED, 103, CN_COE_YCMEA_VOL, 120, 6000, EN_VOL2_C, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, DB5},
{EN_YCMEA_UAB1, "EN_YCMEA_UAB1", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Uab1", "A", 6, 2, CN_RGB_YELLOW, 104, CN_COE_YCMEA_VOL, 120, 10000, 0xAAAA, 0xAAAA, CN_FLAG_TRUE, EN_VOL1_A, EN_VOL1_B, 0xFFFF, 0 }, // AB相电压 1
{EN_YCMEA_UBC1, "EN_YCMEA_UBC1", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Ubc1", "B", 6, 2, CN_RGB_GREEN, 105, CN_COE_YCMEA_VOL, 120, 10000, 0xAAAA, 0xAAAA, CN_FLAG_TRUE, EN_VOL1_B, EN_VOL1_C, 0xFFFF, 0 }, // BC相电压 1
{EN_YCMEA_UCA1, "EN_YCMEA_UCA1", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Uca1", "C", 6, 2, CN_RGB_RED, 106, CN_COE_YCMEA_VOL, 120, 10000, 0xAAAA, 0xAAAA, CN_FLAG_TRUE, EN_VOL1_C, EN_VOL1_A, 0xFFFF, 0 }, // CA相电压 1
{EN_YCMEA_UAB2, "EN_YCMEA_UAB2", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Uab2", "A", 6, 2, CN_RGB_YELLOW, 107, CN_COE_YCMEA_VOL, 120, 10000, 0xAAAA, 0xAAAA, CN_FLAG_TRUE, EN_VOL2_A, EN_VOL2_B, 0xFFFF, 0 }, // AB相电压 1
{EN_YCMEA_UBC2, "EN_YCMEA_UBC2", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Ubc2", "B", 6, 2, CN_RGB_GREEN, 108, CN_COE_YCMEA_VOL, 120, 10000, 0xAAAA, 0xAAAA, CN_FLAG_TRUE, EN_VOL2_B, EN_VOL2_C, 0xFFFF, 0 }, // BC相电压 1
{EN_YCMEA_UCA2, "EN_YCMEA_UCA2", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Uca2", "C", 6, 2, CN_RGB_RED, 109, CN_COE_YCMEA_VOL, 120, 10000, 0xAAAA, 0xAAAA, CN_FLAG_TRUE, EN_VOL2_C, EN_VOL2_A, 0xFFFF, 0 }, // CA相电压 1
{EN_YCMEA_3I01, "EN_YCMEA_3I01", EN_UNIT_A, EN_UNIT_KA, EN_CPU0, EN_ANA_TYP_I0, "Io1", "0", 7, 3, CN_RGB_WHITE, 110, CN_COE_YCMEA_I1A, 6, 1000, EN_UNIT01_0, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // 零序电流
{EN_YCMEA_3U01, "EN_YCMEA_3U01", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U0, "Uo1", "0", 6, 2, CN_RGB_WHITE, 111, CN_COE_YCMEA_VOL, 120, 10000, EN_VOL1_0, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // 零序电压
{EN_YCMEA_3U02, "EN_YCMEA_3U02", EN_UNIT_V, EN_UNIT_KV, EN_CPU0, EN_ANA_TYP_U, "Uo2", "0", 6, 2, CN_RGB_WHITE, 112, CN_COE_YCMEA_VOL, 120, 10000, EN_VOL2_0, CN_FLAG_TRUE, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // 零序电压
{EN_YCMEA_FR1, "EN_YCMEA_FR1", EN_UNIT_HZ, EN_UNIT_HZ, EN_CPU0, EN_ANA_TYP_FR, "Fr1", "0", 5, 2, CN_RGB_YELLOW, 113, 1, 20, 4999, EN_VOL1_FR, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, DB0},
//======================================================================================
// 遥测量直流通道
//======================================================================================
{EN_YCMEA_DC_01, "EN_YCMEA_DC_01", EN_UNIT_NULL, EN_UNIT_NULL, EN_CPU0, EN_ANA_TYP_DU, "ZL01", "0", 6, 2, CN_RGB_WHITE, 114, 1, 512, 6000, EN_UNIT01_DC, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // 直流量1
{EN_YCMEA_DC_02, "EN_YCMEA_DC_02", EN_UNIT_NULL, EN_UNIT_NULL, EN_CPU0, EN_ANA_TYP_DU, "ZL02", "0", 6, 2, CN_RGB_WHITE, 115, 2, 512, 6000, 0xAAAA, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // 直流量2
//======================================================================================
// 遥测量电度通道
//======================================================================================
{EN_YCMEA_PA_1, "EN_YCMEA_PA_1", EN_UNIT_W, EN_UNIT_W, EN_CPU0, EN_ANA_TYP_P, "Pa1", "A", 8, 3, CN_RGB_YELLOW, 116, CN_COE_YCMEA_VOL * CN_COE_YCMEA_I1A, 866, 60000, 0xAAAA, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, DB5}, // PA
{EN_YCMEA_PB_1, "EN_YCMEA_PB_1", EN_UNIT_W, EN_UNIT_W, EN_CPU0, EN_ANA_TYP_P, "Pb1", "B", 8, 3, CN_RGB_GREEN, 117, CN_COE_YCMEA_VOL * CN_COE_YCMEA_I1A, 866, 60000, 0xAAAA, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, DB5}, // PB
{EN_YCMEA_PC_1, "EN_YCMEA_PC_1", EN_UNIT_W, EN_UNIT_W, EN_CPU0, EN_ANA_TYP_P, "Pc1", "C", 8, 3, CN_RGB_RED, 118, CN_COE_YCMEA_VOL * CN_COE_YCMEA_I1A, 866, 60000, 0xAAAA, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, DB5}, // PC
{EN_YCMEA_P_1, "EN_YCMEA_P_1", EN_UNIT_W, EN_UNIT_W, EN_CPU0, EN_ANA_TYP_P, "P1", "0", 8, 3, CN_RGB_YELLOW, 119, CN_COE_YCMEA_VOL * CN_COE_YCMEA_I1A, 866, 180000, 0xAAAA, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // P
{EN_YCMEA_Q_1, "EN_YCMEA_Q_1", EN_UNIT_VAR, EN_UNIT_VAR, EN_CPU0, EN_ANA_TYP_Q, "Q1", "0", 8, 3, CN_RGB_GREEN, 120, CN_COE_YCMEA_VOL * CN_COE_YCMEA_I1A, 866, 180000, 0xAAAA, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // Q
{EN_YCMEA_S_1, "EN_YCMEA_S_1", EN_UNIT_VA, EN_UNIT_VA, EN_CPU0, EN_ANA_TYP_S, "S1", "0", 8, 3, CN_RGB_YELLOW, 121, CN_COE_YCMEA_VOL * CN_COE_YCMEA_I1A, 866, 180000, 0xAAAA, CN_FLAG_TRUE, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // S
{EN_YCMEA_COS_1, "EN_YCMEA_COS_1", EN_UNIT_NULL, EN_UNIT_NULL, EN_CPU0, EN_ANA_TYP_COS, "COS1", "0", 7, 3, CN_RGB_GREEN, 122, 1, 1, 1000, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xFFFF, 0 }, // COS
};
uint16_t Get_RealData_Num(uint16_t wTabType)
{
uint16_t wNum = 0;
if (wTabType == EN_MEA_AC)
{
uint16_t wLoopMax = EN_YCMEA_ANA_END;
for(uint16_t index = 0; index < wLoopMax; index++)
{
if( (g_tYcIndexTab[index].dwCommAttr & DB3) == DB3 )
{
wNum++;
}
}
}
else if (wTabType == EN_MEA_DC)
{
uint16_t wLoopMax = EN_YCMEA_DC_END;
for(uint16_t index = EN_YCMEA_DC_START; index < wLoopMax; index++)
{
if( (g_tYcIndexTab[index].dwCommAttr & DB3) == DB3 )
{
wNum++;
}
}
}
return wNum;
}
#define CN_NUM_OF_PAGE_ANADBG ( 9 ) //每页显示的交流量/遥信量等的个数
void Model_Init(model_t *model)
{
if (model == NULL)
{
return;
}
memset(model, 0, sizeof(*model));
/* 默认顶栏标题,与菜单「实时数据」条目一致 */
model->topName = GlobalModel_GetMenuActionName();
model->wGroup = (Get_RealData_Num(GlobalModel_GetMenuActionAttrib()) + CN_NUM_OF_PAGE_ANADBG - 1) / CN_NUM_OF_PAGE_ANADBG;
model->wPage = 1;
}

16
src/Drv/pages/YC/model.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef YC_MODEL_H
#define YC_MODEL_H
#include "types.h"
typedef struct model_t model_t;
typedef struct model_t {
const uint8_t *topName;
uint16_t wGroup;
uint16_t wPage;
} model_t;
void Model_Init(model_t *model);
#endif

218
src/Drv/pages/YC/page.c Normal file
View File

@@ -0,0 +1,218 @@
#include <stdio.h>
#include <string.h>
#include "Drv/pages/YC/page.h"
#include "Drv/pages/YC/model.h"
#include "Drv/pages/YC/presenter.h"
#include "Drv/pages/YC/view.h"
#include "Drv/pages/global/renderer_lcd.h"
/* -------------------------------------------------------------------------
* 模块内静态对象说明:
* s_model - AppInfo页 Model 实例AppInfo数据与运行时结构
* s_view - AppInfo页 View 实例(布局与渲染能力)
* s_presenter - AppInfo页 Presenter 实例(输入处理与状态驱动)
* s_page - 页面管理器可注册的 page_t 描述对象
*
* 说明:
* - 以上对象均为文件内静态单例,生命周期覆盖进程运行期。
* - 通过 AppInfoPage_GetInstance() 暴露 s_page 给 PageManager 注册。
* ------------------------------------------------------------------------- */
static model_t s_model;
static view_t s_view;
static presenter_t s_presenter;
static page_t s_page;
static const PageRenderPort *s_port = NULL;
/* -------------------------------------------------------------------------
* 函数名: AppInfoPage_OnExit
* 功能:
* 页面退出回调占位点;当前版本无额外退出动作。
*
* 参数:
* page - 当前页面对象指针(本实现未直接使用)
*
* 边界处理:
* - 使用 (void)page 防止未使用参数告警。
*
* 说明:
* - 预留给后续扩展(如停止定时任务、冻结动画、保存瞬时 UI 状态等)。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void Page_OnExit(page_t *page)
{
s_port->clear_screen();
(void)page;
}
/* -------------------------------------------------------------------------
* 函数名: AppInfoPage_OnDestroy
* 功能:
* 页面销毁回调清空菜单页内部三层对象Model/View/Presenter状态。
*
* 参数:
* page - 当前页面对象指针(本实现未直接使用)
*
* 边界处理:
* - 使用 memset 全量清零静态对象,避免残留状态影响后续重建。
*
* 说明:
* - 与 is_cached 策略配合:当页面被标记为非缓存并弹栈销毁时,该函数用于复位。
* - page_t 元信息不在此函数复位,由页面生命周期创建阶段重新赋值。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void Page_OnDestroy(page_t *page)
{
(void)page;
memset(&s_model, 0, sizeof(s_model));
memset(&s_view, 0, sizeof(s_view));
memset(&s_presenter, 0, sizeof(s_presenter));
}
/* -------------------------------------------------------------------------
* 函数名: AppInfoPage_OnEvent
* 功能:
* 页面事件回调:校验输入事件后,将按键转交 Presenter 处理。
*
* 参数:
* page - 当前页面对象指针(本实现未直接使用)
* event - 输入事件指针
*
* 边界处理:
* - event 为 NULL 时返回 EVENT_UNHANDLED。
* - 仅处理 PAGE_EVENT_KEY 事件类型,其它类型返回 EVENT_UNHANDLED。
* - keyVal 为 0 视为无效按键,返回 EVENT_UNHANDLED。
*
* 说明:
* - 事件有效时调用 Presenter 对外输入接口执行业务流转。
* - 返回 EVENT_HANDLED表示该事件已被菜单页消费不再交给上层页面逻辑。
*
* 返回值:
* - EVENT_HANDLED : 事件已处理
* - EVENT_UNHANDLED : 事件无效或不属于本页处理范围
* ------------------------------------------------------------------------- */
static event_result_t Page_OnEvent(page_t *page, input_event_t *event)
{
(void)page;
if ((event == NULL) || (event->type != PAGE_EVENT_KEY) || (event->keyVal == 0))
{
return EVENT_UNHANDLED;
}
s_presenter.handle_input(&s_presenter, event->keyVal);
return EVENT_HANDLED;
}
/* -------------------------------------------------------------------------
* 函数名: AppInfoPage_OnLoop
* 功能:
* 页面循环回调:周期性驱动 Presenter 执行刷新逻辑。
*
* 参数:
* page - 当前页面对象指针(本实现未直接使用)
*
* 边界处理:
* - 使用 (void)page 防止未使用参数告警。
*
* 说明:
* - 实际刷新策略(全量/增量)由 Presenter 内部状态控制。
* - 该函数通常由 PageManager_Loop() 在主循环节拍中调用。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void Page_OnLoop(page_t *page)
{
(void)page;
s_presenter.refresh(&s_presenter);
}
/* -------------------------------------------------------------------------
* 函数名: AppInfoPage_OnCreate
* 功能:
* 页面创建回调:按 Model -> View -> Presenter 顺序完成菜单页运行时装配,
* 并初始化 page_t 描述对象字段。
*
* 参数:
* page - 当前页面对象指针(由 PageManager 传入)
*
* 边界处理:
* - 先清零 s_menuPage再统一重建其元信息与回调绑定避免脏状态遗留。
* - 假定 page 非空且来自 PageManager 生命周期调用链。
*
* 说明:
* - 初始化顺序固定:
* 1) MenuModel_Init(&s_model)
* 2) MenuView_Init(&s_view)
* 3) MenuPresenter_Init(&s_presenter, &s_model, &s_view)
* - 将 model/presenter/view 回填到 page 与 s_menuPage便于调试与统一访问。
* - s_menuPage 作为静态页面实例,对外由 MenuPage_GetInstance() 返回。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void Page_OnCreate(page_t *page)
{
/* 1) model init */
Model_Init(&s_model);
/* 2) view init */
View_Init(&s_view);
/* 3) presenter setup + runtime build */
Presenter_Init(&s_presenter, &s_model, &s_view);
page->model = &s_model;
page->presenter = &s_presenter;
page->view = &s_view;
s_page.presenter = &s_presenter;
s_page.view = &s_view;
s_page.model = &s_model;
s_port = PageRenderer_Lcd();
}
/* -------------------------------------------------------------------------
* 函数名: YCPage_OnEnter
* 功能:
* 页面进入回调:将菜单渲染标记为“首帧全量刷新”,并立即触发一次刷新。
*
* 参数:
* page - 当前页面对象指针(本实现未直接使用)
*
* 边界处理:
* - 本函数不依赖 page 内容,统一转为 (void)page 消除未使用告警。
*
* 说明:
* - 通过 refresh(..., 1) 告知 Presenter 下一次刷新走首帧路径。
* - 进入页面后立即刷新,确保界面可见状态与内部状态同步。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void Page_OnEnter(page_t *page)
{
(void)page;
/* 首帧全量刷新 */
LOG("YCPage_OnEnter\n");
s_presenter.refresh(&s_presenter);
}
page_t *YCPage_GetInstance(void)
{
/* 确保在注册到 PageManager 前,页面生命周期回调已就绪 */
memset(&s_page, 0, sizeof(s_page));
s_page.page_id = PAGE_ID_YC;
s_page.is_cached = 1;
s_page.on_create = Page_OnCreate;
s_page.on_enter = Page_OnEnter;
s_page.on_exit = Page_OnExit;
s_page.on_destroy = Page_OnDestroy;
s_page.on_event = Page_OnEvent;
s_page.on_loop = Page_OnLoop;
return &s_page;
}

8
src/Drv/pages/YC/page.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef YC_PAGE_H
#define YC_PAGE_H
#include "Drv/pages/page.h"
page_t *YCPage_GetInstance(void);
#endif

View File

@@ -0,0 +1,91 @@
#include "Drv/pages/YC/presenter.h"
#include "Drv/pages/page_manager.h"
#include "Drv/key.h"
#include <string.h>
static void Presenter_HandleInput(presenter_t *presenter, uint8_t keyVal)
{
switch (keyVal)
{
case KEY_ESC:
(void)PageManager_Pop();
break;
default: break;
}
}
/* -------------------------------------------------------------------------
* 函数名MenuPresenter_Refresh
* 功能:
* Presenter 层的对外刷新接口,根据是否为首帧渲染选择不同的刷新策略。
* 本函数作为 menu_presenter_t::refresh 回调被调用,负责协调 View 层完成界面更新。
*
* 参数:
* presenter - 菜单 Presenter 实例指针,内部持有 menuCtrl 上下文和 view 接口引用
* isFirstFrame - 是否为首帧标志:
* 1 - 首帧渲染:需要完整初始化并刷新整个菜单界面
* 0 - 非首帧渲染:根据当前状态差异进行增量或局部刷新
*
* 刷新策略:
* 首帧模式 (isFirstFrame == 1):
* - 调用 View 层的 full_refresh() 接口,完整重绘整个菜单界面。
* - 此时 menuCtrl 中的导航路径、选中项等状态已完成初始化,可安全进行全量渲染。
* - MODE_NONE 表示不进行特殊模式过滤(如调试模式、特定层级过滤等)。
*
* 非首帧模式 (isFirstFrame == 0):
* - 调用 MenuPresenter_RenderByState() 进行智能状态对比刷新:
* 1) 比较 pt0Level 与 ptRoute[0],判断顶层上下文是否切换
* 2) 比较 ptCurBak 与 ptCurrent判断选中项是否变化
* 3) 根据层级关系和父节点关联选择最优渲染策略:
* - 同层同父:局部反显更新(旧选中恢复 + 新选中高亮)
* - 新层级 >= 旧层级:补绘受影响层级
* - 回退到更高层:整页刷新保证一致性
* - 此策略可避免不必要的重绘,提升界面响应性能。
*
* 调用关系:
* - 被 MenuPresenter_HandleInput() 在导航状态变化后调用isFirstFrame = 0
* - 被外部初始化完成后首次调用isFirstFrame = 1
* - 通过 presenter->refresh 函数指针绑定,符合 Presenter 的接口抽象。
*
* 边界处理:
* - 本函数假设 presenter 指针有效,不做空指针校验(由调用方保证)。
* - view 接口的 full_refresh() 和内部渲染逻辑负责具体的绘制安全校验。
* ------------------------------------------------------------------------- */
static void Presenter_Refresh(presenter_t *presenter)
{
presenter->view->show_top_name(presenter->model->topName);
presenter->view->show_info_page(presenter->model->wPage, presenter->model->wGroup);
}
/* -------------------------------------------------------------------------
* 函数名: MenuPresenter_Init
* 功能:
* 初始化菜单 Presenter 实例,完成依赖绑定、对外接口挂接以及初始导航状态装配。
*
* 参数:
* presenter - 待初始化的 Presenter 实例
* model - 菜单 Model 实例,提供菜单树与运行时数据
* view - 菜单 View 实例,提供刷新与绘制能力
*
* 边界处理:
* - 若 `presenter`、`model` 或 `view` 任一为空,则直接返回。
*
* 说明:
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
void Presenter_Init(presenter_t *presenter, model_t *model, view_t *view)
{
ASSERT((presenter == NULL) || (model == NULL) || (view == NULL));
if ((presenter == NULL) || (model == NULL) || (view == NULL))
{
return;
}
memset(presenter, 0, sizeof(*presenter));
presenter->model = model;
presenter->view = view;
presenter->handle_input = Presenter_HandleInput;
presenter->refresh = Presenter_Refresh;
}

View File

@@ -0,0 +1,17 @@
#ifndef YC_PRESENTER_H
#define YC_PRESENTER_H
#include "Drv/pages/YC/model.h"
#include "Drv/pages/YC/view.h"
typedef struct presenter_t presenter_t;
typedef struct presenter_t {
model_t *model;
view_t *view;
void (*handle_input)(presenter_t *presenter, uint8_t keyVal);
void (*refresh)(presenter_t *presenter);
} presenter_t;
void Presenter_Init(presenter_t *presenter, model_t *model, view_t *view);
#endif

45
src/Drv/pages/YC/view.c Normal file
View File

@@ -0,0 +1,45 @@
#include "Drv/pages/YC/view.h"
#include <stdio.h>
static const PageRenderPort *s_port = NULL;
static void YCView_ShowInfoPage(uint16_t wPageNum, uint16_t wPageMax)
{
s_port->show_info_page(wPageNum, wPageMax);
}
static void YCView_ShowTerminalInfo(void)
{
uint8_t *context[] = {
"终端类型 F30",
"终端型号 F30",
"软件版本 SV0.010",
"硬件版本 HW0.010",
"软件校验 4454",
"程序日期 2024.08.27"
};
s_port->show_str(32, 26, "馈线自动化终端");
for(uint8_t index = 0; index < 6; index++ )
{
s_port->show_str(6, 26 + (index + 1) * (s_port->get_ascii_height() + s_port->get_row_space()), context[index]);
}
}
static void YCView_ShowTopName(const uint8_t *name)
{
uint16_t wLen = s_port->get_utf8_len(name) * s_port->get_ascii_width();
s_port->fill_rect(0, 0, s_port->get_size_x() - 1, s_port->get_size_y() - 1, s_port->get_color_back());
/* 显示顶部名称,居中显示 */
s_port->show_str((s_port->get_size_x() - wLen) / 2, 3, name);
s_port->draw_meitou(18, 2);
}
void View_Init(view_t *view)
{
s_port = PageRenderer_Lcd();
view->show_top_name = YCView_ShowTopName;
view->show_info_page = YCView_ShowInfoPage;
}

14
src/Drv/pages/YC/view.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef YC_VIEW_H
#define YC_VIEW_H
#include "types.h"
#include "Drv/pages/global/renderer_lcd.h"
typedef struct view_t {
void (*show_top_name)(const uint8_t *name);
void (*show_info_page)(uint16_t wPageNum, uint16_t wPageMax);
} view_t;
void View_Init(view_t *view);
#endif

View File

@@ -4,6 +4,31 @@
static GlobalModel s_globalModel;
/* -------------------------------------------------------------------------
* 函数名GlobalModel_CopyText
* 功能:
* 安全地将源字符串拷贝到目标缓冲区,确保不会发生缓冲区溢出。
*
* 参数:
* dst - 目标缓冲区指针(输出),用于存放拷贝的字符串
* dstSize - 目标缓冲区的大小(字节)
* src - 源字符串指针(输入),需要被拷贝的字符串
*
* 边界处理:
* - 若 dst 为 NULL 或 dstSize 为 0函数直接返回不做任何操作。
* - 若 src 为 NULL则将目标缓冲区置为空字符串 (dst[0] = '\0')。
* - 拷贝时最多保留 dstSize-1 个字符,确保最后一个字节用于存放字符串结束符 '\0'。
* - 若在拷贝过程中遇到源字符串的结束符 '\0',则提前终止拷贝。
*
* 说明:
* - 本函数是一个安全的字符串拷贝工具,专门用于全局模型中菜单名称和提示文本的拷贝。
* - 通过限制拷贝长度为 dstSize-1 并强制在末尾添加 '\0',确保目标缓冲区永远不会越界。
* - 当源字符串长度大于等于目标缓冲区大小时,会截断源字符串,但保证结果仍是有效的 C 字符串。
* - 该函数为静态函数,仅在当前文件内部使用。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void GlobalModel_CopyText(uint8_t *dst, uint16_t dstSize, const uint8_t *src)
{
uint16_t i;
@@ -29,32 +54,141 @@ static void GlobalModel_CopyText(uint8_t *dst, uint16_t dstSize, const uint8_t *
dst[dstSize - 1] = '\0';
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_Init
* 功能:
* 初始化全局模型实例,将所有成员变量设置为零值。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数不处理任何异常情况,直接对静态全局变量进行清零操作。
*
* 说明:
* - 本函数用于在系统启动或需要重置全局状态时调用。
* - 通过 memset 将 s_globalModel 的所有字节设置为 0包括
* 1) activeYcType当前遥测类型
* 2) activeMenuPara当前菜单参数
* 3) activeActionId当前菜单动作 ID
* 4) activeMenuName当前菜单名称数组
* 5) activeMenuTip当前菜单提示文本数组
* - 初始化后,全局模型处于空状态,需要调用其他设置函数来配置有效值。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
void GlobalModel_Init(void)
{
memset(&s_globalModel, 0, sizeof(s_globalModel));
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_Instance
* 功能:
* 获取全局模型单例实例的指针,用于访问和修改全局状态数据。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数不做任何校验,始终返回静态变量 s_globalModel 的地址。
* - 调用方应确保在调用此函数前已先调用 GlobalModel_Init() 进行初始化。
*
* 说明:
* - 本函数采用单例模式,提供对全局模型实例的访问接口。
* - 返回的是静态变量 s_globalModel 的指针,该变量在整个程序生命周期内只有一份副本。
* - 调用方可以通过返回的指针直接访问和修改全局状态成员,如 activeYcType、activeActionId 等。
* - 由于返回的是原始指针,调用方在操作时应注意线程安全和数据一致性。
*
* 返回值:
* - 指向 GlobalModel 结构体的指针
* ------------------------------------------------------------------------- */
GlobalModel *GlobalModel_Instance(void)
{
return &s_globalModel;
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_SetActiveYcType
* 功能:
* 设置当前活跃的遥测类型,用于标识系统正在处理哪种类型的遥测量。
*
* 参数:
* ycType - 遥测类型值,通常为枚举类型或预定义的类型常量
*
* 边界处理:
* - 本函数不做参数合法性校验,调用方应保证 ycType 为有效值。
*
* 说明:
* - 该函数用于设置全局模型中的 activeYcType 字段。
* - 遥测类型用于区分不同类型的交流量(如电压、电流、功率等)。
* - 设置后,系统其他模块可通过 GetActiveYcType() 查询当前类型。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
void GlobalModel_SetActiveYcType(uint16_t ycType)
{
s_globalModel.activeYcType = ycType;
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_GetActiveYcType
* 功能:
* 获取当前活跃的遥测类型。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数不做任何校验,直接返回静态变量的值。
* - 若系统未初始化或类型未被设置,可能返回 0默认值
*
* 说明:
* - 该函数用于查询全局模型中的 activeYcType 字段。
* - 返回值表示当前系统正在处理或最后设置的遥测类型。
* - 调用方应根据返回的值进行相应的数据处理或界面显示逻辑。
*
* 返回值:
* - 当前活跃的遥测类型值
* ------------------------------------------------------------------------- */
uint16_t GlobalModel_GetActiveYcType(void)
{
return s_globalModel.activeYcType;
}
void GlobalModel_SetMenuAction(uint16_t actionId,
/* -------------------------------------------------------------------------
* 函数名GlobalModel_SetMenuAction
* 功能:
* 设置当前菜单的动作信息,包括动作 ID、名称、提示文本和参数。
*
* 参数:
* actionId - 菜单动作 ID用于标识具体的菜单操作如查看、设置等
* menuName - 菜单名称字符串,显示在界面上的菜单标题
* menuTip - 菜单提示文本字符串,用于显示辅助说明信息
* menuPara - 菜单参数,传递与当前菜单相关的额外数据
*
* 边界处理:
* - 若 menuName 或 menuTip 为 NULL对应缓冲区将被置为空字符串。
* - 名称和提示文本的长度会被限制在各自缓冲区大小内50 字节),超长部分会被截断。
* - 本函数不做输入参数的合法性校验,调用方应保证 actionId/menuPara 为有效值。
*
* 说明:
* - 该函数用于更新全局模型中的菜单动作相关信息。
* - 通过 GlobalModel_CopyText() 进行安全拷贝,确保不会发生缓冲区溢出。
* - 设置后,系统其他模块可通过对应的 Get 系列函数查询当前菜单状态。
* - 此函数通常在进入新菜单或切换菜单时调用,用于更新全局上下文信息。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
void GlobalModel_SetMenuAction(uint16_t activeAttrib,
const uint8_t *menuName,
const uint8_t *menuTip,
uint16_t menuPara)
{
s_globalModel.activeActionId = actionId;
s_globalModel.activeAttrib = activeAttrib;
s_globalModel.activeMenuPara = menuPara;
GlobalModel_CopyText(s_globalModel.activeMenuName,
(uint16_t)sizeof(s_globalModel.activeMenuName),
@@ -64,22 +198,124 @@ void GlobalModel_SetMenuAction(uint16_t actionId,
menuTip);
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_GetMenuActionId
* 功能:
* 获取当前菜单的动作 ID。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数不做任何校验,直接返回静态变量的值。
* - 若未调用 SetMenuAction() 设置,将返回默认值 0。
*
* 说明:
* - 该函数用于查询全局模型中的 activeActionId 字段。
* - 返回值表示当前菜单对应的动作类型,可用于判断用户当前所处的菜单位置。
*
* 返回值:
* - 当前菜单的动作 IDmenu_action_id_t 枚举值)
* ------------------------------------------------------------------------- */
uint16_t GlobalModel_GetMenuActionId(void)
{
return s_globalModel.activeActionId;
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_GetMenuActionPara
* 功能:
* 获取当前菜单的参数值。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数不做任何校验,直接返回静态变量的值。
* - 若未调用 SetMenuAction() 设置,将返回默认值 0。
*
* 说明:
* - 该函数用于查询全局模型中的 activeMenuPara 字段。
* - 返回值是与当前菜单相关的额外参数数据,具体含义取决于菜单类型。
*
* 返回值:
* - 当前菜单的参数值
* ------------------------------------------------------------------------- */
uint16_t GlobalModel_GetMenuActionPara(void)
{
return s_globalModel.activeMenuPara;
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_GetMenuActionName
* 功能:
* 获取当前菜单的名称字符串。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数返回静态缓冲区的指针,调用方不应修改返回的字符串内容。
* - 若未调用 SetMenuAction() 设置,将返回空字符串指针(内容为 "\0")。
*
* 说明:
* - 该函数用于查询全局模型中的 activeMenuName 缓冲区。
* - 返回的是 const 指针,表明调用方只能读取不能修改该字符串。
* - 字符串长度最多为 49 个字符(预留 1 字节给结束符 '\0')。
*
* 返回值:
* - 指向当前菜单名称字符串的常量指针
* ------------------------------------------------------------------------- */
const uint8_t *GlobalModel_GetMenuActionName(void)
{
return s_globalModel.activeMenuName;
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_GetMenuActionTip
* 功能:
* 获取当前菜单的提示文本字符串。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数返回静态缓冲区的指针,调用方不应修改返回的字符串内容。
* - 若未调用 SetMenuAction() 设置,将返回空字符串指针(内容为 "\0")。
*
* 说明:
* - 该函数用于查询全局模型中的 activeMenuTip 缓冲区。
* - 返回的是 const 指针,表明调用方只能读取不能修改该字符串。
* - 字符串长度最多为 49 个字符(预留 1 字节给结束符 '\0')。
*
* 返回值:
* - 指向当前菜单提示文本字符串的常量指针
* ------------------------------------------------------------------------- */
const uint8_t *GlobalModel_GetMenuActionTip(void)
{
return s_globalModel.activeMenuTip;
}
/* -------------------------------------------------------------------------
* 函数名GlobalModel_GetMenuActionAttrib
* 功能:
* 获取当前菜单的动作属性。
*
* 参数:
* 无
*
* 边界处理:
* - 本函数不做任何校验,直接返回静态变量的值。
* - 若未调用 SetMenuAction() 设置,将返回默认值 0。
*
* 说明:
* - 该函数用于查询全局模型中的 activeAttrib 字段。
* - 返回值是与当前菜单相关的额外参数数据,具体含义取决于菜单类型。
*
* 返回值:
* - 当前菜单的动作属性
* ------------------------------------------------------------------------- */
uint16_t GlobalModel_GetMenuActionAttrib(void)
{
return s_globalModel.activeAttrib;
}

View File

@@ -46,11 +46,14 @@ typedef enum
MENU_ACTION_YC_SET_ADJ_COE
} menu_action_id_t;
typedef struct
{
uint16_t activeYcType;
uint16_t activeMenuPara;
uint16_t activeActionId;
uint16_t activeAttrib;
uint8_t activeMenuName[50];
uint8_t activeMenuTip[50];
} GlobalModel;
@@ -59,7 +62,7 @@ void GlobalModel_Init(void);
GlobalModel *GlobalModel_Instance(void);
void GlobalModel_SetActiveYcType(uint16_t ycType);
uint16_t GlobalModel_GetActiveYcType(void);
void GlobalModel_SetMenuAction(uint16_t actionId,
void GlobalModel_SetMenuAction(uint16_t activeAttrib,
const uint8_t *menuName,
const uint8_t *menuTip,
uint16_t menuPara);
@@ -67,5 +70,6 @@ uint16_t GlobalModel_GetMenuActionId(void);
uint16_t GlobalModel_GetMenuActionPara(void);
const uint8_t *GlobalModel_GetMenuActionName(void);
const uint8_t *GlobalModel_GetMenuActionTip(void);
uint16_t GlobalModel_GetMenuActionAttrib(void);
#endif

View File

@@ -4,6 +4,13 @@
#include "lcd_draw.h"
#include "lcd_text.h"
/* MSVC 对含多字节/中文格式串的静态分析可能误报 C4474/C4996。
* 本文件内的格式化输出均为受控 buffer并用于显示文本渲染。 */
#if defined(_MSC_VER)
#pragma warning(disable : 4474)
#pragma warning(disable : 4996)
#endif
static uint16_t PageRenderer_LcdSizeX(void)
{
return LCD_SIZE_X;
@@ -53,7 +60,7 @@ static uint16_t PageRenderer_LcdGetASCIIHeight(void)
* 返回值:
* - UTF-8 字符串的显示宽度
* ------------------------------------------------------------------------- */
static uint16_t PageRenderer_LcdGetUtf8Len(uint8_t *str)
static uint16_t PageRenderer_LcdGetUtf8Len(const uint8_t *str)
{
uint16_t strLen = 0;
uint32_t unicode;
@@ -76,6 +83,55 @@ static void PageRenderer_ClearScreen(void)
{
Lcd_FillRect(0, 0, LCD_SIZE_X - 1, LCD_SIZE_Y - 1, LCD_BACK);
}
/* -------------------------------------------------------------------------
* 函数名: PageRenderer_LcdDrawMeitou
* 功能:
* 绘制菜单标题装饰线(“眉头”样式):中间横线 + 左右两端斜线。
*
* 参数:
* yStart - 装饰线基准 Y 坐标(横线所在行)
* width - 线宽参数(传递给 line_h/line
*
* 边界处理:
* - 坐标范围合法性由上层布局计算保证。
*
* 说明:
* - 颜色统一使用字体前景色PageRenderer_LcdColorFont确保装饰与文字风格一致。
* - 绘制顺序:
* 1) 中间横线x:16~144
* 2) 左斜线8, yStart-8 -> 16, yStart
* 3) 右斜线144, yStart -> 152, yStart-8
* - 该函数用于视觉分隔与层次强调,不改变菜单状态数据。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void PageRenderer_LcdDrawMeitou(uint16_t yStart, uint16_t width)
{
uint8_t fontColor = PageRenderer_LcdColorFont();
Lcd_LineH(16, 144, yStart, width, fontColor);
Lcd_Line(8, yStart - 8, 16, yStart, width, fontColor);
Lcd_Line(144, yStart, 152, yStart - 8, width, fontColor);
}
void PageRenderer_LcdShowInfoPage(uint16_t wPageNum, uint16_t wPageMax )
{
/* show_str 期望的是 '\0' 结尾的 UTF-8 字符串 */
uint8_t pbyTips[64];
uint16_t y = LCD_SIZE_Y - 16;
/* 格式化字符串(用于 LCD 文本显示) */
#if defined(_MSC_VER)
(void)sprintf_s((char *)pbyTips, sizeof(pbyTips), "第%4u 页 , 共%4u 页",
(unsigned)wPageNum, (unsigned)wPageMax);
#else
(void)snprintf((char *)pbyTips, sizeof(pbyTips), "第%4u 页 , 共%4u 页",
(unsigned)wPageNum, (unsigned)wPageMax);
#endif
Lcd_ShowStr(6, y, pbyTips);
}
static const PageRenderPort g_lcd_port = {
.get_size_x = PageRenderer_LcdSizeX,
.get_size_y = PageRenderer_LcdSizeY,
@@ -93,6 +149,8 @@ static const PageRenderPort g_lcd_port = {
.invert = Lcd_Invert,
.show_str = Lcd_ShowStr,
.clear_screen = PageRenderer_ClearScreen,
.draw_meitou = PageRenderer_LcdDrawMeitou,
.show_info_page = PageRenderer_LcdShowInfoPage,
};
const PageRenderPort *PageRenderer_Lcd(void)

View File

@@ -11,7 +11,7 @@ typedef struct
uint8_t (*get_color_back)(void);
uint16_t (*get_ascii_width)(void);
uint16_t (*get_ascii_height)(void);
uint16_t (*get_utf8_len)(uint8_t *str);
uint16_t (*get_utf8_len)(const uint8_t *str);
uint16_t (*get_row_space)(void);
int8_t (*fill_rect)(uint16_t left_x, uint16_t top_y, uint16_t right_x, uint16_t bottom_y, uint8_t color);
int8_t (*line_h)(uint16_t x_start, uint16_t x_end, uint16_t y, uint16_t width, uint8_t color);
@@ -19,8 +19,10 @@ typedef struct
int8_t (*line)(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, uint16_t width, uint8_t color);
int8_t (*set_pixel)(uint16_t x, uint16_t y, uint8_t color);
int8_t (*invert)(uint16_t left_x, uint16_t top_y, uint16_t right_x, uint16_t bottom_y);
int8_t (*show_str)(uint16_t x, uint16_t y, uint8_t *text);
int8_t (*clear_screen)(void);
int8_t (*show_str)(uint16_t x, uint16_t y, const uint8_t *text);
void (*clear_screen)(void);
void (*draw_meitou)(uint16_t yStart, uint16_t width);
void (*show_info_page)(uint16_t wPageNum, uint16_t wPageMax);
} PageRenderPort;
const PageRenderPort *PageRenderer_Lcd(void);

View File

@@ -42,38 +42,7 @@ enum _SOFT_TYPE_NUMBER
EN_SOFT_TYPE_END
};
enum _MEA_TYPE_
{
EN_MEA_RLY,
EN_MEA_RLY2,
EN_MEA_RLY3,
EN_MEA_ANA,
EN_MEA_ANA2,
EN_MEA_ANA3,
EN_MEA_AC,
EN_MEA_DC,
EN_MEA_SYN,
EN_MEA_POWER,
EN_MEA_DD,
EN_MEA_JLYC,
EN_MEA_GEAR,
EN_MEA_TQ,
EN_MEA_INPUT1,
EN_MEA_INPUT2,
EN_MEA_INPUT3,
EN_INPUT_RLY_ALL,
EN_INPUT_RLY_FAULT,
EN_INPUT_RLY_OTHER,
EN_INPUT_BS_ALL,
EN_INPUT_BS_FAULT,
EN_INPUT_BS_OTHER,
EN_MEA_ADJ,
EN_MEA_YX,
EN_OUTPUT_TRIP,
EN_OUTPUT_SIGN,
EN_MEA_LS,
EN_MEA_SCRLY
};
enum _INDEX_VALUE_TYPE_
{

View File

@@ -2,7 +2,7 @@
#include <stddef.h>
#include <string.h>
#include "../global/global_state.h"
#include "../../key.h"
/* -------------------------------------------------------------------------
@@ -163,6 +163,7 @@ static MenuNavResult MenuNavigator_ProcessKey(tagMenuCtrl *menuCtrl, uint8_t key
}
else if (ptCurrent->menuDef.pfnWinProc != NULL)
{
GlobalModel_SetMenuAction(ptCurrent->menuDef.byAttrib, ptCurrent->menuDef.byName, ptCurrent->menuDef.byTip, ptCurrent->menuDef.wPara);
/* 无子菜单但有回调函数:执行窗口回调(如打开弹窗) */
ptCurrent->menuDef.pfnWinProc();
}

View File

@@ -4,39 +4,6 @@
static const PageRenderPort *s_port = NULL;
/* -------------------------------------------------------------------------
* 函数名: MenuView_DrawMeitou
* 功能:
* 绘制菜单标题装饰线(“眉头”样式):中间横线 + 左右两端斜线。
*
* 参数:
* view - 菜单视图对象,提供底层渲染端口
* yStart - 装饰线基准 Y 坐标(横线所在行)
* width - 线宽参数(传递给 line_h/line
*
* 边界处理:
* - 本函数不做空指针判定,调用方需保证 view 与 s_port 有效。
* - 坐标范围合法性由上层布局计算保证。
*
* 说明:
* - 颜色统一使用字体前景色get_color_font确保装饰与文字风格一致。
* - 绘制顺序:
* 1) 中间横线x:16~144
* 2) 左斜线8, yStart-8 -> 16, yStart
* 3) 右斜线144, yStart -> 152, yStart-8
* - 该函数用于视觉分隔与层次强调,不改变菜单状态数据。
*
* 返回值:
* - 无
* ------------------------------------------------------------------------- */
static void MenuView_DrawMeitou(MenuView *view, uint16_t yStart, uint16_t width)
{
uint8_t fontColor = s_port->get_color_font();
s_port->line_h(16, 144, yStart, width, fontColor);
s_port->line(8, yStart - 8, 16, yStart, width, fontColor);
s_port->line(144, yStart, 152, yStart - 8, width, fontColor);
}
/* -------------------------------------------------------------------------
* 函数名: MenuView_DrawBoundaryBox
* 功能:
@@ -155,7 +122,7 @@ static void MenuView_DrawBoundaryBox(MenuView *view, uint16_t leftX, uint16_t to
*
* 说明:
* - 先清空顶部区域y: 0~32避免旧文案残留。
* - 再调用 MenuView_DrawMeitou() 绘制标题装饰线,保持页面视觉一致性。
* - 再调用 s_port->draw_meitou(16, 2) 绘制标题装饰线,保持页面视觉一致性。
* - 模式文案映射:
* MODE_OVERFLOW_PROTECTION -> "当前模式: 过流保护"
* MODE_LOCAL_FEEDER_SEGMENT -> "就地馈线: 分段模式"
@@ -170,7 +137,7 @@ static void MenuView_ShowTopLevel(MenuView *view, MenuMode mode)
{
uint16_t lcdSizeX = s_port->get_size_x();
s_port->fill_rect(0, 0, lcdSizeX - 1, 32, s_port->get_color_back());
MenuView_DrawMeitou(view, 16, 2);
s_port->draw_meitou(16, 2);
/* 在 0 级菜单标题栏下方显示当前运行模式提示文字 */
if (mode == MODE_OVERFLOW_PROTECTION)
{

View File

@@ -11,6 +11,7 @@
* PAGE_ID_NONE - 无效页面 ID / 未初始化占位值
* PAGE_ID_MENU - 菜单页 ID当前主运行页
* PAGE_ID_APP_INFO - 装置信息页 ID在 main 中与菜单页一并注册)
* PAGE_ID_YC - 遥测页 ID
* PAGE_ID_MAX - 上界哨兵,不可作为有效页面 ID 使用
*
* 使用约束:
@@ -22,6 +23,7 @@ typedef enum
PAGE_ID_NONE = 0,
PAGE_ID_MENU = 1,
PAGE_ID_APP_INFO = 2, /* 装置信息页AppInfoPage_GetInstance */
PAGE_ID_YC = 3, /* 遥测页YCPage_GetInstance */
PAGE_ID_MAX
} page_id_t;

View File

@@ -33,6 +33,7 @@ static int getch(void)
#include "Drv/pages/page_manager.h"
#include "Drv/pages/AppInfo/page.h"
#include "Drv/pages/menu/page.h"
#include "Drv/pages/YC/page.h"
#include "TCP/tcp.h"
#include "remoteDisplay.h"
#include "Drv/key.h"
@@ -71,6 +72,7 @@ int main(void)
Lcd_Init(); /* 初始化屏幕显存:由入口统一完成 */
(void)PageManager_Register(MenuPage_GetInstance());
(void)PageManager_Register(AppInfoPage_GetInstance());
(void)PageManager_Register(YCPage_GetInstance());
(void)PageManager_Navigate(PAGE_ID_MENU);
Key_Init(); /* 初始化按键 */
printf("PC 端 HMI 菜单模拟启动TCP 服务在单独线程,端口 7003\n");

View File

@@ -101,6 +101,7 @@ add_dtu_test(
"${CMAKE_SOURCE_DIR}/src/Drv/pages/menu/view.c"
"${CMAKE_SOURCE_DIR}/src/Drv/pages/menu/presenter.c"
"${CMAKE_SOURCE_DIR}/src/Drv/pages/menu/page.c"
"${CMAKE_SOURCE_DIR}/src/Drv/pages/global/global_state.c"
"${CMAKE_SOURCE_DIR}/src/Drv/pages/global/renderer_lcd.c"
"${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd_text.c"
"${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd.c"