diff --git a/plsr/run_control/plsr_run_control.c b/plsr/run_control/plsr_run_control.c index 2d8fa28..8b533ab 100644 --- a/plsr/run_control/plsr_run_control.c +++ b/plsr/run_control/plsr_run_control.c @@ -42,7 +42,7 @@ volatile uint8_t g_plsr_busy; volatile uint16_t g_plsr_current_segment_index; volatile int32_t g_plsr_accumulated_pulses; static volatile RcState_e s_state; -static volatile uint8_t s_forward; +static volatile uint8_t s_forward;/*当前端脉冲方向*/ static volatile int32_t s_segment_pulses_done; static volatile int32_t s_segment_pulse_target; static int32_t s_absolute_origin; @@ -182,7 +182,7 @@ static void PlsrRunControlClearChainAndStop(void) } /** - * @brief 中途切段 handoff:同向且有有效频率则不停表衔接,否则停表清链 + * @brief 中途切段:同向且有有效频率则不停表衔接,否则停表清链 * @param allow_act_handoff 1=允许 s_keep_frequency_after_act(边界停表后仍衔接) */ static void PlsrRunControlApplyKeepOrStop(uint8_t allow_act_handoff) @@ -226,31 +226,25 @@ static void PlsrRunControlArmActExtOnPulseStart(void) { PlsrSignalIoClearEdges(); } + s_act_timer_armed = 0U; s_act_expired = 0U; s_act_waiting_for_pulse_boundary = 0U; s_keep_frequency_after_act = 0U; s_wait_time_expired = 0U; + if (g_plsr_segments[g_plsr_current_segment_index].wait_type == PLSR_WAIT_ACT) { act_time_ms = g_plsr_segments[g_plsr_current_segment_index].act_ms; - if (act_time_ms == 0U) - { - act_time_ms = g_plsr_segments[g_plsr_current_segment_index].wait_ms; - } - if (act_time_ms == 0U) - { - act_time_ms = 1U; - } s_act_timer_armed = 1U; PlsrSignalIoScheduleDelayMs((uint32_t)act_time_ms); } } /** - * @brief EXT 触发切段(脉冲可能还在跑) + * @brief EXT信号触发切段 * - * 同向且 PWM 在跑:不停表,下一段 f_from = 当前频率(衔接加速)。 + * 同向且 PWM 在跑:不停表,下一段 f_from = 当前频率。 * 反向或已停表:停表,下一段从起速爬。 */ static void PlsrRunControlCutSegToNext(void) @@ -290,18 +284,13 @@ static void PlsrRunControlActExpire(void) /** * @brief 段发完后的等待策略入口 * - * WAIT时间/信号/纯EXT → 停表清链后进 RC_WAIT_COND 或立即 GotoNext; + * WAIT时间/信号/EXT信号 → 停表清链后进 RC_WAIT_COND 或立即 GotoNext; * EXT_OR_DONE 脉冲先完 → 立刻下一段;其它 → GotoNextOrFinish。 */ static void PlsrRunControlEnterPostWaitOrNext(void) { uint16_t wms; - /* - * 调用顺序策略(与段内波形无关): - * WAIT时间/信号 → 停表清链后等待,再 BeginSeg(下一段从起速/起跳开跑) - * 其它 → 立即跳转下一段 - */ if (g_plsr_segments[g_plsr_current_segment_index].wait_type == PLSR_WAIT_TIME) { wms = g_plsr_segments[g_plsr_current_segment_index].wait_ms; @@ -311,17 +300,14 @@ static void PlsrRunControlEnterPostWaitOrNext(void) } PlsrRunControlClearChainAndStop(); s_waiting_for_input_signal = 0U; - PlsrRunControlWakeDrain(); + PlsrRunControlWakeDrain();/*清理过期令牌*/ s_state = RC_WAIT_COND; PlsrSignalIoScheduleDelayMs((uint32_t)wms); return; } if (g_plsr_segments[g_plsr_current_segment_index].wait_type == PLSR_WAIT_SIGNAL) { - /* - * 与 WAIT 时间相同:本段发完停表,再等 EXTI 确认后的下降沿。 - * 只认锁存的沿,不读当前电平——口线虚低或脉冲耦合都会误跳下一段。 - */ + /* 与 WAIT 时间相同:本段发完停表,再等 EXTI 确认后的下降沿 */ PlsrRunControlClearChainAndStop(); if (PlsrSignalIoTakeWaitFalling() != 0U) { @@ -335,10 +321,7 @@ static void PlsrRunControlEnterPostWaitOrNext(void) if (g_plsr_segments[g_plsr_current_segment_index].wait_type == PLSR_WAIT_EXT) { - /* - * 纯 EXT:脉冲发完后仍要等 EXT 沿才跳转。 - * 停表,下一段从起速/起跳重新规划。 - */ + /* EXT信号:脉冲发完后仍要等 EXT 沿才跳转 */ PlsrRunControlClearChainAndStop(); /* 只清消抖中的假沿;已确认的 fell 保留,供下面 TakeExtFalling 消费 */ PlsrSignalIoClearPending(); @@ -353,14 +336,14 @@ static void PlsrRunControlEnterPostWaitOrNext(void) } /* - * EXT_OR_DONE:脉冲先发完 = 条件已满足,立刻下一段(不再等 EXT)。 + * EXT_OR_DONE:脉冲先发完 = 条件已满足,立刻下一段。 * EXT 先到:RUN 里已 CutSegToNext,走不到这里。 */ PlsrRunControlGotoNextOrFinish(g_plsr_current_segment_index); } /** - * @brief 解析下一段:无则 FinishAll,有则 BeginSeg + * @brief 解析下一段:无则返回-1进 FinishAll,有则 BeginSeg */ static void PlsrRunControlGotoNextOrFinish(uint16_t cur_seg) { @@ -376,8 +359,6 @@ static void PlsrRunControlGotoNextOrFinish(uint16_t cur_seg) } } -/* ---------- 故障诊断(写 0x2006,见文件头说明) ---------- */ - /** * 0x01 脉冲个数诊断 * 时机:段正常结束进入 AfterSegDone 时。 @@ -392,13 +373,7 @@ static void PlsrRunControlCheckPulseCntFault(void) } } -/** - * 0x03 加速曲线诊断(离开 APPROACH → 匀速/减速前调用) - * @param by_pulse_budget - * 1:因相内脉冲走到规划 acc_n 而收尾 → 要求 g_plsr_accel_runtime.completed_pulses == g_plsr_accel_plan.accel_pulses - * 0:因频率已提前到达目标而收尾 → 仅当 n 超过规划预算时报故障 - * 对照量直接使用 PlanSeg 写入的 g_plsr_accel_plan.accel_pulses。 - */ +/* 0x03 加速曲线诊断 */ static void PlsrRunControlCheckApproachCurveFault(uint8_t by_pulse_budget) { if (g_plsr_accel_plan.accel_pulses == 0U) @@ -418,11 +393,7 @@ static void PlsrRunControlCheckApproachCurveFault(uint8_t by_pulse_budget) } } -/** - * 0x03 减速曲线诊断 - * 时机:段结束 AfterSegDone;仅当仍处 DECEL 相。 - * 条件:相内步进须至少跑满进入时锁定的预算(ARPE 超前下允许 n==budget)。 - */ +/* 0x03 减速曲线诊断 */ static void PlsrRunControlCheckDecelCurveFault(void) { if ((s_phase == PH_DECEL) && (g_plsr_accel_runtime.total_pulses > 0U) && @@ -446,10 +417,7 @@ static void PlsrRunControlAfterSegDone(void) /* 先脱离 RUN,避免脉冲 ISR 重入 */ s_state = RC_IDLE; - /* - * ACT ※4:脉冲已发完但 ACT 时间未到 → 停表,等到到期再开下一段。 - * 不从当前频率衔接(本段已经走完停表)。 - */ + /* 脉冲已发完但 ACT 时间未到 → 停表,等到到期再开下一段 */ if (g_plsr_segments[g_plsr_current_segment_index].wait_type == PLSR_WAIT_ACT) { PlsrPulseDriverStop(); @@ -462,7 +430,7 @@ static void PlsrRunControlAfterSegDone(void) { uint32_t remain_ms = PlsrSignalIoDelayRemainMs(); - PlsrSignalIoCancelDelay(); + PlsrSignalIoCancelDelay();//段发完后,wait时间取消旧定时器,重新计算剩余wait时间 s_act_timer_armed = 0U; if (remain_ms >= 1U) { @@ -475,7 +443,7 @@ static void PlsrRunControlAfterSegDone(void) } else { - PlsrSignalIoCancelDelay(); + PlsrSignalIoCancelDelay();//计时已到,取消定时 } s_act_timer_armed = 0U; PlsrRunControlGotoNextOrFinish(g_plsr_current_segment_index); @@ -485,7 +453,7 @@ static void PlsrRunControlAfterSegDone(void) s_act_timer_armed = 0U; s_act_expired = 0U; s_wait_time_expired = 0U; - + /*硬件脉冲是否关闭,1不关,0关闭*/ keep_pwm = (s_stop_after_last_pulse == 0U) ? 1U : 0U; if (g_plsr_config.send_mode == PLSR_SEND_COMPLETE) @@ -497,7 +465,7 @@ static void PlsrRunControlAfterSegDone(void) if (keep_pwm != 0U) { - /* 后续同向且无门禁:不停表直接 BeginSeg(仅衔接策略,不影响本段波形) */ + /* 后续同向且无门禁:不停表直接 BeginSeg */ s_continue_without_stopping = 1U; } else @@ -515,17 +483,11 @@ static void PlsrRunControlAfterSegDone(void) } /** - * @brief 哪些等待类型禁止 FOLLOW 不停表衔接 + * @brief 哪些等待类型禁止后续模式不停表衔接 * @return 1=必须停表等条件;0=允许(含 EXT_OR_DONE 脉冲先完) */ static uint8_t PlsrRunControlBlocksFollowKeep(uint16_t cur_seg) { - /* - * WAIT时间/信号/ACT:发完后停表等条件,禁止后续无缝衔接。 - * EXT:发完后仍等 EXT 沿,必须停表。 - * EXT_OR_DONE:脉冲先完则条件已满足,允许后续衔接; - * EXT 先到由 CutSegToNext 自行判断 keep。 - */ if ((g_plsr_segments[cur_seg].wait_type == PLSR_WAIT_TIME) || (g_plsr_segments[cur_seg].wait_type == PLSR_WAIT_SIGNAL) || (g_plsr_segments[cur_seg].wait_type == PLSR_WAIT_ACT) || @@ -536,31 +498,13 @@ static uint8_t PlsrRunControlBlocksFollowKeep(uint16_t cur_seg) return 0U; } -/** - * 解析本段规划端点:freq_start / freq_end / accel_ms / decel_ms - * - * 【freq_start 四选一,按 if 顺序】 - * follow_cont 且 cur_freq 有效 → 无缝衔接(ACT/EXT 切段) - * pwm 仍在跑 → 同频衔接(未停表) - * chain_valid → 上段落地频(完成模式停表后) - * 否则 → ResolveStartHz(冷启动/起跳) - * - * 【freq_end 大分支】 - * wait=EXT_OR_DONE 且有下一有效段 → 看同向/反向、FOLLOW/COMPLETE - * 其余(TIME/SIGNAL/ACT/EXT/末段)→ ResolveEndHz(止速/起跳三分支) - */ +/* 解析本段规划端点:freq_start / freq_end / accel_ms / decel_ms */ static uint8_t PlsrRunControlResolveSegPlanEndpoints(uint16_t seg_idx0, uint32_t f_tgt, PlsrSegPlanEndpoints_t *endpoints) { endpoints->accel_ms = g_plsr_config.accel_ms; endpoints->decel_ms = g_plsr_config.decel_ms; - /* ---------- 起始频率 ---------- - * 中途切段(ACT/EXT)会置 follow_cont:用打断瞬间的频率衔接下一段。 - * ACT 为了对齐脉冲边界可能先停表,此时 pwm_on=0,但仍要跟当前频率, - * 不能当成「段后停表」去走起跳。 - * 真正段后停表:follow_cont/chain 已清,从配置起速(0 则起跳)开跑。 - */ if ((s_continue_without_stopping != 0U) && (g_plsr_output_frequency_hz >= 1U)) { endpoints->freq_start_hz = g_plsr_output_frequency_hz; @@ -578,10 +522,7 @@ static uint8_t PlsrRunControlResolveSegPlanEndpoints(uint16_t seg_idx0, uint32_t } else { - /* - * 停表后冷启动:入口由 ResolveStartHz 按起速/目标/起跳三分支决定 - * (起速>目标→起速减速;否则与起跳比较取目标或起跳)。 - */ + /* 停表后冷启动 */ endpoints->freq_start_hz = PlsrAccelCurveResolveStartHz(g_plsr_config.start_speed, f_tgt, g_plsr_config.default_speed, @@ -589,13 +530,7 @@ static uint8_t PlsrRunControlResolveSegPlanEndpoints(uint16_t seg_idx0, uint32_t endpoints->decel_ms); } - /* - * ---------- 终止频率 ---------- - * EXT_OR_DONE:同向/反向只看「下一有效段」(跳过频率0且脉冲0 的占位段)。 - * 同向 + 后续 → 过渡到下一有效段目标;同向 + 完成 → 匀速峰值收尾。 - * 真末段 / TIME/SIGNAL/ACT/EXT / 换向 → ResolveEndHz(止速/目标/起跳三分支, - * 不再默认往 0 收;止速>目标则用止速,否则按起跳与目标比较)。 - */ + /* 终止频率 */ { int16_t next_eff = PlsrRunControlNextEffectiveSeg(seg_idx0); @@ -615,7 +550,7 @@ static uint8_t PlsrRunControlResolveSegPlanEndpoints(uint16_t seg_idx0, uint32_t } next_fwd = PlsrRunControlIsForward((uint16_t)next_eff, end_pos); - /* 与下一有效段同向 → FOLLOW/COMPLETE 衔接(换向才落到下方止速) */ + /* 与下一有效段同向 → 后续/完成衔接(换向才落到下方止速) */ if (next_fwd == s_forward) { if (g_plsr_config.send_mode == PLSR_SEND_FOLLOW) @@ -647,7 +582,7 @@ static uint8_t PlsrRunControlResolveSegPlanEndpoints(uint16_t seg_idx0, uint32_t /** * @brief 段末是否可不停表衔接下一段 - * @param local_pos 用于判下一段方向的局部坐标(应用「本段结束后」的位置) + * @param local_pos 用于判下一段方向的局部坐标 * @note 须 FOLLOW + 有同向下一段 + 无 BlocksFollowKeep */ static uint8_t PlsrRunControlWillFollowKeepAt(uint16_t cur_seg, int32_t local_pos) @@ -713,10 +648,10 @@ static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz, return 1U; } -/** 运行输出:0=停表;任务上下文 SetFreq / Start */ -static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start) +/** 任务侧运行输出:0=停表;任务上下文 SetFreq / Start */ +static void PlsrRunControlApplyOutFreq(uint32_t freq, uint8_t do_start) { - if (profile_freq == 0U) + if (freq == 0U) { PlsrPulseDriverStop(); return; @@ -724,30 +659,29 @@ static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start) if ((do_start != 0U) || (g_plsr_pwm_running == 0U)) { - PlsrPulseDriverStart(profile_freq); + PlsrPulseDriverStart(freq); } - else if (profile_freq != g_plsr_output_frequency_hz) + else if (freq != g_plsr_output_frequency_hz) { - PlsrPulseDriverSetFreq(profile_freq); + PlsrPulseDriverSetFreq(freq); } } /** 脉冲 ISR:只走 ARR 预装载路径 */ -static void PlsrRunControlApplyOutFreqIsr(uint32_t profile_freq) +static void PlsrRunControlApplyOutFreqIsr(uint32_t freq) { - if (profile_freq < 1U) + if (freq < 1U) { - profile_freq = 1U; + freq = 1U; } - PlsrPulseDriverSetFreqIsr(profile_freq); + PlsrPulseDriverSetFreqIsr(freq); } static uint8_t PlsrRunControlHasDecel(void) { /* * 第二相脉冲预算 >0 即需要收尾斜坡。 - * 谷底形(起/止速 > 目标):第二相是从目标再加速回止速,f_end > f_tgt, - * 不可再用「f_tgt==f_end 则无减速」这种假定。 + * 谷底形(起/止速 > 目标):第二相是从目标再加速回止速,f_end > f_tgt。 */ return (g_plsr_accel_plan.decel_pulses > 0U) ? 1U : 0U; } @@ -761,11 +695,7 @@ static uint32_t PlsrRunControlRemainPulses(void) return 0U; } -/** - * ARPE:本拍 ISR 写入的影子 ARR 在下一周期生效。 - * remain==dec_n 时切入并写入 f(1),…,remain==1 写入 f_end → 末拍为止速。 - * 若已晚进(remain < planned),预算用满剩余拍数,避免再减 1 导致末两拍同为止速。 - */ +/* remain==dec_n 时进入减速 */ static uint8_t PlsrRunControlShouldEnterDecel(uint32_t remain) { if (PlsrRunControlHasDecel() == 0U) @@ -801,10 +731,10 @@ static int32_t PlsrRunControlAbsLocalPos(void) } /** - * 减速相写出频率:仅 remain==1(供末拍)允许钉止速; + * 减速相写出频率:仅 remain==1允许钉止速; * 更早写入若已碰到 end,则让出 1Hz,避免末两拍同频。 */ -static uint32_t PlsrRunControlDecelOutFreq(uint32_t profile_freq, uint32_t remain) +static uint32_t PlsrRunControlDecelOutFreq(uint32_t freq, uint32_t remain) { uint32_t end_hz = g_plsr_accel_plan.end_frequency_hz; @@ -820,20 +750,20 @@ static uint32_t PlsrRunControlDecelOutFreq(uint32_t profile_freq, uint32_t remai if (g_plsr_accel_runtime.frequency_rising == 0U) { - if ((profile_freq <= end_hz) && (end_hz < 100000U)) + if ((freq <= end_hz) && (end_hz < 100000U)) { return end_hz + 1U; } } - else if ((profile_freq >= end_hz) && (end_hz > 1U)) + else if ((freq >= end_hz) && (end_hz > 1U)) { return end_hz - 1U; } - return profile_freq; + return freq; } /** - * @brief 进入减速相:budget 为曲线步进总数(非物理 remain),BeginDec + * @brief 进入减速相:budget 为曲线步进总数,BeginDec */ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t budget) { @@ -853,10 +783,7 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t budget) g_plsr_accel_runtime.current_frequency_hz = from_hz; } -/** - * 开表纯减速:只 Start(f1)。下一拍起由 ISR NextFrequency 写入 f2…f_end。 - * (旧逻辑再预装 f2 会在 ARPE 下让首拍直接吃到 f2,并多步进一次。) - */ +/* 开表纯减速:只 Start(f1)。下一拍起由 ISR NextFrequency 写入 f2…f_end */ static void PlsrRunControlPrimeDecelOnStart(void) { uint32_t next; @@ -865,7 +792,7 @@ static void PlsrRunControlPrimeDecelOnStart(void) PlsrRunControlApplyOutFreq(next, 1U); } -/** 离开加速相时触发 0x03 加速诊断(仅当前相为 APPROACH 时有效) */ +/** 离开加速相时触发 0x03 加速诊断 */ static void PlsrRunControlOnApproachDone(void) { uint8_t by_budget; @@ -874,14 +801,13 @@ static void PlsrRunControlOnApproachDone(void) { return; } - /* n 已走到预算 → 按「预算收尾」精确比对;否则按「提前到频」只查超额 */ - by_budget = ((g_plsr_accel_plan.accel_pulses > 0U) && (g_plsr_accel_runtime.completed_pulses >= g_plsr_accel_plan.accel_pulses)) ? 1U : 0U; + /* n 已走到预算 → 按预算收尾精确比对;否则按提前到频只查超额 */ + by_budget = ((g_plsr_accel_plan.accel_pulses > 0U) + && (g_plsr_accel_runtime.completed_pulses >= g_plsr_accel_plan.accel_pulses)) ? 1U : 0U; PlsrRunControlCheckApproachCurveFault(by_budget); } -/** - * 进匀速:写一次 f_tgt,之后 ISR 不改 ARR(复用缓存)。 - */ +/* 进匀速:写一次 f_tgt,之后 ISR 不改 ARR(复用缓存)*/ static void PlsrRunControlEnterConstHold(uint8_t do_start) { uint32_t f_hold = g_plsr_accel_plan.target_frequency_hz; @@ -914,15 +840,7 @@ static void PlsrRunControlEnterConstHoldIsr(void) /** * 任务侧:按当前段内相 s_phase,决定开表/改频用哪个频率。 - * * @param do_start 1=需要 Start PWM(RefreshProfile(1));0=已在跑只改频 - * - * 【分支顺序】 - * 1) CONST 且 remain 进减速窗 → EnterDecel,return 前不 Start - * 2) CONST → 仅 do_start 时 Start(f_tgt),return - * 3) DECEL 且刚开段(n=0) → PrimeDecelOnStart(Start(f1),其余交 ISR) - * 4) APPROACH → FreqAtPulse(done_n);若已到 f_tgt 则进 CONST 或 DECEL - * 5) 其它 → ApplyOutFreq(next, do_start) */ static void PlsrRunControlRefreshProfile(uint8_t do_start) { @@ -988,7 +906,7 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) (next <= g_plsr_accel_plan.target_frequency_hz))) { next = g_plsr_accel_plan.target_frequency_hz; - PlsrRunControlOnApproachDone(); + PlsrRunControlOnApproachDone();/* 加速结束诊断曲线 */ if (PlsrRunControlShouldEnterDecel(remain) != 0U) { PlsrRunControlEnterDecel(next, @@ -1019,13 +937,9 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, uint16_t accel_ms, uint16_t decel_ms) { uint32_t f_start; - uint32_t f_lo; - uint32_t f_hi; + uint32_t f_min; + uint32_t f_max; - /* - * 曲线估 acc_n / dec_n,const_n = total − acc − dec。 - * f_from/f_end 已由策略层解析为真实频率;配置起止=0 时已换成起跳/落地。 - */ PlsrAccelCurvePlan(&g_plsr_accel_plan, total, f_from, @@ -1036,11 +950,7 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, decel_ms, g_plsr_config.accel_mode); - /* - * 0x02 频率可达性诊断 - * AccelCurvePlan 后:若脉冲不够爬升/下降到设定目标,规划会压低/抬高实际峰值 - * (典型为三角波)。此时写故障码 2,仍按压后的规划继续运行。 - */ + /* 0x02 频率是否与设定一致诊断/\或\/ */ if ((f_tgt > f_from) && (g_plsr_accel_plan.target_frequency_hz < f_tgt)) { PlsrCommandSetFault(PLSR_ERR_FREQ_UNREACH); @@ -1058,77 +968,65 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, /* 运行层使用规划后的实际起始频率。 */ f_start = g_plsr_accel_plan.start_frequency_hz; - /* - * 脉冲域:ISR 用 PlsrAccelNextFrequency(直线现场算 / S·正弦查预建表)。 - * FreqAtPulse 仅任务侧 RefreshProfile 对齐用,勿再做时间轴二次拟合。 - */ - + /* 脉冲域:ISR 用 PlsrAccelNextFrequency(直线现场算 / S·正弦查预建表)*/ /* 本段频率范围锁 PSC,升降只改 ARR;跨度过大则 LockPscRange 自动不锁 */ - f_lo = g_plsr_accel_plan.target_frequency_hz; - f_hi = g_plsr_accel_plan.target_frequency_hz; - if (f_start > f_hi) + /* 本段可能出现的最低/最高频率,取 入口、目标、出口 三者的 min/max */ + f_min = g_plsr_accel_plan.target_frequency_hz; + f_max = g_plsr_accel_plan.target_frequency_hz; + if (f_start > f_max) { - f_hi = f_start; + f_max = f_start; } if (f_start >= 1U) { - if (f_start < f_lo) + if (f_start < f_min) { - f_lo = f_start; + f_min = f_start; } } else { - f_lo = 1U; + f_min = 1U; } - if (g_plsr_accel_plan.end_frequency_hz > f_hi) + if (g_plsr_accel_plan.end_frequency_hz > f_max) { - f_hi = g_plsr_accel_plan.end_frequency_hz; + f_max = g_plsr_accel_plan.end_frequency_hz; } if (g_plsr_accel_plan.end_frequency_hz >= 1U) { - if (g_plsr_accel_plan.end_frequency_hz < f_lo) + if (g_plsr_accel_plan.end_frequency_hz < f_min) { - f_lo = g_plsr_accel_plan.end_frequency_hz; + f_min = g_plsr_accel_plan.end_frequency_hz; } } else { - if (f_lo > 1U) + if (f_min > 1U) { - f_lo = 1U; + f_min = 1U; } } - if (f_lo < 1U) + if (f_min < 1U) { - f_lo = 1U; + f_min = 1U; } - if (f_hi < f_lo) + if (f_max < f_min) { - f_hi = f_lo; + f_max = f_min; } - /* - * 后续同向不停表时 PWM 仍在跑:禁止重锁 PSC。 - */ + /* 后续同向不停表时 PWM 仍在跑:禁止重锁 PSC */ if (g_plsr_pwm_running == 0U) { - PlsrPulseDriverLockPscRange(f_lo, f_hi); + PlsrPulseDriverLockPscRange(f_min, f_max); } - /* - * 保持 AccelCurvePlan 算出的脉冲预算;运行时逐拍计算下一频率。 - */ - /* - * 进入段内初始相(决定 RefreshProfile / ISR 从哪开始): - * 纯减段(dec_n>=total 且已在高位)→ 直接 PH_DECEL - * 入口=目标 → PH_CONST(无加速) - * 否则 → PH_APPROACH - */ + /* 保持 AccelCurvePlan 算出的脉冲预算;运行时逐拍计算下一频率 */ if ((g_plsr_accel_plan.decel_pulses >= total) && (total > 0U) && (g_plsr_accel_plan.end_frequency_hz != g_plsr_accel_plan.target_frequency_hz) && (f_start >= g_plsr_accel_plan.target_frequency_hz)) { + /*纯减开段,脉冲数不足以减速到目标频率 */ PlsrRunControlEnterDecel(f_start, g_plsr_accel_plan.decel_pulses); } else if (f_start == g_plsr_accel_plan.target_frequency_hz) @@ -1165,14 +1063,7 @@ static void PlsrRunControlFinishAll(void) s_waiting_for_last_period = 0U; } -/** - * @brief 开一段:算位移/方向 → PlanSeg → 选「无缝 / 同向直开 / 换向延时」 - * - * 【开表三分支 — BeginSeg 末尾】 - * follow_cont 上段 FOLLOW/ACT 衔接:不停表,RefreshProfile(0) - * 同向且 dir 已对 跳过 DIR_WAIT,RefreshProfile(1) 开表 - * 否则 设方向脚;dir_delay=0 立刻开,>0 进 RC_DIR_WAIT+Prepare - */ +/* 开一段:算位移/方向 → PlanSeg → 选无缝/同向直开/换向延时 */ static void PlsrRunControlBeginSeg(uint16_t seg_idx0) { int32_t cnt; @@ -1232,14 +1123,11 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx0) s_forward = 0U; s_segment_pulse_target = -move; } - + + /* 0x04:本段(或默认速度)频率非法 */ if (PlsrRunControlGetSegTargetFreq(g_plsr_segments[seg_idx0].freq_hz, g_plsr_config.default_speed, &f_tgt) == 0U) { - /* - * 0x04:本段(或默认速度)频率非法。 - * 禁止启动该段:清忙并结束整次运行,不 AfterSegDone 以免误切下一段。 - */ PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); PlsrRunControlFinishAll(); return; @@ -1277,7 +1165,7 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx0) if (s_continue_without_stopping != 0U) { - /* 分支 A:段间无缝(FOLLOW 或 ACT handoff) */ + /* 分支 A:段间无缝(后续模式或 ACT切段) */ PlsrPulseDriverClearOnePulseStop(); /* * 必须先 RC_RUN 再 RefreshProfile/Start:否则冷启动首拍 UPDATE 时 @@ -1326,7 +1214,7 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx0) } } -/** @brief 运行控制初始化(见 plsr_run_control.h) */ +/** @brief 运行控制初始化 */ void PlsrRunControlInit(void) { s_state = RC_IDLE; @@ -1365,7 +1253,7 @@ static void PlsrRunControlWakeDrain(void) { while (OSSemAccept(s_wake_sem) > 0U) { - /* drain */ + /* 全部丢弃令牌 */ } } } @@ -1379,7 +1267,7 @@ static void PlsrRunControlWakePost(void) } /** - * @brief 创建任务唤醒信号量(见 plsr_run_control.h) + * @brief 创建任务唤醒信号量 */ void PlsrRunControlWakeInit(void) { @@ -1390,7 +1278,7 @@ void PlsrRunControlWakeInit(void) } /** - * @brief PlsrTask 休眠(见 plsr_run_control.h) + * @brief PlsrTask 休眠 */ void PlsrRunControlWakePend(uint16_t timeout_ticks) { @@ -1410,7 +1298,7 @@ void PlsrRunControlWakePend(uint16_t timeout_ticks) } /** - * @brief 是否在 TIM5 精确等待(见 plsr_run_control.h) + * @brief 是否在 TIM5 精确等待 */ uint8_t PlsrRunControlIsPreciseWait(void) { @@ -1425,7 +1313,7 @@ uint8_t PlsrRunControlIsPreciseWait(void) return 0U; } -/** @brief 启动多段序列(见 plsr_run_control.h) */ +/** @brief 启动多段序列 */ uint8_t PlsrStart(uint16_t start_seg_1based) { uint16_t n; @@ -1473,7 +1361,7 @@ uint8_t PlsrStart(uint16_t start_seg_1based) return 1U; } -/** @brief 急停(见 plsr_run_control.h) */ +/** @brief 急停 */ void PlsrStop(void) { PlsrSignalIoCancelDelay(); @@ -1493,7 +1381,7 @@ void PlsrStop(void) s_waiting_for_last_period = 0U; } -/** @brief 运行中改频(见 plsr_run_control.h) */ +/** @brief 运行中改频 */ uint8_t PlsrChangeFreq(uint32_t new_tgt_hz) { uint32_t remain; @@ -1524,7 +1412,7 @@ uint8_t PlsrChangeFreq(uint32_t new_tgt_hz) return 1U; } -/** @brief 毫秒任务节拍(见 plsr_run_control.h) */ +/** @brief 毫秒任务节拍 */ void PlsrRunControlTickMs(void) { if (s_act_expired != 0U) @@ -1621,30 +1509,22 @@ void PlsrRunControlOnDelayTimer(void) } } -/** @brief 脉冲 UPDATE ISR — 本文件最核心、if 最多的函数 */ +/** @brief 脉冲 UPDATE ISR */ void PlsrOnPulseIsr(void) { uint32_t remain; uint32_t next; - /* 只有 RC_RUN 才计数、改频;WAIT/IDLE 里进 ISR 是空操作 */ if (s_state != RC_RUN) { return; } - /* - * 末拍整周期已跑完:本 UPDATE 由 OPM 停表产生,不再计入脉冲。 - * 先于 s_segment_pulses_done++,保证个数 = target 且示波器末拍完整。 - */ if (s_waiting_for_last_period != 0U) { s_waiting_for_last_period = 0U; s_act_waiting_for_pulse_boundary = 0U; - /* - * 末拍下降沿已在 CC1 中断拉低;本 UPDATE 为 OPM 周期结束,不再 ++。 - * 再 HoldOutputLow 完整停表,交 AfterSegDone。 - */ + PlsrPulseDriverHoldOutputLow(); PlsrRunControlAfterSegDone(); return; @@ -1660,20 +1540,11 @@ void PlsrOnPulseIsr(void) g_plsr_accumulated_pulses--; } - /* - * ACT 到期切段只在脉冲边界执行,避免半个 PWM 周期改段。 - * 到点由 TIM5 置 cut_pending 并 OPM;此处收尾切段。 - * 加减速下周期长短不定,不按脉冲个数预测,墙钟可能多出「当前这一拍」的剩余。 - */ if (s_act_waiting_for_pulse_boundary != 0U) { s_act_waiting_for_pulse_boundary = 0U; s_keep_frequency_after_act = 1U; - /* - * TIM5 已 ArmActStop:输出在本拍下降沿后保持低,UPDATE 后计数器会停。 - * 必须清 g_plsr_pwm_running,否则 ActExpire 同向衔接走 RefreshProfile(0) - * 时误判「表仍在跑」而不 Start,卡死在下一段入口。 - */ + PlsrPulseDriverHoldOutputLow(); s_state = RC_IDLE; s_act_expired = 1U; @@ -1685,11 +1556,6 @@ void PlsrOnPulseIsr(void) { if (s_stop_after_last_pulse != 0U) { - /* - * 段末停表模式:本 UPDATE 是「最后一拍」的上升沿(s_segment_pulses_done 已等于 target)。 - * 武装 OPM+CC1:下降沿拉低,下一 UPDATE 进 s_waiting_for_last_period 再 AfterSegDone。 - * FOLLOW-keep 时 s_stop_after_last_pulse=0,走 else 立刻切段不停表。 - */ PlsrPulseDriverArmSegEndStop(); s_waiting_for_last_period = 1U; return; @@ -1701,16 +1567,9 @@ void PlsrOnPulseIsr(void) remain = PlsrRunControlRemainPulses(); - /* - * --- 段内三相:按 s_phase 改频(匀速几乎空转)--- - * remain = 还剩几拍(含当前正在进行的这一拍) - */ if (s_phase == PH_CONST) { - /* - * 匀速:不改频、不写 ARR(热路径几乎空转)。 - * 仅在 remain 进入减速窗口时切相并查表改频。 - */ + /* 匀速:不改频、不写 ARR,仅在 remain 进入减速窗口时切相并查表改频 */ PlsrPulseDriverClearStartPeriodProtect(); if (PlsrRunControlShouldEnterDecel(remain) != 0U) { @@ -1724,7 +1583,7 @@ void PlsrOnPulseIsr(void) } else if (s_phase == PH_APPROACH) { - /* 每拍 Step 得下一频;若加速相结束则进 CONST 或 DECEL(条件同 RefreshProfile) */ + /* 每拍 Step 得下一频;若加速相结束则进 CONST 或 DECEL */ next = PlsrAccelNextFrequency(&g_plsr_accel_runtime); if ((g_plsr_accel_plan.accel_pulses == 0U) || @@ -1758,10 +1617,6 @@ void PlsrOnPulseIsr(void) } else /* PH_DECEL */ { - /* - * ARPE:remain==k 写入 → 下一拍使用。 - * remain==1 必须写出 f_end(末拍);remain>1 禁止提前钉止速。 - */ if ((remain <= 1U) && (g_plsr_accel_runtime.total_pulses > 0U) && (g_plsr_accel_runtime.completed_pulses >= g_plsr_accel_runtime.total_pulses)) @@ -1778,7 +1633,7 @@ void PlsrOnPulseIsr(void) } } -/** @brief 清累计与绝对原点(见 plsr_run_control.h) */ +/** @brief 清累计与绝对原点 */ void PlsrClearAccPulse(void) { g_plsr_accumulated_pulses = 0; @@ -1786,7 +1641,7 @@ void PlsrClearAccPulse(void) s_absolute_origin_locked = 0U; /* 下次 Start 重新锁定原点 */ } -/** @brief 上电恢复累计(见 plsr_run_control.h) */ +/** @brief 上电恢复累计 */ void PlsrRunControlRestoreAccPulse(int32_t acc_pulse) { g_plsr_accumulated_pulses = acc_pulse;