|
|
|
@@ -37,8 +37,10 @@ |
|
|
|
* 5) s_segment_pulses_done >= target → OPM 末拍 or 立刻 AfterSegDone |
|
|
|
* 6) 按 s_phase 改频:CONST 只进减速;APPROACH Step;DECEL Step |
|
|
|
* |
|
|
|
* ARPE 补偿(为何 remain==dec_n+1 才进减速): |
|
|
|
* 本拍 ISR 写的 ARR 要「再下一拍」才生效;故须提前一拍写入 f_end。 |
|
|
|
* ARPE(UPDATE ISR 写影子 → 下一周期才装入工作 ARR): |
|
|
|
* 在 remain==k 时写入的频率供下一拍使用;进减速窗为 remain<=dec_n, |
|
|
|
* 在 remain==1 写入 f_end,末拍才能吃到止速。勿再用 remain<=dec_n+1, |
|
|
|
* 否则会在 remain==2 就强制止速,造成末两拍同频。 |
|
|
|
* |
|
|
|
* 分层(阶段1薄拆分): |
|
|
|
* 1) 曲线(accel_curve):只吃 (f_from,f_tgt,f_end,斜率,N,mode) → 梯形/三角; |
|
|
|
@@ -59,14 +61,14 @@ |
|
|
|
* 【运行节拍】纯脉冲计数: |
|
|
|
* UPDATE ISR:s_segment_pulses_done++;末拍用 ArmSegEndStop 完整收尾; |
|
|
|
* 加/减速逐拍 PlsrAccelNextFrequency + SetFreqIsr; |
|
|
|
* 匀速复用 ARR(不改频);remain<=dec_n+1 进减速(补偿 ARR 预装载晚一拍)。 |
|
|
|
* 匀速复用 ARR(不改频);remain<=dec_n 进减速。 |
|
|
|
* 任务 TickMs:ACT(OS 节拍)/ EXT / ApplyPending; |
|
|
|
* TIM5 one-shot:换向/WAIT/ACT/ACT剩余;ACT 到期收完当前脉冲并锁低,周期边界再切段。 |
|
|
|
* PlsrTask:DebouncePoll + TickMs + WakePend。 |
|
|
|
* |
|
|
|
* 【段末频率 / ARPE】预装载开启时,本拍写的 ARR 要到再下一拍才生效; |
|
|
|
* 若不超前,末拍实际是 f(N-1)≈sqrt(f_end^2+2a),示波器偶发「末频偏高」。 |
|
|
|
* 减速在 remain==dec_n+1 切入;纯减速开表再预装一拍。 |
|
|
|
* 【段末频率 / ARPE】UPDATE 里写的影子 ARR 在下一周期生效; |
|
|
|
* 减速在 remain==dec_n 切入,共 Step dec_n 次,最后一次(remain==1)写入 f_end。 |
|
|
|
* 纯减速开表:Start(f1),后续由 ISR 顺序写入 f2…f_end(勿再预步进一拍)。 |
|
|
|
* |
|
|
|
* 【段末停表】非 FOLLOW-keep 时开段锁 s_stop_after_last_pulse: |
|
|
|
* UPDATE≈上升沿;s_segment_pulses_done 到 target 时 ArmSegEndStop(OPM+CC1 末拍下降沿拉低), |
|
|
|
@@ -859,9 +861,9 @@ static uint32_t PlsrRunControlRemainPulses(void) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* ARPE:本拍 ISR 写入的 ARR 要到「再下一拍」才被计数器使用。 |
|
|
|
* 故在 remain==dec_n+1 时进入并写入 f(1),末拍才能吃到 f_end。 |
|
|
|
* 若已晚进(remain<=dec_n),预算改为 remain-1,仍保证 remain==2 时落到止速。 |
|
|
|
* ARPE:本拍 ISR 写入的影子 ARR 在下一周期生效。 |
|
|
|
* remain==dec_n 时切入并写入 f(1),…,remain==1 写入 f_end → 末拍为止速。 |
|
|
|
* 若已晚进(remain < planned),预算用满剩余拍数,避免再减 1 导致末两拍同为止速。 |
|
|
|
*/ |
|
|
|
static uint8_t PlsrRunControlShouldEnterDecel(uint32_t remain) |
|
|
|
{ |
|
|
|
@@ -869,7 +871,7 @@ static uint8_t PlsrRunControlShouldEnterDecel(uint32_t remain) |
|
|
|
{ |
|
|
|
return 0U; |
|
|
|
} |
|
|
|
return (remain <= (g_plsr_accel_plan.decel_pulses + 1U)) ? 1U : 0U; |
|
|
|
return (remain <= g_plsr_accel_plan.decel_pulses) ? 1U : 0U; |
|
|
|
} |
|
|
|
|
|
|
|
static uint32_t PlsrRunControlDecelEnterBudget(uint32_t remain) |
|
|
|
@@ -880,15 +882,15 @@ static uint32_t PlsrRunControlDecelEnterBudget(uint32_t remain) |
|
|
|
{ |
|
|
|
planned = 1U; |
|
|
|
} |
|
|
|
if (remain > planned) |
|
|
|
if (remain >= planned) |
|
|
|
{ |
|
|
|
return planned; |
|
|
|
} |
|
|
|
if (remain > 1U) |
|
|
|
if (remain < 1U) |
|
|
|
{ |
|
|
|
return remain - 1U; |
|
|
|
return 1U; |
|
|
|
} |
|
|
|
return 1U; |
|
|
|
return remain; |
|
|
|
} |
|
|
|
|
|
|
|
/** 绝对模式:相对本次启动原点的位置 */ |
|
|
|
@@ -897,6 +899,38 @@ static int32_t PlsrRunControlAbsLocalPos(void) |
|
|
|
return g_plsr_accumulated_pulses - s_absolute_origin; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 减速相写出频率:仅 remain==1(供末拍)允许钉止速; |
|
|
|
* 更早写入若已碰到 end,则让出 1Hz,避免末两拍同频。 |
|
|
|
*/ |
|
|
|
static uint32_t PlsrRunControlDecelOutFreq(uint32_t profile_freq, uint32_t remain) |
|
|
|
{ |
|
|
|
uint32_t end_hz = g_plsr_accel_plan.end_frequency_hz; |
|
|
|
|
|
|
|
if (end_hz < 1U) |
|
|
|
{ |
|
|
|
end_hz = 1U; |
|
|
|
} |
|
|
|
|
|
|
|
if (remain <= 1U) |
|
|
|
{ |
|
|
|
return end_hz; |
|
|
|
} |
|
|
|
|
|
|
|
if (g_plsr_accel_runtime.frequency_rising == 0U) |
|
|
|
{ |
|
|
|
if ((profile_freq <= end_hz) && (end_hz < 100000U)) |
|
|
|
{ |
|
|
|
return end_hz + 1U; |
|
|
|
} |
|
|
|
} |
|
|
|
else if ((profile_freq >= end_hz) && (end_hz > 1U)) |
|
|
|
{ |
|
|
|
return end_hz - 1U; |
|
|
|
} |
|
|
|
return profile_freq; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 进入减速相:budget 为曲线步进总数(非物理 remain),BeginDec |
|
|
|
*/ |
|
|
|
@@ -919,7 +953,8 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t budget) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 开表纯减速:Start(f1) 后再预装 f2,补偿 ARPE,使第 N 拍为 f_end。 |
|
|
|
* 开表纯减速:只 Start(f1)。下一拍起由 ISR NextFrequency 写入 f2…f_end。 |
|
|
|
* (旧逻辑再预装 f2 会在 ARPE 下让首拍直接吃到 f2,并多步进一次。) |
|
|
|
*/ |
|
|
|
static void PlsrRunControlPrimeDecelOnStart(void) |
|
|
|
{ |
|
|
|
@@ -927,11 +962,6 @@ static void PlsrRunControlPrimeDecelOnStart(void) |
|
|
|
|
|
|
|
next = PlsrAccelNextFrequency(&g_plsr_accel_runtime); |
|
|
|
PlsrRunControlApplyOutFreq(next, 1U); |
|
|
|
if (g_plsr_accel_runtime.total_pulses > 1U) |
|
|
|
{ |
|
|
|
next = PlsrAccelNextFrequency(&g_plsr_accel_runtime); |
|
|
|
PlsrPulseDriverSetFreq(next); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** 离开加速相时触发 0x03 加速诊断(仅当前相为 APPROACH 时有效) */ |
|
|
|
@@ -989,7 +1019,7 @@ static void PlsrRunControlEnterConstHoldIsr(void) |
|
|
|
* 【分支顺序】 |
|
|
|
* 1) CONST 且 remain 进减速窗 → EnterDecel,return 前不 Start |
|
|
|
* 2) CONST → 仅 do_start 时 Start(f_tgt),return |
|
|
|
* 3) DECEL 且刚开段(n=0) → PrimeDecelOnStart(预装两拍,补 ARPE) |
|
|
|
* 3) DECEL 且刚开段(n=0) → PrimeDecelOnStart(Start(f1),其余交 ISR) |
|
|
|
* 4) APPROACH → FreqAtPulse(done_n);若已到 f_tgt 则进 CONST 或 DECEL |
|
|
|
* 5) 其它 → ApplyOutFreq(next, do_start) |
|
|
|
*/ |
|
|
|
@@ -1022,7 +1052,7 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* 纯减速开表:超前预装,避免末拍停在 f(N-1) */ |
|
|
|
/* 纯减速开表:Start(f1),f2…f_end 由后续 UPDATE ISR 写入 */ |
|
|
|
if ((s_phase == PH_DECEL) && |
|
|
|
(do_start != 0U) && |
|
|
|
(s_segment_pulses_done == 0) && |
|
|
|
@@ -1348,13 +1378,17 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx0) |
|
|
|
{ |
|
|
|
/* 分支 A:段间无缝(FOLLOW 或 ACT handoff) */ |
|
|
|
PlsrPulseDriverClearOnePulseStop(); |
|
|
|
/* |
|
|
|
* 必须先 RC_RUN 再 RefreshProfile/Start:否则冷启动首拍 UPDATE 时 |
|
|
|
* OnPulseIsr 仍见非 RUN 直接 return,影子停在起跳频,第 1、2 拍同频。 |
|
|
|
*/ |
|
|
|
s_state = RC_RUN; |
|
|
|
s_continue_without_stopping = 0U; |
|
|
|
/* |
|
|
|
* FOLLOW 真不停表:do_start=0 只改频。 |
|
|
|
* ACT 经 OPM 边界停表后 g_plsr_pwm_running 已为 0:须 Start 重开,否则无脉冲卡死。 |
|
|
|
*/ |
|
|
|
PlsrRunControlRefreshProfile((g_plsr_pwm_running == 0U) ? 1U : 0U); |
|
|
|
s_state = RC_RUN; |
|
|
|
s_continue_without_stopping = 0U; |
|
|
|
PlsrRunControlArmActExtOnPulseStart(); |
|
|
|
} |
|
|
|
else if ((g_plsr_direction_valid != 0U) && (s_forward == g_plsr_direction_forward)) |
|
|
|
@@ -1782,6 +1816,8 @@ void PlsrOnPulseIsr(void) |
|
|
|
PlsrRunControlEnterDecel(g_plsr_accel_plan.target_frequency_hz, |
|
|
|
PlsrRunControlDecelEnterBudget(remain)); |
|
|
|
next = PlsrAccelNextFrequency(&g_plsr_accel_runtime); |
|
|
|
next = PlsrRunControlDecelOutFreq(next, remain); |
|
|
|
g_plsr_accel_runtime.current_frequency_hz = next; |
|
|
|
PlsrRunControlApplyOutFreqIsr(next); |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -1805,6 +1841,8 @@ void PlsrOnPulseIsr(void) |
|
|
|
PlsrRunControlEnterDecel(next, |
|
|
|
PlsrRunControlDecelEnterBudget(remain)); |
|
|
|
next = PlsrAccelNextFrequency(&g_plsr_accel_runtime); |
|
|
|
next = PlsrRunControlDecelOutFreq(next, remain); |
|
|
|
g_plsr_accel_runtime.current_frequency_hz = next; |
|
|
|
PlsrRunControlApplyOutFreqIsr(next); |
|
|
|
} |
|
|
|
else |
|
|
|
@@ -1820,23 +1858,21 @@ void PlsrOnPulseIsr(void) |
|
|
|
else /* PH_DECEL */ |
|
|
|
{ |
|
|
|
/* |
|
|
|
* remain==1:末拍已在跑(ARR 在 remain==2 时写入),勿再 Step, |
|
|
|
* 以免 n 超过 budget 误触 0x03。 |
|
|
|
* 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)) |
|
|
|
{ |
|
|
|
next = g_plsr_accel_plan.end_frequency_hz; |
|
|
|
if (next < 1U) |
|
|
|
{ |
|
|
|
next = 1U; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
next = PlsrAccelNextFrequency(&g_plsr_accel_runtime); |
|
|
|
} |
|
|
|
next = PlsrRunControlDecelOutFreq(next, remain); |
|
|
|
g_plsr_accel_runtime.current_frequency_hz = next; |
|
|
|
PlsrRunControlApplyOutFreqIsr(next); |
|
|
|
} |
|
|
|
} |
|
|
|
|