|
|
|
@@ -60,6 +60,8 @@ static uint16_t s_act_time_ms; /* 本段 ACT 时长(出脉冲后计) */ |
|
|
|
static uint32_t s_act_arm_ms; /* 武装时刻的 TIM3 s_ms,与改频 elapsed 脱钩 */ |
|
|
|
static volatile uint8_t s_act_armed; |
|
|
|
static volatile uint8_t s_act_expire_req; /* TIM3 置位,任务里切段(避免 ISR 里 PlanSeg) */ |
|
|
|
static volatile uint8_t s_act_cut_pending; /* ACT 到期,等待当前脉冲 UPDATE 边界 */ |
|
|
|
static volatile uint8_t s_act_handoff_keep; /* 边界停表后,下一段仍从当前频率衔接 */ |
|
|
|
static volatile uint8_t s_wait_expire_req; /* WAIT 时间到:ISR 只置位 */ |
|
|
|
static uint8_t s_wait_is_signal; /* RC_WAIT_COND:1=等 WAIT 沿,0=等时间 */ |
|
|
|
|
|
|
|
@@ -77,6 +79,7 @@ static uint8_t s_pwm_on; |
|
|
|
/* 本段由策略层解析后的加减速时间(段内只用这两份,不再读 wait) */ |
|
|
|
static uint16_t s_run_accel_ms; |
|
|
|
static uint16_t s_run_decel_ms; |
|
|
|
static uint8_t s_orig_end_zero; /* 原始止速为 0(起跳频率已替代 plan.f_end) */ |
|
|
|
|
|
|
|
/** 策略层交给段处理的接口参数 */ |
|
|
|
typedef struct { |
|
|
|
@@ -103,7 +106,6 @@ static uint16_t PlsrRunControlWaitTimeMs(const PlsrSeg_t *seg); |
|
|
|
static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
|
uint32_t f_tgt, uint32_t f_end, |
|
|
|
uint16_t accel_ms, uint16_t decel_ms); |
|
|
|
static void PlsrRunControlApplyActTimeCap(uint16_t act_ms); |
|
|
|
static uint32_t PlsrRunControlClampSpeed(uint32_t spd); |
|
|
|
static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz, |
|
|
|
uint32_t default_spd, |
|
|
|
@@ -124,6 +126,8 @@ static void PlsrRunControlArmActExtOnPulseStart(void) |
|
|
|
} |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
s_act_handoff_keep = 0U; |
|
|
|
s_wait_expire_req = 0U; |
|
|
|
if (seg->wait_type == PLSR_WAIT_ACT) |
|
|
|
{ |
|
|
|
@@ -142,6 +146,8 @@ static void PlsrRunControlCutSegToNext(void) |
|
|
|
s_state = RC_IDLE; |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
s_act_handoff_keep = 0U; |
|
|
|
s_wait_expire_req = 0U; |
|
|
|
PlsrPulseDriverStop(); |
|
|
|
s_follow_cont = 0U; |
|
|
|
@@ -176,7 +182,9 @@ static void PlsrRunControlActExpire(void) |
|
|
|
|
|
|
|
next0 = PlsrPathPlanResolveAfterSeg(s_cur_seg); |
|
|
|
keep = 0U; |
|
|
|
if ((next0 >= 0) && (s_pwm_on != 0U) && (s_cur_freq >= 1U) && |
|
|
|
if ((next0 >= 0) && |
|
|
|
((s_pwm_on != 0U) || (s_act_handoff_keep != 0U)) && |
|
|
|
(s_cur_freq >= 1U) && |
|
|
|
(PlsrPathPlanIsForward((uint16_t)next0, s_acc_pulse) == s_forward)) |
|
|
|
{ |
|
|
|
keep = 1U; |
|
|
|
@@ -200,6 +208,8 @@ static void PlsrRunControlActExpire(void) |
|
|
|
s_chain_freq = 0U; |
|
|
|
} |
|
|
|
|
|
|
|
s_act_handoff_keep = 0U; |
|
|
|
|
|
|
|
PlsrRunControlGotoNextOrFinish(s_cur_seg); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -317,7 +327,7 @@ static void PlsrRunControlAfterSegDone(void) |
|
|
|
if (cfg->send_mode == PLSR_SEND_COMPLETE) |
|
|
|
{ |
|
|
|
/* 段正常结束:下一段起速 = 本段止速 f_end,不能用峰值 s_cur_freq */ |
|
|
|
s_chain_freq = s_accel_plan.f_end; |
|
|
|
s_chain_freq = (s_orig_end_zero != 0U) ? 0U : s_accel_plan.f_end; |
|
|
|
s_chain_valid = 1U; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -393,7 +403,7 @@ static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
|
* ---------- 终止频率:仅由发送模式 + 是否有下一段决定 ---------- |
|
|
|
* 完成方式 / 真末段:公共止速 |
|
|
|
* 后续方式非末段:下一段目标(无缝衔接) |
|
|
|
* ACT 不在这里改 f_end:先按梯形算出加/匀/减时间,再 ApplyActTimeCap。 |
|
|
|
* ACT 只由运行控制层管理,不改变本段曲线的 f_end 或阶段规划。 |
|
|
|
*/ |
|
|
|
(void)f_tgt; |
|
|
|
next0 = PlsrPathPlanNextSeg(seg_0); |
|
|
|
@@ -609,7 +619,7 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
|
* (拉长会在尾部堆 1Hz 空耗)。 |
|
|
|
*/ |
|
|
|
if ((old_t_dec > 0U) && (old_dec_n > 0U) && |
|
|
|
((remain_pulses == old_dec_n) || (f_end == 0U))) |
|
|
|
((remain_pulses == old_dec_n) || (s_orig_end_zero != 0U))) |
|
|
|
{ |
|
|
|
s_accel_plan.t_dec_ms = old_t_dec; |
|
|
|
return; |
|
|
|
@@ -646,7 +656,7 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (f_end == 0U) |
|
|
|
if (s_orig_end_zero != 0U) |
|
|
|
{ |
|
|
|
s_accel_plan.t_dec_ms = (t_slope > 0U) ? t_slope : |
|
|
|
((old_t_dec > 0U) ? old_t_dec : 1U); |
|
|
|
@@ -696,10 +706,10 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
next = PlsrAccelCurveFreqAtSegTime(&s_accel_plan, s_seg_elapsed_ms); |
|
|
|
if (next < 1U) |
|
|
|
{ |
|
|
|
if ((s_accel_plan.f_end == 0U) && (s_seg_elapsed_ms > 0U)) |
|
|
|
if ((s_orig_end_zero != 0U) && (s_seg_elapsed_ms > 0U)) |
|
|
|
{ |
|
|
|
/* |
|
|
|
* 时间轴已落到止速 0。剩余脉冲仍要发出并计数(ACT※4: |
|
|
|
* 原始止速为 0,时间轴走完。剩余脉冲仍要发出并计数(ACT※4: |
|
|
|
* 三阶段走完后等时间,不能把 s_target 截掉导致计数丢失)。 |
|
|
|
*/ |
|
|
|
if (s_done < s_target) |
|
|
|
@@ -734,6 +744,7 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
|
/* 段内只吃传入端点与加减速时间,不感知 wait */ |
|
|
|
s_run_accel_ms = accel_ms; |
|
|
|
s_run_decel_ms = decel_ms; |
|
|
|
s_orig_end_zero = (f_end == 0U) ? 1U : 0U; |
|
|
|
|
|
|
|
/* |
|
|
|
* 曲线估 acc_n / dec_n,const_n = total − acc − dec。 |
|
|
|
@@ -843,41 +854,6 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按 ACT 时间裁剪本段时间轴(规划已含加速/匀速/减速): |
|
|
|
* - T_acc > ACT → 加速未到目标频就被打断 |
|
|
|
* - T_acc+T_const > ACT → 匀速期内打断,不进入减速 |
|
|
|
* - T_acc+T_const < ACT < 三段总长 → 进入减速,可能被中途打断 |
|
|
|
* - ACT ≥ 加速+匀速+减速 → 三阶段走完(含减速到止速),脉冲发完后等 ACT(※4) |
|
|
|
*/ |
|
|
|
static void PlsrRunControlApplyActTimeCap(uint16_t act_ms) |
|
|
|
{ |
|
|
|
uint32_t t_act; |
|
|
|
uint32_t t_acc; |
|
|
|
uint32_t t_const_end; |
|
|
|
uint32_t t_wave; |
|
|
|
|
|
|
|
t_act = (act_ms == 0U) ? 1U : (uint32_t)act_ms; |
|
|
|
t_acc = s_accel_plan.t_acc_ms; |
|
|
|
t_const_end = s_accel_plan.t_decel_start_ms; |
|
|
|
if (t_const_end < t_acc) |
|
|
|
{ |
|
|
|
t_const_end = t_acc; |
|
|
|
} |
|
|
|
t_wave = t_const_end + s_accel_plan.t_dec_ms; |
|
|
|
|
|
|
|
if ((t_act >= t_wave) || (t_act > t_const_end)) |
|
|
|
{ |
|
|
|
/* 进入减速,或 ACT 比三段总时间还长:保留减速规划 */ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* 加速中途或匀速期内就会切段:时间轴上不再走减速 */ |
|
|
|
s_accel_plan.t_dec_ms = 0U; |
|
|
|
s_accel_plan.dec_n = 0U; |
|
|
|
s_accel_plan.f_end = s_accel_plan.f_tgt; |
|
|
|
} |
|
|
|
|
|
|
|
static void PlsrRunControlFinishAll(void) |
|
|
|
{ |
|
|
|
PlsrPulseDriverStop(); |
|
|
|
@@ -892,6 +868,8 @@ static void PlsrRunControlFinishAll(void) |
|
|
|
s_chain_freq = 0U; |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
s_act_handoff_keep = 0U; |
|
|
|
s_wait_expire_req = 0U; |
|
|
|
s_act_time_ms = 0U; |
|
|
|
s_act_arm_ms = 0U; |
|
|
|
@@ -970,11 +948,6 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0) |
|
|
|
total = (uint32_t)s_target; |
|
|
|
PlsrRunControlPlanSeg(total, io.f_from, f_tgt, io.f_end, |
|
|
|
io.accel_ms, io.decel_ms); |
|
|
|
if (seg->wait_type == PLSR_WAIT_ACT) |
|
|
|
{ |
|
|
|
PlsrRunControlApplyActTimeCap(PlsrRunControlActTimeMs(seg)); |
|
|
|
} |
|
|
|
|
|
|
|
s_done = 0; |
|
|
|
s_busy = 1U; |
|
|
|
|
|
|
|
@@ -1017,12 +990,15 @@ void PlsrRunControlInit(void) |
|
|
|
s_chain_valid = 0U; |
|
|
|
s_run_accel_ms = 0U; |
|
|
|
s_run_decel_ms = 0U; |
|
|
|
s_orig_end_zero = 0U; |
|
|
|
s_phase = PH_CONST; |
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
|
s_approach_from = 0U; |
|
|
|
s_decel_from = 0U; |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
s_act_handoff_keep = 0U; |
|
|
|
s_wait_expire_req = 0U; |
|
|
|
s_act_time_ms = 0U; |
|
|
|
s_act_arm_ms = 0U; |
|
|
|
@@ -1074,6 +1050,8 @@ void PlsrRunControlStop(void) |
|
|
|
s_chain_freq = 0U; |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 0U; |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
s_act_handoff_keep = 0U; |
|
|
|
s_wait_expire_req = 0U; |
|
|
|
s_act_time_ms = 0U; |
|
|
|
s_act_arm_ms = 0U; |
|
|
|
@@ -1101,13 +1079,6 @@ uint8_t PlsrRunControlChangeFreq(uint32_t new_tgt_hz) |
|
|
|
f_end = s_accel_plan.f_end; |
|
|
|
PlsrRunControlPlanSeg(remain, s_cur_freq, new_tgt_hz, f_end, |
|
|
|
s_run_accel_ms, s_run_decel_ms); |
|
|
|
if (PlsrParamGetSeg(s_cur_seg)->wait_type == PLSR_WAIT_ACT) |
|
|
|
{ |
|
|
|
uint32_t used = PlsrSignalIoGetMs() - s_act_arm_ms; |
|
|
|
uint16_t left = (used < (uint32_t)s_act_time_ms) ? |
|
|
|
(uint16_t)((uint32_t)s_act_time_ms - used) : 1U; |
|
|
|
PlsrRunControlApplyActTimeCap(left); |
|
|
|
} |
|
|
|
s_target = (int32_t)remain; |
|
|
|
s_done = 0; |
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
|
@@ -1123,7 +1094,7 @@ void PlsrRunControlTickMs(void) |
|
|
|
if (s_act_expire_req != 0U) |
|
|
|
{ |
|
|
|
s_act_expire_req = 0U; |
|
|
|
if (s_state == RC_RUN) |
|
|
|
if ((s_state == RC_RUN) || (s_act_handoff_keep != 0U)) |
|
|
|
{ |
|
|
|
PlsrRunControlActExpire(); |
|
|
|
} |
|
|
|
@@ -1208,29 +1179,25 @@ void PlsrRunControlOn1ms(void) |
|
|
|
s_seg_elapsed_ms++; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* ACT 到点:若加/匀/减三阶段已经走完,不要按当前频率切段, |
|
|
|
* 剩余脉冲继续发完,由 AfterSegDone ※4 停表等到点。 |
|
|
|
*/ |
|
|
|
if ((s_act_armed != 0U) && |
|
|
|
(PlsrSignalIoMsReached(s_act_arm_ms + (uint32_t)s_act_time_ms) != 0U)) |
|
|
|
{ |
|
|
|
uint32_t t_wave; |
|
|
|
/* |
|
|
|
* ACT 是运动控制条件,不参与曲线规划:加速、匀速、减速 |
|
|
|
* 任一阶段到期都在当前脉冲 UPDATE 边界切段。这样不会在 |
|
|
|
* 一个 PWM 周期中间改段,也不会把边界脉冲计到下一段。 |
|
|
|
*/ |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_cut_pending = 1U; |
|
|
|
} |
|
|
|
|
|
|
|
t_wave = s_accel_plan.t_decel_start_ms + s_accel_plan.t_dec_ms; |
|
|
|
if ((s_accel_plan.t_dec_ms >= 1U) && (s_seg_elapsed_ms >= t_wave)) |
|
|
|
{ |
|
|
|
/* 三段已结束,等脉冲 ISR 把 s_done 走到 s_target */ |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
s_act_armed = 0U; |
|
|
|
s_act_expire_req = 1U; |
|
|
|
return; |
|
|
|
} |
|
|
|
/* 保持 ACT 到期瞬间的频率,不让 1ms 曲线继续推进到下一个边界。 */ |
|
|
|
if (s_act_cut_pending != 0U) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if ((s_accel_plan.f_end == 0U) && |
|
|
|
if ((s_orig_end_zero != 0U) && |
|
|
|
(s_accel_plan.mode != PLSR_ACCEL_LINEAR) && |
|
|
|
(s_accel_plan.t_dec_ms >= 1U) && |
|
|
|
(s_seg_elapsed_ms >= |
|
|
|
@@ -1266,6 +1233,21 @@ void PlsrRunControlOnPulseIsr(void) |
|
|
|
s_acc_pulse--; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* ACT 到期后的切段只在脉冲边界执行。当前 UPDATE 已完成本段 |
|
|
|
* 最后一个完整脉冲,立即停表,任务再用当前频率衔接下一段。 |
|
|
|
*/ |
|
|
|
if (s_act_cut_pending != 0U) |
|
|
|
{ |
|
|
|
s_act_cut_pending = 0U; |
|
|
|
PlsrPulseDriverStop(); |
|
|
|
s_pwm_on = 0U; |
|
|
|
s_act_handoff_keep = 1U; |
|
|
|
s_state = RC_IDLE; |
|
|
|
s_act_expire_req = 1U; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (s_done >= s_target) |
|
|
|
{ |
|
|
|
PlsrRunControlAfterSegDone(); |
|
|
|
|