|
|
|
@@ -12,10 +12,11 @@ |
|
|
|
* 3) 发送模式只影响本段 f_end(完成=止速;后续且不停表=下一段目标) |
|
|
|
* 4) PlanSeg / ChangeFreq 共用规划入口,便于后期动态改频 |
|
|
|
* |
|
|
|
* 【运行节拍】脉冲 UPDATE:计 s_done;加/减速置 dirty,匀速不周期性改频。 |
|
|
|
* 任务 TickMs:dirty 时 FreqAtPulse 改频。 |
|
|
|
* TIM3 1ms:仅 ACT/WAIT 时基(不改频)。 |
|
|
|
* 匀速“保持”≠禁止改频:ACT/EXT 打断、ChangeFreq、进减速、开下一段仍可 Start/SetFreq。 |
|
|
|
* 【运行节拍】纯脉冲计数: |
|
|
|
* UPDATE ISR:s_done++;加/减速逐拍 PlsrAccelPulseRtStep + SetFreqIsr; |
|
|
|
* 匀速复用 ARR(不改频);remain<=dec_n 进减速。 |
|
|
|
* 任务 TickMs:仅 ACT/WAIT/EXT/换向延时 + ApplyPending(极少换 PSC)。 |
|
|
|
* TIM3 1ms:仅 ACT/WAIT 时基。 |
|
|
|
*/ |
|
|
|
#include "plsr_run_control.h" |
|
|
|
#include "plsr_path_plan.h" |
|
|
|
@@ -61,11 +62,11 @@ static volatile uint8_t s_wait_expire_req; /* WAIT 时间到:ISR 只置位 */ |
|
|
|
static uint8_t s_wait_is_signal; /* RC_WAIT_COND:1=等 WAIT 沿,0=等时间 */ |
|
|
|
|
|
|
|
static PlsrAccelPlan_t s_accel_plan; |
|
|
|
static PlsrAccelPulseRt_t s_pulse_rt; |
|
|
|
static volatile RunPhase_e s_phase; /* ISR 读相,须 volatile */ |
|
|
|
static uint32_t s_approach_from; |
|
|
|
static uint32_t s_decel_from; |
|
|
|
static uint8_t s_follow_cont; |
|
|
|
static volatile uint8_t s_profile_dirty; /* 脉冲推进后由任务改频 */ |
|
|
|
|
|
|
|
static uint32_t s_chain_freq; |
|
|
|
static uint8_t s_chain_valid; |
|
|
|
@@ -630,6 +631,17 @@ static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start) |
|
|
|
s_cur_freq = profile_freq; |
|
|
|
} |
|
|
|
|
|
|
|
/** 脉冲 ISR:只走 ARR 预装载路径 */ |
|
|
|
static void PlsrRunControlApplyOutFreqIsr(uint32_t profile_freq) |
|
|
|
{ |
|
|
|
if (profile_freq < 1U) |
|
|
|
{ |
|
|
|
profile_freq = 1U; |
|
|
|
} |
|
|
|
PlsrPulseDriverSetFreqIsr(profile_freq); |
|
|
|
s_cur_freq = profile_freq; |
|
|
|
} |
|
|
|
|
|
|
|
static void PlsrRunControlEnterPhase(RunPhase_e ph, uint32_t anchor_freq) |
|
|
|
{ |
|
|
|
s_phase = ph; |
|
|
|
@@ -671,7 +683,8 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
|
s_accel_plan.dec_n = remain_pulses; |
|
|
|
s_accel_plan.f_tgt = from_hz; |
|
|
|
s_decel_from = from_hz; |
|
|
|
s_profile_dirty = 1U; |
|
|
|
PlsrAccelPulseRtBeginDec(&s_pulse_rt, &s_accel_plan); |
|
|
|
s_pulse_rt.f = from_hz; |
|
|
|
|
|
|
|
if (remain_pulses == 0U) |
|
|
|
{ |
|
|
|
@@ -685,7 +698,6 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* 时间字段仅预览兼容;运行取频走 FreqAtPulse */ |
|
|
|
if (s_accel_plan.t_dec_ms == 0U) |
|
|
|
{ |
|
|
|
s_accel_plan.t_dec_ms = 1U; |
|
|
|
@@ -693,9 +705,7 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 进匀速:写一次 f_tgt,之后 RefreshProfile 不再周期性取频/改 ARR(防抖)。 |
|
|
|
* 注意:这不是禁止改频——ACT/EXT 打断、ChangeFreq、进减速、开下一段 |
|
|
|
* 都会离开 PH_CONST 或直接 Start/Stop,ApplyOutFreq 仍可改频。 |
|
|
|
* 进匀速:写一次 f_tgt,之后 ISR 不改 ARR(复用缓存)。 |
|
|
|
*/ |
|
|
|
static void PlsrRunControlEnterConstHold(uint8_t do_start) |
|
|
|
{ |
|
|
|
@@ -706,9 +716,25 @@ static void PlsrRunControlEnterConstHold(uint8_t do_start) |
|
|
|
f_hold = 1U; |
|
|
|
} |
|
|
|
PlsrRunControlEnterPhase(PH_CONST, f_hold); |
|
|
|
PlsrAccelPulseRtBeginConst(&s_pulse_rt, &s_accel_plan); |
|
|
|
PlsrPulseDriverClearPending(); |
|
|
|
PlsrRunControlApplyOutFreq(f_hold, do_start); |
|
|
|
} |
|
|
|
|
|
|
|
static void PlsrRunControlEnterConstHoldIsr(void) |
|
|
|
{ |
|
|
|
uint32_t f_hold = s_accel_plan.f_tgt; |
|
|
|
|
|
|
|
if (f_hold < 1U) |
|
|
|
{ |
|
|
|
f_hold = 1U; |
|
|
|
} |
|
|
|
PlsrRunControlEnterPhase(PH_CONST, f_hold); |
|
|
|
PlsrAccelPulseRtBeginConst(&s_pulse_rt, &s_accel_plan); |
|
|
|
PlsrPulseDriverClearPending(); |
|
|
|
PlsrRunControlApplyOutFreqIsr(f_hold); |
|
|
|
} |
|
|
|
|
|
|
|
static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
{ |
|
|
|
uint32_t next; |
|
|
|
@@ -722,21 +748,13 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
} |
|
|
|
remain = PlsrRunControlRemainPulses(); |
|
|
|
|
|
|
|
/* |
|
|
|
* 匀速 → 减速:只看剩余脉冲,不反复算频。 |
|
|
|
*/ |
|
|
|
if ((s_phase == PH_CONST) && |
|
|
|
(PlsrRunControlHasDecel() != 0U) && |
|
|
|
(remain <= s_accel_plan.dec_n)) |
|
|
|
{ |
|
|
|
PlsrRunControlEnterPhase(PH_DECEL, s_accel_plan.f_tgt); |
|
|
|
PlsrRunControlEnterDecel(s_accel_plan.f_tgt, remain); |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* 匀速保持:跳过周期性 FreqAtPulse(防顶频抖动)。 |
|
|
|
* 仍允许:do_start / 停表后重开 写一次;打断切段走 BeginSeg/PlanSeg |
|
|
|
* 会改 s_phase,不再走本分支。 |
|
|
|
*/ |
|
|
|
if (s_phase == PH_CONST) |
|
|
|
{ |
|
|
|
if ((do_start != 0U) || (s_pwm_on == 0U)) |
|
|
|
@@ -746,18 +764,15 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* 加速 / 减速:按脉冲域算下一频率 */ |
|
|
|
next = PlsrAccelCurveFreqAtPulse(&s_accel_plan, done_n); |
|
|
|
if (next < 1U) |
|
|
|
{ |
|
|
|
next = 1U; |
|
|
|
} |
|
|
|
s_pulse_rt.f = next; |
|
|
|
|
|
|
|
if (s_phase == PH_APPROACH) |
|
|
|
{ |
|
|
|
/* |
|
|
|
* 加速结束:脉冲用完或频率已到峰值 → 匀速保持(或直接进减速)。 |
|
|
|
*/ |
|
|
|
if ((s_accel_plan.acc_n == 0U) || |
|
|
|
(done_n >= s_accel_plan.acc_n) || |
|
|
|
((s_accel_plan.f_tgt >= s_accel_plan.f_cur) && |
|
|
|
@@ -769,7 +784,7 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
if ((PlsrRunControlHasDecel() != 0U) && |
|
|
|
(remain <= s_accel_plan.dec_n)) |
|
|
|
{ |
|
|
|
PlsrRunControlEnterPhase(PH_DECEL, next); |
|
|
|
PlsrRunControlEnterDecel(next, remain); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
@@ -882,7 +897,7 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* 保持 AccelCurvePlan 算出的脉冲预算;运行时 FreqAtPulse 按 s_done 取频。 |
|
|
|
* 保持 AccelCurvePlan 算出的脉冲预算;运行时逐拍 PulseRtStep。 |
|
|
|
*/ |
|
|
|
/* |
|
|
|
* 纯减速段:已在目标速(或更高)且整段预算不超过 dec_n。 |
|
|
|
@@ -898,12 +913,13 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
|
else if (f_start == s_accel_plan.f_tgt) |
|
|
|
{ |
|
|
|
PlsrRunControlEnterPhase(PH_CONST, f_start); |
|
|
|
PlsrAccelPulseRtBeginConst(&s_pulse_rt, &s_accel_plan); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
PlsrRunControlEnterPhase(PH_APPROACH, f_start); |
|
|
|
PlsrAccelPulseRtBeginAcc(&s_pulse_rt, &s_accel_plan); |
|
|
|
} |
|
|
|
s_profile_dirty = 1U; |
|
|
|
} |
|
|
|
|
|
|
|
static void PlsrRunControlFinishAll(void) |
|
|
|
@@ -918,7 +934,6 @@ static void PlsrRunControlFinishAll(void) |
|
|
|
s_follow_cont = 0U; |
|
|
|
s_chain_valid = 0U; |
|
|
|
s_chain_freq = 0U; |
|
|
|
s_profile_dirty = 0U; |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
@@ -1013,7 +1028,6 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0) |
|
|
|
if (s_follow_cont != 0U) |
|
|
|
{ |
|
|
|
PlsrPulseDriverClearOnePulseStop(); |
|
|
|
s_profile_dirty = 0U; |
|
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
|
s_state = RC_RUN; |
|
|
|
s_follow_cont = 0U; |
|
|
|
@@ -1046,7 +1060,6 @@ void PlsrRunControlInit(void) |
|
|
|
s_phase = PH_CONST; |
|
|
|
s_approach_from = 0U; |
|
|
|
s_decel_from = 0U; |
|
|
|
s_profile_dirty = 0U; |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
@@ -1100,7 +1113,6 @@ void PlsrRunControlStop(void) |
|
|
|
s_follow_cont = 0U; |
|
|
|
s_chain_valid = 0U; |
|
|
|
s_chain_freq = 0U; |
|
|
|
s_profile_dirty = 0U; |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
@@ -1134,7 +1146,6 @@ uint8_t PlsrRunControlChangeFreq(uint32_t new_tgt_hz) |
|
|
|
s_run_accel_ms, s_run_decel_ms); |
|
|
|
s_target = (int32_t)remain; |
|
|
|
s_done = 0; |
|
|
|
s_profile_dirty = 0U; |
|
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
|
return 1U; |
|
|
|
} |
|
|
|
@@ -1168,7 +1179,6 @@ void PlsrRunControlTickMs(void) |
|
|
|
if (PlsrRunControlOsTimeReached(s_dir_deadline) != 0U) |
|
|
|
{ |
|
|
|
s_state = RC_RUN; |
|
|
|
s_profile_dirty = 0U; |
|
|
|
PlsrRunControlRefreshProfile(1U); |
|
|
|
PlsrRunControlArmActExtOnPulseStart(); |
|
|
|
} |
|
|
|
@@ -1177,23 +1187,8 @@ void PlsrRunControlTickMs(void) |
|
|
|
|
|
|
|
if (s_state == RC_RUN) |
|
|
|
{ |
|
|
|
/* |
|
|
|
* 仅加/减速(或匀速刚到进减速点)才改频。 |
|
|
|
* 匀速锁定期间 dirty 不会置位,避免顶频反复写 ARR。 |
|
|
|
*/ |
|
|
|
if ((s_profile_dirty != 0U) && (s_act_cut_pending == 0U)) |
|
|
|
{ |
|
|
|
s_profile_dirty = 0U; |
|
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
|
} |
|
|
|
else if ((s_phase == PH_CONST) && |
|
|
|
(PlsrRunControlHasDecel() != 0U) && |
|
|
|
(s_act_cut_pending == 0U) && |
|
|
|
(PlsrRunControlRemainPulses() <= s_accel_plan.dec_n)) |
|
|
|
{ |
|
|
|
/* 任务侧兜底:进减速 */ |
|
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
|
} |
|
|
|
/* ISR 极少换 PSC 时挂起的改频 */ |
|
|
|
PlsrPulseDriverApplyPending(); |
|
|
|
|
|
|
|
seg = PlsrParamGetSeg(s_cur_seg); |
|
|
|
|
|
|
|
@@ -1267,10 +1262,11 @@ void PlsrRunControlOn1ms(void) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** 脉冲 UPDATE:计脉冲;仅加/减速置 dirty(匀速不改频) */ |
|
|
|
/** 脉冲 UPDATE:计脉冲 + 逐拍改频(匀速复用 ARR) */ |
|
|
|
void PlsrRunControlOnPulseIsr(void) |
|
|
|
{ |
|
|
|
uint32_t remain; |
|
|
|
uint32_t next; |
|
|
|
|
|
|
|
if (s_state != RC_RUN) |
|
|
|
{ |
|
|
|
@@ -1287,30 +1283,8 @@ void PlsrRunControlOnPulseIsr(void) |
|
|
|
s_acc_pulse--; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* 匀速:不置 dirty,定时器 ARR 保持不动。 |
|
|
|
* 仅当剩余脉冲进入减速预算时置位,让任务切到 DECEL。 |
|
|
|
*/ |
|
|
|
if (s_phase == PH_CONST) |
|
|
|
{ |
|
|
|
if (PlsrRunControlHasDecel() != 0U) |
|
|
|
{ |
|
|
|
remain = PlsrRunControlRemainPulses(); |
|
|
|
if (remain <= s_accel_plan.dec_n) |
|
|
|
{ |
|
|
|
s_profile_dirty = 1U; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
s_profile_dirty = 1U; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* ACT 到期切段只在脉冲边界执行,避免半个 PWM 周期改段。 |
|
|
|
* 同向衔接:不停表,任务里用当前频率规划下一段(丢掉本段剩余)。 |
|
|
|
* 停表会把 pwm_on 清掉,Resolve 若再要求 pwm_on 就会误走起跳。 |
|
|
|
*/ |
|
|
|
if (s_act_cut_pending != 0U) |
|
|
|
{ |
|
|
|
@@ -1327,6 +1301,58 @@ void PlsrRunControlOnPulseIsr(void) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
remain = PlsrRunControlRemainPulses(); |
|
|
|
|
|
|
|
if (s_phase == PH_CONST) |
|
|
|
{ |
|
|
|
/* |
|
|
|
* 匀速热路径:频率未变 → 不写寄存器。 |
|
|
|
* 制动区:remain <= dec_n(规划好的距离)→ 进减速。 |
|
|
|
*/ |
|
|
|
if ((PlsrRunControlHasDecel() != 0U) && |
|
|
|
(remain <= s_accel_plan.dec_n)) |
|
|
|
{ |
|
|
|
PlsrRunControlEnterDecel(s_accel_plan.f_tgt, remain); |
|
|
|
next = PlsrAccelPulseRtStep(&s_pulse_rt); |
|
|
|
PlsrRunControlApplyOutFreqIsr(next); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (s_phase == PH_APPROACH) |
|
|
|
{ |
|
|
|
next = PlsrAccelPulseRtStep(&s_pulse_rt); |
|
|
|
|
|
|
|
if ((s_accel_plan.acc_n == 0U) || |
|
|
|
(s_pulse_rt.active == 0U) || |
|
|
|
(s_pulse_rt.n >= s_accel_plan.acc_n) || |
|
|
|
((s_accel_plan.f_tgt >= s_accel_plan.f_cur) && |
|
|
|
(next >= s_accel_plan.f_tgt)) || |
|
|
|
((s_accel_plan.f_tgt < s_accel_plan.f_cur) && |
|
|
|
(next <= s_accel_plan.f_tgt))) |
|
|
|
{ |
|
|
|
next = s_accel_plan.f_tgt; |
|
|
|
if ((PlsrRunControlHasDecel() != 0U) && |
|
|
|
(remain <= s_accel_plan.dec_n)) |
|
|
|
{ |
|
|
|
PlsrRunControlEnterDecel(next, remain); |
|
|
|
next = PlsrAccelPulseRtStep(&s_pulse_rt); |
|
|
|
PlsrRunControlApplyOutFreqIsr(next); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
PlsrRunControlEnterConstHoldIsr(); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
PlsrRunControlApplyOutFreqIsr(next); |
|
|
|
} |
|
|
|
} |
|
|
|
else /* PH_DECEL */ |
|
|
|
{ |
|
|
|
next = PlsrAccelPulseRtStep(&s_pulse_rt); |
|
|
|
PlsrRunControlApplyOutFreqIsr(next); |
|
|
|
} |
|
|
|
|
|
|
|
if (s_done >= (s_target - 1)) |
|
|
|
{ |
|
|
|
if (PlsrRunControlWillFollowKeep(s_cur_seg) == 0U) |
|
|
|
|