| @@ -97,8 +97,8 @@ int main(void) | |||
| OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP); | |||
| /* | |||
| * 参数块任务:Pend 信号量 → ApplyFromHold → PersistPoll。 | |||
| * 分帧写完后由 OnHoldWrite Post,尽快落盘,不堵在 PlsrTask 里。 | |||
| * 参数块任务:Pend → ApplyFromHold → SaveParamsFromHold → ExportToHold。 | |||
| * 分帧写完后由 OnHoldWrite Post;Save 落 BKP,Export 仅供读回钳位结果。 | |||
| */ | |||
| OSTaskCreateExt(PlsrParamBlockTask, | |||
| NULL, | |||
| @@ -67,7 +67,13 @@ void ModbusSlaveTask(void *pArg) | |||
| (void)pArg; | |||
| /* | |||
| * ModbusDataInit 会 memset 整个 g_hold_reg,冲掉 PlsrInit 里 PersistLoad/Export 的结果。 | |||
| * 须立刻 Export:用已 Apply 的 s_cfg/s_seg 填回公共+段参数,供 FC03 读与后续 START。 | |||
| * (监控区另由 PlsrPersistTickMonitor 每节拍从运行态回填。) | |||
| */ | |||
| ModbusDataInit(); | |||
| PlsrParamBlockExportToHold(); | |||
| ModbusPortInit(); | |||
| while (1) | |||
| @@ -64,7 +64,6 @@ void PlsrCommandSetFault(uint16_t code) | |||
| { | |||
| s_fault = code; | |||
| WriteHoldReg(PLSR_MON_ERR, code); | |||
| PlsrPersistNotifyMonitorChanged(); | |||
| } | |||
| /** @brief 清故障(见 plsr_command.h) */ | |||
| @@ -72,7 +71,6 @@ void PlsrCommandClearFault(void) | |||
| { | |||
| s_fault = PLSR_ERR_NONE; | |||
| WriteHoldReg(PLSR_MON_ERR, PLSR_ERR_NONE); | |||
| PlsrPersistNotifyMonitorChanged(); | |||
| } | |||
| /** @brief 读故障镜像(见 plsr_command.h) */ | |||
| @@ -147,7 +145,8 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity) | |||
| if (seg != (PlsrSeg_t *)0) | |||
| { | |||
| seg->freq_hz = (int32_t)f; | |||
| PlsrPersistNotifyCommonChanged(); /* 动态改频:段表 dirty,Poll 写入 BKPSRAM */ | |||
| /* 运行中改频:立即只把该段频率双字写入 BKP,不等整包参数落盘 */ | |||
| PlsrPersistSaveSegFreqToBkp(seg0, f); | |||
| } | |||
| s_live_freq_hz = f; | |||
| @@ -15,7 +15,8 @@ | |||
| * | |||
| * 与其它模块关系 | |||
| * Modbus FC10 应答路径调用 OnHoldWrite;Command START 也会同步 ApplyFromHold; | |||
| * Persist 仅保存公共参数;段表每次由上位机全量下发。 | |||
| * Persist:Apply 成功后 SaveParamsFromHold 整包落 BKP;运行中改频单独落频率双字; | |||
| * ExportToHold 只把钳位后的结构体摊回 hold(读回 / 抗 ModbusDataInit 清零),不负责写 BKP。 | |||
| */ | |||
| #include "plsr_param.h" | |||
| #include "plsr_persist.h" | |||
| @@ -283,13 +284,19 @@ uint8_t PlsrParamBlockApplyFromHold(void) | |||
| seg->jump_seg = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP)); | |||
| } | |||
| PlsrPersistNotifyCommonChanged(); | |||
| return 1U; | |||
| } | |||
| /** | |||
| * @brief 运行映像 → 全部相关保持寄存器(含未使用段槽位) | |||
| * | |||
| * @details 用途(与落 BKP 无关) | |||
| * 1. Apply 钳位后摊回 hold,使「读 PLC」与运行结构体一致; | |||
| * 2. ModbusDataInit() memset 清 hold 后,把已 Apply 的 s_cfg/s_seg 填回, | |||
| * 否则上位机读公共/段参数全 0,START 也会用空 hold 再次 Apply 冲掉结构体。 | |||
| * | |||
| * @note 0x100F 保留字写 0;段表写满 PLSR_SEG_MAX 槽,避免读回脏数据 | |||
| * @note 落 BKP 请用 PlsrPersistSaveParamsFromHold(读 hold 原值),不依赖本函数 | |||
| */ | |||
| void PlsrParamBlockExportToHold(void) | |||
| { | |||
| @@ -406,8 +413,8 @@ void PlsrParamBlockInit(void) | |||
| * @brief 参数块任务(见 plsr_param.h) | |||
| * | |||
| * for(;;) 为 uC/OS 任务标准死循环: | |||
| * OSSemPend 永久等待 → ApplyFromHold → 写 XFER_OK 并尽快 PersistPoll | |||
| * (不等 PlsrTask,缩短参数落盘延迟)。 | |||
| * OSSemPend → ApplyFromHold → SaveParamsFromHold → ExportToHold | |||
| * Save 用 hold 中上位机刚写入的值落 BKP;Export 仅把钳位结果摊回 hold 供读回。 | |||
| * Apply 失败则写 XFER_FAIL 与当前 recv 帧号。 | |||
| */ | |||
| void PlsrParamBlockTask(void *pArg) | |||
| @@ -427,7 +434,8 @@ void PlsrParamBlockTask(void *pArg) | |||
| if (PlsrParamBlockApplyFromHold() != 0U) | |||
| { | |||
| PlsrParamSetXferStatus(PLSR_PARAM_XFER_OK, 0U); | |||
| PlsrPersistPoll(); /* 分帧收齐后尽快落盘,不等 PlsrTask */ | |||
| PlsrPersistSaveParamsFromHold(); /* hold 原值 → BKP(不依赖 Export) */ | |||
| PlsrParamBlockExportToHold(); /* 钳位后映像 → hold,供 Modbus 读回 */ | |||
| } | |||
| else | |||
| { | |||
| @@ -12,14 +12,15 @@ | |||
| * - modbus_rtu / modbus_data :ReadHoldReg / WriteHoldReg | |||
| * - plsr_command :启动前 ApplyFromHold;运行中写频改 s_seg[].freq_hz | |||
| * - plsr_run_control :GetCfg / GetSeg / GetSegCount / GetStartSeg | |||
| * - plsr_persist :Apply 成功后 NotifyCommonChanged,落盘公共+段表+监控 | |||
| * - PlsrParamBlockTask :独立 uC/OS 任务,等信号量后 Apply + PersistPoll | |||
| * - plsr_persist :Apply 成功后 SaveParamsFromHold;动态改频 SaveSegFreqToBkp | |||
| * - PlsrParamBlockTask :独立 uC/OS 任务,等信号量后 Apply + 整包落 BKP | |||
| * | |||
| * 关键数据流 | |||
| * 上位机写公共帧@0x1000 → OnHoldWrite 开传输 expect=1+N | |||
| * 上位机写段帧@0x1100+ → recv++;收齐 → OSSemPost | |||
| * ParamBlockTask → ApplyFromHold → 结构体更新 → PersistNotify → 状态 OK | |||
| * 上电:InitDefault → PersistLoad 覆盖公共+段表 → ExportToHold | |||
| * ParamBlockTask → ApplyFromHold → SaveParamsFromHold → ExportToHold → 状态 OK | |||
| * 上电:PersistLoad → ApplyFromHold → … ModbusDataInit 清 hold … | |||
| * → ExportToHold(填回参数)+ TickMonitor(填回监控) | |||
| * | |||
| * 协议概要 | |||
| * - 公共帧:0x1000~0x1013(20 字),0x1009=段数 N,预期总帧=1+N | |||
| @@ -194,7 +195,7 @@ uint16_t PlsrParamGetStartSeg(void); | |||
| void PlsrParamBlockInit(void); | |||
| /** | |||
| * @brief 参数块任务:阻塞等信号量 → ApplyFromHold → 状态 OK/FAIL → PersistPoll | |||
| * @brief 参数块任务:阻塞等信号量 → ApplyFromHold → SaveParamsFromHold → ExportToHold | |||
| * @param pArg 未使用 | |||
| * @note for(;;) 死循环为 RTOS 任务常态;空循环体是错觉(花括号内有 Pend/Apply) | |||
| */ | |||
| @@ -211,13 +212,17 @@ void PlsrParamBlockOnHoldWrite(uint16_t start_addr, uint16_t quantity); | |||
| /** | |||
| * @brief 保持寄存器 → s_cfg / s_seg | |||
| * @return 1=成功(当前恒为 1;完整校验/故障码待扩展) | |||
| * @note 副作用:NotifyCommonChanged 标记 BKPSRAM 待存 | |||
| * @note 成功后由 ParamBlockTask 调用 SaveParamsFromHold 整包落 BKP | |||
| */ | |||
| uint8_t PlsrParamBlockApplyFromHold(void); | |||
| /** | |||
| * @brief s_cfg / s_seg → 保持寄存器(供 0x03 读回) | |||
| * @note 调用时机:上电 Export、PlsrTask 首次延迟后再次 Export | |||
| * @brief s_cfg / s_seg → 保持寄存器(供 FC03 读回 / START 前 hold 有效) | |||
| * @note 调用时机: | |||
| * - ParamBlockTask:Apply+Save 之后,把钳位结果摊回 hold | |||
| * - ModbusDataInit 清 hold 之后立刻 Export | |||
| * - PlsrTask 首次延时后再 Export(双保险) | |||
| * @note 本函数不写 BKP;落盘用 SaveParamsFromHold | |||
| */ | |||
| void PlsrParamBlockExportToHold(void); | |||
| @@ -10,10 +10,11 @@ | |||
| * 本文件仅依赖 plsr.h 及各子模块头文件,不被其它 plsr 模块反向引用。 | |||
| * | |||
| * 关键数据流 | |||
| * PlsrInit 顺序:Param 默认 → PersistLoad(BKP→hold) → ApplyFromHold → | |||
| * PlsrInit 顺序:PersistLoad(BKP→hold) → ApplyFromHold → | |||
| * PulseDriver → RunControl → RestoreRuntime → ExportToHold → | |||
| * CommandInit → RestoreMonitor → PersistPoll | |||
| * PlsrTask 循环:TickMs → DebouncePoll → CommandPoll → PersistPoll → WakePend | |||
| * CommandInit → RestoreMonitor → TickMonitor | |||
| * (随后 ModbusDataInit 可能清 hold,须再 Export + TickMonitor) | |||
| * PlsrTask 循环:TickMs → DebouncePoll → CommandPoll → TickMonitor → WakePend | |||
| */ | |||
| #include "plsr.h" | |||
| #include "plsr_pulse_driver.h" | |||
| @@ -26,20 +27,25 @@ | |||
| /** | |||
| * @brief 子系统初始化(见 plsr.h) | |||
| * | |||
| * 顺序要点 | |||
| * PersistLoad → Apply:BKP 进结构体; | |||
| * Export:先填 hold(随后 ModbusDataInit 仍可能清零,故任务里再 Export); | |||
| * RestoreRuntime / TickMonitor:累计脉冲进运行态并与 BKP 对齐。 | |||
| */ | |||
| void PlsrInit(void) | |||
| { | |||
| //PlsrParamInitDefault(); | |||
| PlsrPersistLoad(); /* BKPSRAM 稀疏映像 → g_hold_reg */ | |||
| (void)PlsrParamBlockApplyFromHold(); | |||
| (void)PlsrParamBlockApplyFromHold(); /* hold → s_cfg / s_seg[] */ | |||
| PlsrPulseDriverInit(); | |||
| PlsrSignalIoInit(); | |||
| PlsrRunControlInit(); | |||
| PlsrPersistRestoreRuntime(); /* 0x2000 累计 → run_control */ | |||
| PlsrParamBlockExportToHold(); /* 运行映像与 hold 对齐,供 Modbus 读 */ | |||
| PlsrPersistRestoreRuntime(); /* hold 0x2000 累计 → run_control(须在 DataInit 清 hold 前) */ | |||
| PlsrParamBlockExportToHold(); /* 结构体 → hold;Modbus 清零后须再 Export */ | |||
| PlsrCommandInit(); | |||
| PlsrPersistRestoreMonitor(); /* 恢复故障码;0x3000/运行态强制空闲 */ | |||
| PlsrPersistPoll(); /* 消费 Restore 置的 dirty */ | |||
| PlsrPersistTickMonitor(); /* 监控区 hold+BKP 与运行态对齐 */ | |||
| } | |||
| /** | |||
| @@ -110,22 +116,25 @@ void PlsrTask(void *pArg) | |||
| while(1) | |||
| { | |||
| /* | |||
| * 首次进入:Modbus 从站上电常会清零保持寄存器。 | |||
| * 延迟 ~300ms 后再 Export + CommandInit,避免默认映像被冲掉。 | |||
| * 首次进入:ModbusSlaveTask 启动时 ModbusDataInit 会 memset(g_hold_reg)。 | |||
| * 延迟让出 CPU 后再次 Export:把已从 BKP Apply 的运行映像摊回 hold, | |||
| * 否则读 PLC 公共/段为 0,START 的 ApplyFromHold 也会用空 hold 覆盖结构体。 | |||
| * TickMonitor:清 hold 后立刻把累计等监控量刷回 hold+BKP。 | |||
| */ | |||
| if (s_booted == 0U) | |||
| { | |||
| OSTimeDly(30U); /* ~300ms @ 100Hz tick */ | |||
| PlsrParamBlockExportToHold(); | |||
| OSTimeDly(3U); /* ~30ms @ 100Hz tick;让出 CPU 给 Modbus 完成 DataInit */ | |||
| PlsrParamBlockExportToHold(); /* 参数区 hold ← s_cfg/s_seg */ | |||
| PlsrCommandInit(); | |||
| PlsrPersistRestoreMonitor(); /* 若仍有 pending;无则空操作 */ | |||
| PlsrPersistRestoreMonitor(); | |||
| PlsrPersistTickMonitor(); /* 监控区 hold+BKP ← 运行态 */ | |||
| s_booted = 1U; | |||
| } | |||
| PlsrRunControlTickMs(); /* 优先:WAIT/换向到期立刻开表 */ | |||
| PlsrSignalIoDebouncePoll(); /* OS 节拍消抖确认 */ | |||
| PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 */ | |||
| PlsrPersistPoll(); /* BKPSRAM:消费 dirty(累计脉冲限频落盘) */ | |||
| PlsrPersistTickMonitor(); /* 监控区:运行态→hold→BKP(每 OS 节拍) */ | |||
| /* | |||
| * 换向 / WAIT 时间:WakePend(0) 只等 TIM5 Post(墙钟≈设定 ms)。 | |||
| @@ -9,19 +9,20 @@ | |||
| * | |||
| * 与其它模块关系 | |||
| * - plsr_param :运行参数映像(公共 + 段表),Modbus 保持寄存器 ↔ 结构体 | |||
| * - plsr_persist :公共参数 Flash 掉电保存(不含段表) | |||
| * - plsr_persist :BKPSRAM 掉电保存(公共+段表、动态频率、监控区) | |||
| * - plsr_command :Modbus 监控区 0x2000~0x2006、控制区 0x3000 指令解析 | |||
| * - plsr_run_control:段状态机、等待策略、加减速执行、故障诊断 | |||
| * - plsr_pulse_driver:TIM PWM 脉冲 + Y3 方向 GPIO | |||
| * - plsr_signal_io :WAIT/EXT 外部输入、TIM5 延时 | |||
| * | |||
| * 关键数据流 | |||
| * 上电:PlsrInit → 默认参数 → Flash 覆盖公共参数 → 驱动/IO/运行控制初始化 | |||
| * → 参数导出到保持寄存器 → 指令模块初始化 | |||
| * 周期:PlsrTask → CommandPoll → PersistPoll → RunControlTickMs | |||
| * → WakePend(1)(TIM5 WAIT/ACT 到期 SemPost 可立刻唤醒) | |||
| * 上电:PlsrInit → PersistLoad(BKP→hold) → ApplyFromHold → 驱动/IO/RunControl | |||
| * → RestoreRuntime → ExportToHold → CommandInit → RestoreMonitor → TickMonitor | |||
| * →(ModbusDataInit 清 hold 后再次 Export + TickMonitor) | |||
| * 周期:PlsrTask → TickMs → Debounce → CommandPoll → TickMonitor → WakePend | |||
| * 脉冲:TIM UPDATE 中断 → PlsrOnPulseIsr → RunControl 计数 + 逐拍改频 | |||
| * 启动:PlsrStart → RunControlStart → 段序/方向 + 曲线规划 + PWM 输出 | |||
| * 写参:分帧收齐 → ParamBlockTask Apply → SaveParamsFromHold → ExportToHold | |||
| */ | |||
| #ifndef PLSR_H | |||
| #define PLSR_H | |||
| @@ -54,7 +54,6 @@ | |||
| #include "plsr_pulse_driver.h" | |||
| #include "plsr_command.h" | |||
| #include "plsr_signal_io.h" | |||
| #include "plsr_persist.h" | |||
| #include "ucos_ii.h" | |||
| #include <stdint.h> | |||
| @@ -1225,7 +1224,6 @@ static void PlsrRunControlFinishAll(void) | |||
| s_wait_expire_req = 0U; | |||
| s_act_time_ms = 0U; | |||
| s_last_period_wait = 0U; | |||
| PlsrPersistNotifyMonitorChanged(); /* 全部结束:落盘累计与空闲状态 */ | |||
| } | |||
| /** | |||
| @@ -1555,7 +1553,6 @@ void PlsrRunControlStop(void) | |||
| s_wait_expire_req = 0U;/*段后等待到期请求标志*/ | |||
| s_act_time_ms = 0U;/*本段 ACT 定时时长*/ | |||
| s_last_period_wait = 0U; | |||
| PlsrPersistNotifyMonitorChanged(); /* 停机:立刻落盘累计/状态 */ | |||
| } | |||
| /** @brief 运行中改频(见 plsr_run_control.h) */ | |||
| @@ -1735,7 +1732,6 @@ void PlsrRunControlOnPulseIsr(void) | |||
| { | |||
| s_acc_pulse--; | |||
| } | |||
| PlsrPersistNotifyAccPulseDirty(); | |||
| /* | |||
| * ACT 到期切段只在脉冲边界执行,避免半个 PWM 周期改段。 | |||
| @@ -1858,7 +1854,6 @@ void PlsrRunControlClearAccPulse(void) | |||
| s_acc_pulse = 0; | |||
| s_abs_origin = 0; | |||
| s_abs_origin_locked = 0U; /* 下次 Start 重新锁定原点 */ | |||
| PlsrPersistNotifyMonitorChanged(); | |||
| } | |||
| /** @brief 上电恢复累计(见 plsr_run_control.h) */ | |||