EMS 知识库
首页 / knowledge/代码解析/midware/evc

evc.c

源文件路径:midware/evc/evc.c 所属模块:midware/evc(一代交流充电桩 SMILE-EVCT11 通信中间件) 代码行数:1146

1. 文件职责

本文件是 EMS 主控对一代交流充电桩(EVC,SMILE-EVCT11,单桩)的完整驱动实现,通过 USART3(RS485)以 Modbus-RTU 主站方式周期读写充电桩。

数据流上游:evc_gat_sys_data()(evc.c:145)从 g_t_logic_info、meter_read_*()、logic_read_*() 抓取电网/逆变器/电池快照;核心环节:evc_calculated_total_power()(evc.c:619)与 evc_calculate_single_station_power()(evc.c:790)按充电策略算出"剩余可分配给充电桩的功率",再由 send_cmd_evc()(evc.c:352)写成 Modbus 0x10 写多寄存器帧下发;下游:功率、电量、故障字通过 get_evc_*() 接口被 logic.c、net/ems.c、flash_data_store.c、fault_warn_log.c 消费。

驱动方:midware/interface/interface.c:351 的 Modbus 任务在 get_evc_enable_flag()==TRUE 且非升级状态下每 100ms 调用一次 evc_control()(evc.c:958),内部再自行分频出 1s 读、10s 控的节拍。

本文件与二代桩实现 evc_ii.c 是互斥的两套协议:同一时刻只启用其一(interface.c:347-357),二者共用 g_evc_send_buf/g_evc_recv_buf。

2. 关键数据结构与宏

名称类型说明
g_evc_send_buf[EVC_BUF_LEN]全局数组发送缓存 256B,一代/二代/升级三模块共用(evc.c:25)
g_evc_recv_buf[EVC_BUF_LEN]全局数组接收缓存 256B(evc.c:26)
g_t_evc_setting_info全局变量(EVC_SETTING_TABLE_T)单桩设置表;本文件会就地改写其 u8_ev_phase、u16_max_charg_curr 字段(evc.c:811/824/834)
g_t_evc_config_table全局变量(EVC_CONFIG_TABLE_T)整体配置表;本文件决定性地使用 u16_max_consume_cur(evc.c:630)与 u8_plot(evc.c:699)
g_t_evc_run_info全局变量(EVC_RUN_INFO_T)运行数据表,本文件的读写核心
g_t_evc_debug_data全局变量(EVC_DEBUG_DATA_T)记录系统 RTC 与两个时间段的分钟刻度,供调试界面(evc.c:529-533)
s_t_sys_datastatic(EVC_SYS_DATA_T)系统侧输入快照,每个 10s 控制周期刷新一次(evc.c:33)
s_t_evc_control_parastatic(EVC_CONTROL_PARA_T)功率计算中间量:A/B/C 相与总剩余可充功率(evc.c:34)
s_evc_rtc_datetimestatic(struct RTC_DateTime)从 SYSTEM_DATETIME 拷入的 RTC 副本(evc.c:35)
SYSTEM_DATETIMEextern(struct RTC_DateTime)系统全局时间,用于充电时间段的分钟刻度换算(evc.c:37)
DEBUG_EVC宏(evc.h:12)调试打印总开关,为 0 时编译期剔除全部 printf
EVC_BUF_LEN宏(evc.h:14)256,收发缓存长度上限
EVC_SLOW / EVC_NORMAL / EVC_QUICK / EVC_SPECIFIED_POWER枚举(evc.h:34)switch(g_t_evc_config_table.u8_plot) 的四个分支(evc.c:701/721/761/773)
EMS_START / CARD_START枚举(evc.h:20)evc_state_u.BIT.startmode 的两种启动来源(evc.c:1070/1074)
CHARGE_NORMAL / CONDITION_CHARGE / NO_CONDITION_CHARGE枚举(evc.h:50)条件充电延迟状态机取值(evc.c:906/915/921/933)
EVC_NULL_MODEL / EVC_EMS_START_MODEL / EVC_CARD_START_MODEL / EVC_AVAILABLE_MODEL枚举(evc.h:42)get_evc_chargemodel() 的四种输出
EVC_REMOTE_DENY 语义常量(一代未宏化)evc_set_u.BIT.remotcontrol:0=允许、1=禁止(evc.c:854/862)
TIME_FORCE_CHARGE_MODE、FORCE_BAT_FEEDIN_MODE、TIME_PEAK_SHAVING_MODE、TIME_ALLOW_DISCHG_MODE、CMD_/SYS_/BAT_/USER_FORCE_CHARGE_MODE、TIME_FORBID_DISCHG_MODE枚举(logic.h)logic_read_sequencecontrol_mode() 返回的调度模式,决定电池充放限值的裁剪(evc.c:651-683)
UPS_RESERVE_SOC_MAX / UPS_RESERVE_SOC_MIN宏(logic.h)UPS 预留 SOC 的使能门限判定(evc.c:653/667)

3. 函数清单

函数名作用域说明
evc_master_send_cmdstatic(evc.c:60)组 Modbus-RTU 帧(addr + fun + data + CRC16-Modbus 低字节在前)并经 uart3_send_data 发出
evc_master_recv_datastatic(evc.c:82)500ms 窗口内轮询接收,校验尾部 CRC16,成功回填 *len,失败回填 0
evc_gat_sys_datastatic(evc.c:145)抓取电网/电表/逆变器/电池数据到 s_t_sys_data,并刷新 RTC 副本
get_evc_id_infostatic(evc.c:205)读 0x0100 起 38 个寄存器:SN、启动功率、相数、软/硬件版本、最大功率
get_evc_run_infostatic(evc.c:261)读 0x9100 起 19 个寄存器:三相电压电流、总功率、电量、故障字、CP 电压、占空比、状态字
send_cmd_evcstatic(evc.c:352)写 0x0100 起 9 个寄存器:总/分相设定功率 + 控制字(evc_set_u)
set_evc_energystatic(evc.c:472)写 0x00A2 起 2 个寄存器为 0,清零充电桩电量
evc_charge_timestatic(evc.c:515)把 RTC 时刻与两个时间段的时分换算成分钟刻度,判定 u8_time1_flag/u8_time2_flag
evc_calculated_total_powerstatic(evc.c:619)按充电策略计算系统侧"剩余可充总功率",并裁剪电池充放限值
evc_calculate_single_station_powerstatic(evc.c:790)计算单桩总设定功率,内含启动功率预留与条件充电延时状态机
evc_control全局(evc.c:958)周期调度总入口:清电量、1s 读、10s 控制+下发、通讯丢失检测
get_evc_enable_flag全局(evc.c:1043)返回单桩使能;未使能时 memset 清空整张运行表
get_evc_chargemodel全局(evc.c:1060)依据 charge_en/startmode 折算上报云端的充电模式
get_evc_type全局(evc.c:1094)直接返回 FW_TYPE_EVC("SMILE-EVCT11")
get_evc_power_total全局(evc.c:1106)返回 s32_evc_power_total
get_evc_energy_total全局(evc.c:1118)返回 u32_evc_energy_total(可清零侧)
clear_evc_energy全局(evc.c:1130)置 clear_energy_flag,由 evc_control 异步执行清零
set_evc_charge_flag全局(evc.c:1142)直接写入 u8_charge_flag(云端/本地充停指令)

4. 核心逻辑解析

4.1 Modbus-RTU 帧格式与超时重试

三条命令都走同一个组帧函数 evc_master_send_cmd(u8 addr, u8 fun, u8 *buf, u8 len, u16 timeout)(evc.c:60):

+--------+--------+------------------+---------------+---------------+
| addr   | fun    | data[len]        | CRC16 低字节  | CRC16 高字节  |
| 1B=0x01| 1B     | len 字节          |               |               |
+--------+--------+------------------+---------------+---------------+

响应接收 evc_master_recv_data(u8 *buf, u16 *len)(evc.c:82)的机制:

  1. 记录起始 OSTimeGet()(evc.c:90),超时窗口硬编码为 500 ms(evc.c:94),超时即 *len = 0 返回。
  2. 处理 tick 回绕:若 OSTimeGet() < l_u32_recv_tick,重置基准(evc.c:99-102)。
  3. uart3_is_recv_async_data() 为真时,取 uart3_get_data_len(),上限截到 EVC_BUF_LEN(evc.c:107-108),长度小于 2 直接 continue。
  4. 逐字节 uart3_read_data_async() 拷入 buf(evc.c:115-119)。
  5. 校验:crc_temp = buf[len-1]<<8 | buf[len-2],与 GetCrcCode_Modbus(buf, len-2) 比对,相等则 *len = l_u16_len 返回,否则 *len = 0 并继续循环直到超时(evc.c:121-129)。

注意:本文件没有应用层重试计数,重试由调用方的时间节拍隐式完成——evc_control 每 1s 读一次、每 10s 控一次,通讯丢包等价于"下一拍再来"。唯一的显式重发是清电量循环(evc.c:968-973,最多 3 次)。

各命令的报文与响应判据:

命令功能码起始寄存器寄存器数data 长度超时响应判据
get_evc_id_info0x030x01000x0026(38)4500msbuf[0]==1 && buf[1]==0x03 && buf[2]==0x26*2(76)(evc.c:218-221)
get_evc_run_info0x030x91000x0013(19)4500msbuf[2]==0x13*2(38)(evc.c:273-276)
send_cmd_evc0x100x01000x0009(9)5+18500ms回显 addr/fun/起址高/起址低/寄存器数高/低 六字节(evc.c:448-454)
set_evc_energy0x100x00A20x0002(2)5+4500ms同上(evc.c:491-497)

4.2 寄存器映射

身份信息(0x0100 起 38 寄存器,响应 76 字节,evc.c:223-231)

响应偏移长度含义
[3..34]32Bu8_evc_sn 桩序列号
[51..52]2Bu32_start_power_total 启动功率(单相,主机字节序)
[53..54]2Bu8_evc_phase 相位数
[55..64]10Bu8_evc_fw_ver 软件版本
[65..74]10Bu8_evc_hw_ver 硬件版本
[75..78]4Bu32_max_power_total 最大功率(大端 32 位)

型号 u8_evc_modle 不由桩上报,而是本地写死 FW_TYPE_EVC(evc.c:224-225)。随后按相数折算出 u32_start_power_single_phase 与 u32_max_power_single_phase(evc.c:233-234),并置 comm_flag=TRUE、刷新 u32_evc_comm_tick、清 Set_Setup_Config_Extend1_Status(FALSE)(表示扩展配置已读完)。

运行信息(0x9100 起 19 寄存器,响应 38 字节,evc.c:278-304)

响应偏移长度目标字段说明
[3..4]2Bu16_evc_volt_l1A 相电压
[5..6]2Bs16_evc_curr_l1A 相电流(有符号)
[7..10]4Bs32_evc_power_total总功率
[11..14]4Bu32_evc_energy_total_real桩侧原始累计电量
[15..16]2Bu16_evc_volt_l2B 相电压
[17..18]2Bs16_evc_curr_l2B 相电流
[19..20]2Bu16_evc_volt_l3C 相电压
[21..22]2Bs16_evc_curr_l3C 相电流
[23..26]4Bevc_fault_u.u32_evc_fault_all故障字,**按 `[25]<<24\[26]<<16\[23]<<8\[24]` 拼装**
[31..32]2Bu16_evc_cp_voltCP 电压
[33..34]2Bu16_evc_dutyCP 占空比
[35..36]2Bevc_state_u.u16_all状态字(startmode/chargingfull/chgsts/charge_en)
[37..40]4Bu32_evc_energy_total可被清空的累计电量

控制下发(0x0100 起 9 寄存器,evc.c:358-428)

data 下标内容
[0..3]起址 0x0100 + 寄存器数 0x0009
[4]字节数 = 18
[5..8]s32_evc_set_power_total(大端 4B)
[9..12] / [13..16] / [17..20]s32_evc_set_power_a/b/c(大端 4B)
[21..22]evc_set_u.u16_all(remotcontrol + phasecontrol)

下发前先做两重裁剪(evc.c:364-405):负值全部截为 0;总值上限 = 单相最大功率 × 相数,分相值上限 = 单相最大功率。

4.3 主调度时序(evc_control,evc.c:958)

由 interface.c:351 每 100ms 调用一次(之后 OSTimeDlyHMSM(0,0,0,100)),内部三档节拍:

每 100ms 进入 evc_control
├─ clear_energy_flag == TRUE           → 置 0,set_evc_energy() 最多重试 3 次
├─ (now - s_u32_recv_tick) >= 1000ms   → 1s 档
│    ├─ comm_flag == FALSE → get_evc_id_info()   (先读身份)
│    └─ comm_flag == TRUE  → get_evc_run_info()  (再读运行)
├─ (now - s_u32_send_tick) >= 10000ms  → 10s 档(控制周期)
│    ├─ get_evc_run_info()
│    ├─ evc_gat_sys_data()
│    ├─ evc_charge_time()
│    ├─ evc_calculated_total_power()
│    ├─ evc_calculate_single_station_power()
│    ├─ send_cmd_evc()
│    └─ 刷新 evc_tags_u(server_control / rechargeable / full_tag)
└─ 通讯丢失判定
     ├─ (now - u32_evc_comm_tick) >= 10000ms → b_comm_failure = TRUE
     │    且首次进入时清空桩侧易失数据(见 4.6)
     └─ else                                 → b_comm_failure = FALSE

注意 10s 档里 get_evc_run_info() 被重复调用一次(evc.c:1001),使功率计算用的是最新数据而非 1s 档的旧值,代价是每个控制周期多一次 500ms 阻塞等待。

三个 static u32 计时基准 s_u32_recv_tick/s_u32_send_tick(evc.c:962-963)以及 g_t_evc_run_info.u32_evc_comm_tick 都做了 tick 回绕保护(evc.c:991/1011/754)。

4.4 策略与功率计算

(1)系统侧剩余可充功率 evc_calculated_total_power(evc.c:619)

单相剩余可充功率(evc.c:630-632):

P_phaseX = V_meterX * u16_max_consume_cur * 8 / 1000 + P_meterX

u16_max_consume_cur 单位 0.1A(默认 320 → 32A,system_config.c:785),P_meterX 为电表侧功率取负后的值(evc.c:153-155 用电表数据时取负号,即"负载为正")。三相均有效时取三相最小值 l_s32_min_power 作为策略 4 的输入;只有 A 相有效时降级为单相。

电池限值裁剪(evc.c:651-693):

逆变器最大可放功率(evc.c:696):

P_inv_max = min(|P_pv| + P_bat_dischg_limit, P_inv_rated)

四套策略(switch (g_t_evc_config_table.u8_plot),evc.c:699):

策略离网(grid_status == FALSE)并网
EVC_SLOW(1)P = P_meter1_total(等于馈网功率)P = P_meter1 - (92% * P_bat_charge_limit + P_bat),仅当 92%*P_bat_charge_limit + P_bat > 0(电池未到最大可充)时扣减,否则 P = P_meter1
EVC_NORMAL(2)P = P_meter1P = P_meter1 + P_inv_max - P_inv;若为负且"逆变器已接近满放"(92%*P_inv_max > P_inv)且距上次上调 < 2 min,则钳为 0;否则刷新上调时刻
EVC_QUICK(3)P = P_meter2(PV 电表) - get_evc_power_total()P = P_meter2 + P_inv_max - get_evc_power_total()
EVC_SPECIFIED_POWER(4)—P = l_s32_min_power * 3
其它P = 0P = 0

EVC_NORMAL 的 2 分钟"不下调"窗口由 static u32 s_u32_power_regulation_tick(evc.c:623)实现,语义是"逆变器已经最大出力时,给充电桩 2 分钟缓冲,不做激进降额"。

(2)单桩功率 evc_calculate_single_station_power(evc.c:790)

  1. 最大功率模式(策略 4)先把总额度按相数折算:P = P_total * u8_ev_phase / 3(evc.c:802)。
  2. 相数自适应:u8_ev_phase == 0 时置 3(evc.c:809-812);只有 A 相电压 >1000(100.0V)时强制降为 1 相(evc.c:820-826);u16_max_charg_curr == 0 时置默认 160(16A,evc.c:832-835)。
  3. 计算"实际启动功率"(evc.c:839):
P_start = u32_start_power_single_phase * phasecontrol * V_meter_a / 2300

2300 即额定 230.0V(0.1V 单位),用于按实际电压修正启动门槛。

  1. 允许/禁止判定(evc.c:847-863):仅当 charge_en == TRUE 且(本地充电指令非默认 或 刷卡启动 或 任一时间段命中)时把 remotcontrol 置 0(允许);若电表丢失则保持 0 功率输出;若 u8_charge_flag == STOP_CHARGE 则强制禁止。
  2. 正常充电时的目标功率(evc.c:866-886):
P_a = V_meterA * I_l1 / 100 + P_avail_a        (分相,同理 b/c)
P_set = max(P_actual, P_start) + P_avail_total  (P_actual < 150 时不抬高)
充满时改为 P_set = P_start + 200
  1. 限流(evc.c:889-897,仅策略 4):先取 14a/ENWG 动态限值 get_enwg_evc_power_limit(),再按 V * I_max * phasecontrol / 100 限制,最后 += phasecontrol * 50 补偿。
  2. 条件充电延迟状态机(evc.c:900-936):
当前状态条件动作
任意P_set + 500 < P_start刷新 s_u32_charge_dealy_tick,状态 = NO_CONDITION_CHARGE
CHARGE_NORMAL 或 (CONDITION_CHARGE 且耗时 < 3 min)P_start - 500 <= P_set < P_startP_set += 500,状态 = CONDITION_CHARGE
CONDITION_CHARGE 且耗时 ≥ 3 min同上刷新 tick,状态 = NO_CONDITION_CHARGE
P_set >= P_start—刷新 tick,状态 = CHARGE_NORMAL

即:功率不足启动门槛时最多"勉强多给 500W"并给 3 分钟宽限,超时后判定为不满足充电条件。

4.5 充电时间段判定(evc_charge_time,evc.c:515)

把 RTC 与时间段起止都换算成"当日分钟数"(hour*60+minute),对每段时间输出三态:

跨天段(start > end,如 22:00–06:00)采用反向判定:落在"段外区间"即认为在段内(evc.c:564-572,注释写"跨天在时间段内无效",与实现语义相反,属注释与代码不一致)。

4.6 通讯丢失处理与"清空字段"技巧

evc.c:1016-1033:若 u32_evc_comm_tick 超过 10s 未刷新:

  1. 首次进入时保存 u8_charge_flag 与 charge_en(这两项是 EMS 侧远程写入的,不能被桩掉线抹掉);
  2. 用一条 memset 把 u8_evc_phase+1 到 u32_evc_comm_tick 之前的整段运行数据清零(evc.c:1023)——利用结构体成员连续布局,一次性清掉电压/电流/功率/电量/故障/时间段标志;
  3. 写回保存的两个字段;
  4. 置 evc_fault_u.bit.b_comm_failure = TRUE。

b_comm_failure 由 fault_warn_log.c:1129 按位读出,生成故障记录。

4.7 全局变量的协同

5. 对外接口

本文件导出的函数(供谁调用)

导出函数调用方
evc_controlmidware/interface/interface.c:351
get_evc_enable_flaginterface.c:331、data/resume_data/flash/flash_data_store.c:673、logic/logic.c:164、net/ems.c:540
get_evc_power_totalflash_data_store.c:673、logic.c:165、net/ems.c:540、本文件 evc_calculated_total_power
get_evc_energy_totalflash_data_store.c:1037、midware/interface/modbus/modbus.c:933/944、net/ems.c:760
get_evc_chargemodelmodbus.c:956、net/ems.c:1010
get_evc_typenet/ems.c:3015/3096、net/server.c:3305/3709/3710
clear_evc_energynet/server.c:1222
set_evc_charge_flagnet/server.c:1772

本文件导出的全局变量

g_evc_send_buf、g_evc_recv_buf(被 evc_ii.c/evc_upgrade.c 复用)、g_t_evc_setting_info、g_t_evc_config_table、g_t_evc_run_info、g_t_evc_debug_data(声明见 evc.h:350-358)。

本文件调用的外部函数/变量

来源模块符号
hardware/usart3uart3_clear_buffer、uart3_send_data、uart3_is_recv_async_data、uart3_get_data_len、uart3_read_data_async
common/crcGetCrcCode_Modbus
logic/logic.clogic_read_sequencecontrol_mode、logic_read_charger_cut_soc、logic_read_ups_reserve_soc、logic_read_feedin_cut_soc、logic_read_allow_discharge_cut_soc、logic_read_peakshving_discharge_cut_soc、get_enwg_evc_power_limit、g_t_logic_info、各 *_MODE 枚举
midware/metermeter_read_voltage、meter_read_actpower、GRID_METER、PV_METER、PHASE_A/B/C/T
net/ems.cSet_Setup_Config_Extend1_Status
data/system_configSYSTEM_DATETIME
uCOS-IIOSTimeGet
C 库memcpy、memset、printf、abs

6. 依赖关系

7. 备注与风险点

  1. 疑似逻辑缺陷(削峰截止 SOC 判据写错):evc.c:665-666 写作

(sys_logic == TIME_PEAK_SHAVING_MODE) && (u8_peakshaving_discharg_cut_soc <= u8_bat_feedin_cut_soc), 比较的是两个配置阈值而非"当前 SOC 与阈值"。对照二代同位置实现 evc_ii.c:957-958: (u8_bat_soc <= u8_peakshaving_discharg_cut_soc)。一代此处很可能漏写了 u8_bat_soc,会导致削峰模式下放电限值清零条件几乎从不按预期触发(或被错误触发)。

  1. 除零风险:evc.c:233-234 直接 u32_start_power_total / u8_evc_phase,当桩上报相数为 0 时触发整数除零(Cortex-M4 上 SDIV 得到 0 而非异常,但结果错误)。后续 evc.c:809 的"相数为 0 置 3"保护在这之后才执行,来不及补救。evc_calculate_single_station_power 的 phasecontrol 若为 0,evc.c:894 的乘法虽安全,但 evc.c:839 会把启动功率也算成 0。
  2. 魔法数字 *8/1000:evc.c:630-632 的 V * I * 8 / 1000。若 V 单位 0.1V、I 单位 0.1A,物理功率应为 V*I/100,代码相当于打了 0.8 折(约 80% 降额)。同文件 EVC_SLOW/EVC_NORMAL 又统一用 92/100,两处降额系数不一致,建议确认是否有意为之。
  3. 配置表被就地改写:evc.c:811、evc.c:824、evc.c:834 修改 g_t_evc_setting_info(Flash 映射表),evc.c:822 还会按电压情况强制把用户设置的 3 相改为 1 相且不会恢复。若该表在别处被回写 Flash,用户的相数设置会被 EMS 覆盖。
  4. u8 形参承载长度:evc_master_send_cmd 的 len 为 u8(evc.c:60),而调用点 evc.c:445 传 l_u8_cmd[4]+5(整数提升后截断),当前最大值 23 安全;但若将来 data 域超过 255 字节会静默回绕。
  5. printf 已屏蔽但存在真实笔误:evc.c:316 的 printf("%02X ", g_evc_recv_buf) 漏了数组下标 [i]。因 DEBUG_EVC == 0 编译期剔除,不影响发布固件,但一旦打开调试开关会打印错误内容。
  6. 清空运行数据依赖结构体布局(evc.c:1023):memset(&u8_evc_phase+1, 0, (u8*)&u32_evc_comm_tick - &u8_evc_phase - 1) 依赖 u8_evc_phase 与 u32_evc_comm_tick 在 EVC_RUN_INFO_T 中按声明顺序连续排布。若有人调整 evc.h 的成员顺序,该 memset 会破坏无关字段且不会编译报错。
  7. get_evc_chargemodel 有隐式副作用:evc.c:1062 内部调用 get_evc_enable_flag(),后者在未使能时 memset 整张 g_t_evc_run_info(evc.c:1047)。即"读一个上报值"会清空整张运行表,调用频次高时(net/ems.c:1010 每帧上报)会造成数据抖动。
  8. 10s 控制周期里重复读运行数据(evc.c:1001)导致每个控制周期最多两次 500ms 阻塞等待,interface.c 的 100ms 节拍被拉长;若充电桩无响应,单次 evc_control 最坏耗时约 1.0s,可能影响同任务里其它 485 设备(SUNSPEC、并机)的响应。
  9. 通讯丢失清空为破坏性操作:evc.c:1023 清零后 u32_evc_energy_total 归 0,get_evc_energy_total() 会把 0 上报云端与断电续传存储(flash_data_store.c:1037),存在云端统计被"清零"的观感风险;energy_total_real 未被清,可作为对照。
  10. u8_timeX_flag 的取值语义用裸数字 0/1/2 贯穿全文件(evc.c:546、evc.c:553-570、evc.c:849-852),无宏定义,可读性差且易与 EVC_CHARGE_MODE_E 混淆。
  11. 注释与实现不一致:evc.c:562、evc.c:594 注释为"跨天在时间段内无效",但代码实际把跨天段的"段外区间"判定为段内(evc.c:564-572);evc.c:919 注释写"五分钟到"而条件用的是 3*60*1000(3 分钟)。