|
|
@@ -7,17 +7,16 @@ |
|
|
* 起始频率 f_from、终止频率 f_end、加速/减速时间(斜率基准) |
|
|
* 起始频率 f_from、终止频率 f_end、加速/减速时间(斜率基准) |
|
|
* 2) 段内处理:不感知 wait_type;只按 (f_from,f_tgt,f_end,accel,decel) |
|
|
* 2) 段内处理:不感知 wait_type;只按 (f_from,f_tgt,f_end,accel,decel) |
|
|
* 做加速→匀速→减速(脉冲不够则三角) |
|
|
* 做加速→匀速→减速(脉冲不够则三角) |
|
|
* 3) 波形只跟斜坡计算:算 T、按相时间取频;上拍发完才更新频率。 |
|
|
|
|
|
* ARR 预装载(ARPE)下必须提前一拍写入影寄存器,否则起速会多一拍、止速落不到末拍。 |
|
|
|
|
|
|
|
|
* 3) 曲线估加/减速脉冲;匀速=总数−加速−减速。 |
|
|
|
|
|
* 规划反向算 t_decel_start_ms;运行时 TIM3 1ms 按段内时间轴取频(直线为纯代数)。 |
|
|
|
|
|
* 起止≠0:首拍起速、末拍止速;起止=0:首末跟曲线,段末停表。 |
|
|
* |
|
|
* |
|
|
* 典型策略映射: |
|
|
* 典型策略映射: |
|
|
* - 完成方式:每段 f_end=止速(梯形/三角);WAIT 只改段后等待与下一段 f_from |
|
|
|
|
|
* - WAIT时间/信号 + 后续:本段 f_end=止速;段后等待;下一段 f_from=起速 |
|
|
|
|
|
* - 后续无缝:本段 f_end=下一段目标;不停表,f_from=当前频 |
|
|
|
|
|
|
|
|
* - 完成方式:每段 f_end=止速;WAIT 只做段后等待与下一段 f_from(清链→起速) |
|
|
|
|
|
* - 后续方式末段:f_end=止速;非末段无缝:f_end=下一段目标 |
|
|
|
|
|
* - 梯形/三角仅由 f_from/f_tgt/f_end/斜率/mode/脉冲数决定,不读 wait_type |
|
|
* |
|
|
* |
|
|
* 【硬约束】脉冲 UPDATE ISR(PlsrRunControlOnPulseIsr)内禁止重计算: |
|
|
|
|
|
* - 禁止 FitRampTimeMs / EstimatePulses 等 O(N) 或查表迭代 |
|
|
|
|
|
* - 升降速:每脉冲 O(1) 取频改 ARR;TIM3 1ms 只服务 WAIT/ACT 时钟 |
|
|
|
|
|
|
|
|
* 【运行节拍】TIM3 1ms:RefreshProfile 改频;脉冲 UPDATE ISR 只计 s_done。 |
|
|
*/ |
|
|
*/ |
|
|
#include "plsr_run_control.h" |
|
|
#include "plsr_run_control.h" |
|
|
#include "plsr_path_plan.h" |
|
|
#include "plsr_path_plan.h" |
|
|
@@ -47,7 +46,6 @@ static volatile uint8_t s_busy; |
|
|
static volatile uint8_t s_forward; |
|
|
static volatile uint8_t s_forward; |
|
|
static volatile uint16_t s_cur_seg; |
|
|
static volatile uint16_t s_cur_seg; |
|
|
static volatile uint32_t s_cur_freq; |
|
|
static volatile uint32_t s_cur_freq; |
|
|
static volatile uint32_t s_pending_freq; /* ARPE 影子频率,下一 UPDATE 才成为当前拍 */ |
|
|
|
|
|
static volatile int32_t s_done; |
|
|
static volatile int32_t s_done; |
|
|
static volatile int32_t s_target; |
|
|
static volatile int32_t s_target; |
|
|
static volatile int32_t s_acc_pulse; |
|
|
static volatile int32_t s_acc_pulse; |
|
|
@@ -60,7 +58,7 @@ static uint8_t s_wait_is_signal; /* RC_WAIT_COND:1=等 WAIT 沿,0=等时 |
|
|
|
|
|
|
|
|
static PlsrAccelPlan_t s_accel_plan; |
|
|
static PlsrAccelPlan_t s_accel_plan; |
|
|
static RunPhase_e s_phase; |
|
|
static RunPhase_e s_phase; |
|
|
static uint32_t s_phase_elapsed_us; /* 相内已过时间(按脉冲周期累加) */ |
|
|
|
|
|
|
|
|
static uint32_t s_seg_elapsed_ms; /* 段内绝对时间(TIM3 1ms 累加) */ |
|
|
static uint32_t s_approach_from; |
|
|
static uint32_t s_approach_from; |
|
|
static uint32_t s_decel_from; |
|
|
static uint32_t s_decel_from; |
|
|
static uint8_t s_follow_cont; |
|
|
static uint8_t s_follow_cont; |
|
|
@@ -156,7 +154,6 @@ static void PlsrRunControlEnterPostWaitOrNext(void) |
|
|
s_chain_valid = 0U; |
|
|
s_chain_valid = 0U; |
|
|
s_chain_freq = 0U; |
|
|
s_chain_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_pending_freq = 0U; |
|
|
|
|
|
s_wait_is_signal = 0U; |
|
|
s_wait_is_signal = 0U; |
|
|
s_wait_deadline_ms = PlsrSignalIoDeadlineFromNow(wms); |
|
|
s_wait_deadline_ms = PlsrSignalIoDeadlineFromNow(wms); |
|
|
s_state = RC_WAIT_COND; |
|
|
s_state = RC_WAIT_COND; |
|
|
@@ -170,7 +167,6 @@ static void PlsrRunControlEnterPostWaitOrNext(void) |
|
|
s_chain_valid = 0U; |
|
|
s_chain_valid = 0U; |
|
|
s_chain_freq = 0U; |
|
|
s_chain_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_pending_freq = 0U; |
|
|
|
|
|
PlsrSignalIoClearEdges(); |
|
|
PlsrSignalIoClearEdges(); |
|
|
s_wait_is_signal = 1U; |
|
|
s_wait_is_signal = 1U; |
|
|
s_state = RC_WAIT_COND; |
|
|
s_state = RC_WAIT_COND; |
|
|
@@ -207,23 +203,25 @@ static void PlsrRunControlAfterSegDone(void) |
|
|
|
|
|
|
|
|
if (cfg->send_mode == PLSR_SEND_COMPLETE) |
|
|
if (cfg->send_mode == PLSR_SEND_COMPLETE) |
|
|
{ |
|
|
{ |
|
|
s_chain_freq = s_cur_freq; |
|
|
|
|
|
|
|
|
/* 段正常结束:下一段起速 = 本段止速 f_end,不能用峰值 s_cur_freq */ |
|
|
|
|
|
s_chain_freq = s_accel_plan.f_end; |
|
|
s_chain_valid = 1U; |
|
|
s_chain_valid = 1U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (keep_pwm != 0U) |
|
|
if (keep_pwm != 0U) |
|
|
{ |
|
|
{ |
|
|
/* 后续同向且无门禁:不停表直接 BeginSeg */ |
|
|
|
|
|
|
|
|
/* 后续同向且无门禁:不停表直接 BeginSeg(仅衔接策略,不影响本段波形) */ |
|
|
s_follow_cont = 1U; |
|
|
s_follow_cont = 1U; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
PlsrPulseDriverStop(); |
|
|
PlsrPulseDriverStop(); |
|
|
|
|
|
PlsrPulseDriverClearOnePulseStop(); |
|
|
s_follow_cont = 0U; |
|
|
s_follow_cont = 0U; |
|
|
s_pwm_on = 0U; |
|
|
s_pwm_on = 0U; |
|
|
|
|
|
s_cur_freq = 0U; |
|
|
if (cfg->send_mode == PLSR_SEND_FOLLOW) |
|
|
if (cfg->send_mode == PLSR_SEND_FOLLOW) |
|
|
{ |
|
|
{ |
|
|
s_cur_freq = 0U; |
|
|
|
|
|
s_chain_valid = 0U; |
|
|
s_chain_valid = 0U; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@@ -257,7 +255,6 @@ static uint8_t PlsrRunControlBlocksFollowKeep(uint16_t cur_seg) |
|
|
static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
PlsrSegCallIo_t *io) |
|
|
PlsrSegCallIo_t *io) |
|
|
{ |
|
|
{ |
|
|
PlsrSeg_t *seg = PlsrParamGetSeg(seg_0); |
|
|
|
|
|
PlsrCfg_t *cfg = PlsrParamGetCfg(); |
|
|
PlsrCfg_t *cfg = PlsrParamGetCfg(); |
|
|
int16_t next0; |
|
|
int16_t next0; |
|
|
uint8_t end_at_stop; /* 1:本段终止频率用公共止速 */ |
|
|
uint8_t end_at_stop; /* 1:本段终止频率用公共止速 */ |
|
|
@@ -282,10 +279,10 @@ static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* ---------- 终止频率:策略层决定,段内不感知 wait ---------- |
|
|
|
|
|
* 完成方式:每段都止于公共止速(与上位机预览一致;段间靠链频/WAIT 决定下一段 f_from) |
|
|
|
|
|
* WAIT时间/信号 或 真末段:止速 |
|
|
|
|
|
* 后续无缝:下一段目标 |
|
|
|
|
|
|
|
|
* ---------- 终止频率:仅由发送模式 + 是否有下一段决定 ---------- |
|
|
|
|
|
* 完成方式 / 真末段:公共止速 |
|
|
|
|
|
* 后续方式非末段:下一段目标(无缝衔接) |
|
|
|
|
|
* 不读 wait_type——等待只在段后 EnterPostWaitOrNext 处理 |
|
|
*/ |
|
|
*/ |
|
|
next0 = PlsrPathPlanNextSeg(seg_0); |
|
|
next0 = PlsrPathPlanNextSeg(seg_0); |
|
|
end_at_stop = (next0 < 0) ? 1U : 0U; |
|
|
end_at_stop = (next0 < 0) ? 1U : 0U; |
|
|
@@ -294,11 +291,6 @@ static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
{ |
|
|
{ |
|
|
end_at_stop = 1U; |
|
|
end_at_stop = 1U; |
|
|
} |
|
|
} |
|
|
else if ((seg->wait_type == PLSR_WAIT_TIME) || |
|
|
|
|
|
(seg->wait_type == PLSR_WAIT_SIGNAL)) |
|
|
|
|
|
{ |
|
|
|
|
|
end_at_stop = 1U; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (end_at_stop != 0U) |
|
|
if (end_at_stop != 0U) |
|
|
{ |
|
|
{ |
|
|
@@ -306,7 +298,7 @@ static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
return 1U; |
|
|
return 1U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 仅后续方式 + 无缝:过渡到下一段目标 */ |
|
|
|
|
|
|
|
|
/* 后续方式 + 有下一段:过渡到下一段目标 */ |
|
|
{ |
|
|
{ |
|
|
PlsrSeg_t *nseg = PlsrParamGetSeg((uint16_t)next0); |
|
|
PlsrSeg_t *nseg = PlsrParamGetSeg((uint16_t)next0); |
|
|
if (PlsrRunControlGetSegTargetFreq(nseg->freq_hz, |
|
|
if (PlsrRunControlGetSegTargetFreq(nseg->freq_hz, |
|
|
@@ -410,28 +402,14 @@ static uint32_t PlsrRunControlClampSpeed(uint32_t spd) |
|
|
return spd; |
|
|
return spd; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** 运行输出下限:参数起/止速为 0 时曲线可算到 0,TIM 最低按 1Hz 输出 */ |
|
|
|
|
|
static uint32_t PlsrRunControlOutFreq(uint32_t f) |
|
|
|
|
|
{ |
|
|
|
|
|
if (f < 1U) |
|
|
|
|
|
{ |
|
|
|
|
|
return 1U; |
|
|
|
|
|
} |
|
|
|
|
|
return f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 运行输出:0=停表;1ms 节拍直接 SetFreq / Start */ |
|
|
static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start) |
|
|
static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start) |
|
|
{ |
|
|
{ |
|
|
/* |
|
|
|
|
|
* 运行中只写预装载(下一拍生效),避免直接改 ARR 出毛刺多计脉冲。 |
|
|
|
|
|
* s_cur_freq = 当前正在跑的拍;s_pending_freq = 已写入影子、下一拍的频率。 |
|
|
|
|
|
*/ |
|
|
|
|
|
if (profile_freq == 0U) |
|
|
if (profile_freq == 0U) |
|
|
{ |
|
|
{ |
|
|
PlsrPulseDriverStop(); |
|
|
PlsrPulseDriverStop(); |
|
|
s_pwm_on = 0U; |
|
|
s_pwm_on = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_pending_freq = 0U; |
|
|
|
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -439,19 +417,16 @@ static void PlsrRunControlApplyOutFreq(uint32_t profile_freq, uint8_t do_start) |
|
|
{ |
|
|
{ |
|
|
PlsrPulseDriverStart(profile_freq); |
|
|
PlsrPulseDriverStart(profile_freq); |
|
|
s_pwm_on = 1U; |
|
|
s_pwm_on = 1U; |
|
|
s_cur_freq = profile_freq; |
|
|
|
|
|
s_pending_freq = profile_freq; |
|
|
|
|
|
} |
|
|
} |
|
|
else |
|
|
|
|
|
|
|
|
else if (profile_freq != s_cur_freq) |
|
|
{ |
|
|
{ |
|
|
s_pending_freq = profile_freq; |
|
|
|
|
|
PlsrPulseDriverRequestFreq(profile_freq); |
|
|
|
|
|
|
|
|
PlsrPulseDriverSetFreq(profile_freq); |
|
|
} |
|
|
} |
|
|
|
|
|
s_cur_freq = profile_freq; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void PlsrRunControlEnterPhase(RunPhase_e ph, uint32_t anchor_freq) |
|
|
static void PlsrRunControlEnterPhase(RunPhase_e ph, uint32_t anchor_freq) |
|
|
{ |
|
|
{ |
|
|
/* 相时间由 ISR 累加;切入减速时在 EnterDecel 里清零 */ |
|
|
|
|
|
s_phase = ph; |
|
|
s_phase = ph; |
|
|
if (ph == PH_APPROACH) |
|
|
if (ph == PH_APPROACH) |
|
|
{ |
|
|
{ |
|
|
@@ -461,43 +436,10 @@ static void PlsrRunControlEnterPhase(RunPhase_e ph, uint32_t anchor_freq) |
|
|
{ |
|
|
{ |
|
|
s_decel_from = anchor_freq; |
|
|
s_decel_from = anchor_freq; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static uint32_t PlsrRunControlPeriodUs(uint32_t f_hz) |
|
|
|
|
|
{ |
|
|
|
|
|
if (f_hz < 1U) |
|
|
|
|
|
{ |
|
|
|
|
|
f_hz = 1U; |
|
|
|
|
|
} |
|
|
|
|
|
return (1000000UL + (f_hz / 2UL)) / f_hz; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static uint32_t PlsrRunControlFreqOnRampMs(uint32_t f0, uint32_t f1, |
|
|
|
|
|
uint32_t t_ms, uint32_t T_ms, |
|
|
|
|
|
PlsrAccelMode_e mode) |
|
|
|
|
|
{ |
|
|
|
|
|
return PlsrRunControlOutFreq( |
|
|
|
|
|
PlsrAccelCurveFreqOnRampMs(f0, f1, t_ms, T_ms, mode)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 斜坡时间短于「from 频率一拍周期」:该拍结束后相时间已越过 T, |
|
|
|
|
|
* 应直接取相终点频率。 |
|
|
|
|
|
*/ |
|
|
|
|
|
static uint8_t PlsrRunControlRampDoneInOnePulse(uint32_t from_hz, uint32_t T_ms) |
|
|
|
|
|
{ |
|
|
|
|
|
uint32_t per_ms; |
|
|
|
|
|
|
|
|
|
|
|
if (T_ms < 1U) |
|
|
|
|
|
|
|
|
else if (ph == PH_CONST) |
|
|
{ |
|
|
{ |
|
|
return 1U; |
|
|
|
|
|
} |
|
|
|
|
|
if (from_hz < 1U) |
|
|
|
|
|
{ |
|
|
|
|
|
from_hz = 1U; |
|
|
|
|
|
|
|
|
(void)anchor_freq; |
|
|
} |
|
|
} |
|
|
per_ms = (1000UL + from_hz - 1UL) / from_hz; |
|
|
|
|
|
return (T_ms <= per_ms) ? 1U : 0U; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
@@ -517,7 +459,6 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
old_t_dec = s_accel_plan.t_dec_ms; |
|
|
old_t_dec = s_accel_plan.t_dec_ms; |
|
|
|
|
|
|
|
|
PlsrRunControlEnterPhase(PH_DECEL, from_hz); |
|
|
PlsrRunControlEnterPhase(PH_DECEL, from_hz); |
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
f_end = s_accel_plan.f_end; |
|
|
f_end = s_accel_plan.f_end; |
|
|
|
|
|
|
|
|
if (remain_pulses == 0U) |
|
|
if (remain_pulses == 0U) |
|
|
@@ -536,17 +477,18 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* 规划阶段已按 dec_n 拟合过 T(含 S/正弦)且剩余脉冲仍等于规划值: |
|
|
|
|
|
* 直接沿用,避免 ISR 内 O(1) 平均公式把形状时间改歪。 |
|
|
|
|
|
* 脉冲被改频/截断等导致 remain 变化时,再走下面 O(1) 回退。 |
|
|
|
|
|
|
|
|
* 规划阶段已按斜率算好 t_dec:优先沿用,避免 ISR 内改歪形状。 |
|
|
|
|
|
* 止速=0:始终用斜率时间;时间走完即停,不按剩余脉冲把 T 拉长 |
|
|
|
|
|
* (拉长会在尾部堆 1Hz 空耗)。 |
|
|
*/ |
|
|
*/ |
|
|
if ((old_t_dec > 0U) && (old_dec_n > 0U) && (remain_pulses == old_dec_n)) |
|
|
|
|
|
|
|
|
if ((old_t_dec > 0U) && (old_dec_n > 0U) && |
|
|
|
|
|
((remain_pulses == old_dec_n) || (f_end == 0U))) |
|
|
{ |
|
|
{ |
|
|
s_accel_plan.t_dec_ms = old_t_dec; |
|
|
s_accel_plan.t_dec_ms = old_t_dec; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 参数斜率决定的理想减速时间(用本段策略解析的 accel/decel) */ |
|
|
|
|
|
|
|
|
/* 参数斜率决定的理想减速时间(本段 accel_ms/decel_ms) */ |
|
|
df = (from_hz > f_end) ? (from_hz - f_end) : (f_end - from_hz); |
|
|
df = (from_hz > f_end) ? (from_hz - f_end) : (f_end - from_hz); |
|
|
if (f_end > from_hz) |
|
|
if (f_end > from_hz) |
|
|
{ |
|
|
{ |
|
|
@@ -577,11 +519,16 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (f_end == 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
s_accel_plan.t_dec_ms = (t_slope > 0U) ? t_slope : |
|
|
|
|
|
((old_t_dec > 0U) ? old_t_dec : 1U); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* 注意:本函数会在脉冲 UPDATE ISR 里调用,禁止再跑 FitRampTimeMs/ |
|
|
|
|
|
* EstimatePulses 那种 O(N) 递推。段脉冲多时会卡死 ISR,定时器继续 |
|
|
|
|
|
* 溢出 → 示波器上最后一段多出若干脉冲(500 准、5000 多 6~7 个)。 |
|
|
|
|
|
* 这里只用 O(1) 平均公式拟合 T。 |
|
|
|
|
|
|
|
|
* 止速≠0:ISR 内禁止 FitRamp/EstimatePulses;用 O(1) 平均公式。 |
|
|
|
|
|
* 脉冲被截断导致 remain 变化时才走这里。 |
|
|
*/ |
|
|
*/ |
|
|
sum_f = from_hz + f_end; |
|
|
sum_f = from_hz + f_end; |
|
|
if (sum_f == 0U) |
|
|
if (sum_f == 0U) |
|
|
@@ -611,163 +558,45 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static uint32_t PlsrRunControlCalcOutFreq(uint32_t elapsed_us, uint32_t remain) |
|
|
|
|
|
|
|
|
static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
{ |
|
|
{ |
|
|
uint32_t next; |
|
|
uint32_t next; |
|
|
uint32_t T_ms; |
|
|
|
|
|
const PlsrAccelPlan_t *p = &s_accel_plan; |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* 止速段:剩余脉冲进入 dec_n 时切入减速(加速相也可切,避免脉冲被加速吃光)。 |
|
|
|
|
|
|
|
|
* 1ms 改频:段内统一时间轴;t_decel_start_ms 由规划反向算出, |
|
|
|
|
|
* 减速为 f_tgt→f_end 直线,自然落到止速,末拍不再强行对齐。 |
|
|
*/ |
|
|
*/ |
|
|
if ((p->dec_n > 0U) && (remain <= p->dec_n) && |
|
|
|
|
|
(p->f_end != p->f_tgt) && |
|
|
|
|
|
((s_phase == PH_CONST) || (s_phase == PH_APPROACH))) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlEnterDecel(s_cur_freq, remain); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (s_phase == PH_APPROACH) |
|
|
|
|
|
|
|
|
next = PlsrAccelCurveFreqAtSegTime(&s_accel_plan, s_seg_elapsed_ms); |
|
|
|
|
|
if (next < 1U) |
|
|
{ |
|
|
{ |
|
|
T_ms = p->t_acc_ms; |
|
|
|
|
|
if (s_approach_from == p->f_tgt) |
|
|
|
|
|
|
|
|
if ((s_accel_plan.f_cur == 0U) && (s_seg_elapsed_ms < 1U)) |
|
|
{ |
|
|
{ |
|
|
next = p->f_tgt; |
|
|
|
|
|
PlsrRunControlEnterPhase(PH_CONST, next); |
|
|
|
|
|
} |
|
|
|
|
|
else if ((T_ms < 1U) || (elapsed_us >= (T_ms * 1000UL))) |
|
|
|
|
|
{ |
|
|
|
|
|
next = p->f_tgt; |
|
|
|
|
|
PlsrRunControlEnterPhase(PH_CONST, next); |
|
|
|
|
|
if ((p->dec_n > 0U) && (remain <= p->dec_n)) |
|
|
|
|
|
|
|
|
next = PlsrAccelCurveFirstPulseFreq(s_accel_plan.f_cur, s_accel_plan.f_tgt, |
|
|
|
|
|
(s_accel_plan.t_acc_ms >= 1U) ? |
|
|
|
|
|
(s_accel_plan.t_acc_ms * 1000UL) : 1U, |
|
|
|
|
|
s_accel_plan.mode); |
|
|
|
|
|
if (next < 1U) |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlEnterDecel(next, remain); |
|
|
|
|
|
if ((remain <= 1U) || |
|
|
|
|
|
(PlsrRunControlRampDoneInOnePulse(s_decel_from, |
|
|
|
|
|
p->t_dec_ms) != 0U)) |
|
|
|
|
|
{ |
|
|
|
|
|
next = p->f_end; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
next = PlsrRunControlFreqOnRampMs(s_decel_from, p->f_end, |
|
|
|
|
|
0U, |
|
|
|
|
|
p->t_dec_ms, p->mode); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
next = 1U; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
next = PlsrRunControlFreqOnRampMs(s_approach_from, p->f_tgt, |
|
|
|
|
|
elapsed_us / 1000UL, |
|
|
|
|
|
T_ms, p->mode); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else if (s_phase == PH_DECEL) |
|
|
|
|
|
{ |
|
|
|
|
|
T_ms = p->t_dec_ms; |
|
|
|
|
|
if ((remain <= 1U) || |
|
|
|
|
|
(PlsrRunControlRampDoneInOnePulse(s_decel_from, T_ms) != 0U) || |
|
|
|
|
|
((T_ms >= 1U) && (elapsed_us >= (T_ms * 1000UL)))) |
|
|
|
|
|
{ |
|
|
|
|
|
next = p->f_end; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
|
|
|
else if (next == 0U) |
|
|
{ |
|
|
{ |
|
|
next = PlsrRunControlFreqOnRampMs(s_decel_from, p->f_end, |
|
|
|
|
|
elapsed_us / 1000UL, |
|
|
|
|
|
T_ms, p->mode); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
next = p->f_tgt; |
|
|
|
|
|
if ((p->dec_n > 0U) && (remain <= p->dec_n)) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlEnterDecel(next, remain); |
|
|
|
|
|
if ((remain <= 1U) || |
|
|
|
|
|
(PlsrRunControlRampDoneInOnePulse(s_decel_from, |
|
|
|
|
|
p->t_dec_ms) != 0U)) |
|
|
|
|
|
|
|
|
if (s_done < s_target) |
|
|
{ |
|
|
{ |
|
|
next = p->f_end; |
|
|
|
|
|
|
|
|
s_target = s_done + 1; |
|
|
} |
|
|
} |
|
|
else |
|
|
|
|
|
|
|
|
if (PlsrRunControlWillFollowKeep(s_cur_seg) == 0U) |
|
|
{ |
|
|
{ |
|
|
next = PlsrRunControlFreqOnRampMs(s_decel_from, p->f_end, |
|
|
|
|
|
0U, |
|
|
|
|
|
p->t_dec_ms, p->mode); |
|
|
|
|
|
|
|
|
PlsrPulseDriverArmOnePulseStop(); |
|
|
} |
|
|
} |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return PlsrRunControlOutFreq(next); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 开跑:现行 ARR=第1拍,影寄存器提前装第2拍。 |
|
|
|
|
|
* STM32 ARPE:UPDATE 里写的 ARR 要到再下一拍才生效;若不预装,起速会打两拍、 |
|
|
|
|
|
* 止速永远落不到最后一拍。 |
|
|
|
|
|
*/ |
|
|
|
|
|
static void PlsrRunControlStartWithPreload(void) |
|
|
|
|
|
{ |
|
|
|
|
|
uint32_t f1; |
|
|
|
|
|
uint32_t f2; |
|
|
|
|
|
uint32_t e1; |
|
|
|
|
|
uint32_t rem1; |
|
|
|
|
|
uint32_t rem2; |
|
|
|
|
|
|
|
|
|
|
|
rem1 = (uint32_t)s_target; |
|
|
|
|
|
if (rem1 < 1U) |
|
|
|
|
|
{ |
|
|
|
|
|
rem1 = 1U; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
f1 = PlsrRunControlCalcOutFreq(0U, rem1); |
|
|
|
|
|
|
|
|
|
|
|
if (s_target <= 1) |
|
|
|
|
|
|
|
|
if ((next != s_cur_freq) || (do_start != 0U) || (s_pwm_on == 0U)) |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlApplyOutFreq(f1, 1U); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
e1 = PlsrRunControlPeriodUs(f1); |
|
|
|
|
|
rem2 = (uint32_t)(s_target - 1); |
|
|
|
|
|
f2 = PlsrRunControlCalcOutFreq(e1, rem2); |
|
|
|
|
|
|
|
|
|
|
|
/* ISR 从已完成拍累加相时间,开跑时尚未完成任何拍 */ |
|
|
|
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
|
|
|
|
|
|
PlsrRunControlApplyOutFreq(f1, 1U); |
|
|
|
|
|
s_pending_freq = f2; |
|
|
|
|
|
PlsrPulseDriverRequestFreq(f2); |
|
|
|
|
|
PlsrPulseDriverApplyPending(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
|
|
{ |
|
|
|
|
|
uint32_t remain; |
|
|
|
|
|
uint32_t next; |
|
|
|
|
|
|
|
|
|
|
|
if (do_start != 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlStartWithPreload(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (s_done < s_target) |
|
|
|
|
|
{ |
|
|
|
|
|
remain = (uint32_t)(s_target - s_done); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
remain = 0U; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
next = PlsrRunControlCalcOutFreq(s_phase_elapsed_us, remain); |
|
|
|
|
|
if ((next != s_pending_freq) || (s_pwm_on == 0U)) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlApplyOutFreq(next, 0U); |
|
|
|
|
|
|
|
|
PlsrRunControlApplyOutFreq(next, do_start); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -783,6 +612,10 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
s_run_accel_ms = accel_ms; |
|
|
s_run_accel_ms = accel_ms; |
|
|
s_run_decel_ms = decel_ms; |
|
|
s_run_decel_ms = decel_ms; |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* 曲线估 acc_n / dec_n,const_n = total − acc − dec。 |
|
|
|
|
|
* 起止≠0:运行时首拍=起速、末拍=止速;起止=0:首末跟曲线,段末停表。 |
|
|
|
|
|
*/ |
|
|
PlsrAccelCurvePlan(&s_accel_plan, |
|
|
PlsrAccelCurvePlan(&s_accel_plan, |
|
|
total, |
|
|
total, |
|
|
f_from, |
|
|
f_from, |
|
|
@@ -795,12 +628,13 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
decel_ms, |
|
|
decel_ms, |
|
|
cfg->accel_mode); |
|
|
cfg->accel_mode); |
|
|
|
|
|
|
|
|
/* 本段频率范围锁 PSC,升降过程只改 ARR。 |
|
|
|
|
|
* |
|
|
|
|
|
* 注意:不要为了“起速/止速=0”把下限锁到 1Hz。 |
|
|
|
|
|
* 1Hz 会迫使 PSC 极大,目标频附近 ARR 挤成一团,加减速在示波器上变成 |
|
|
|
|
|
* 方波或“斜坡半截再直跳”。下限取 max(峰值/20, 20Hz),末了再停表到 0。 |
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* 1ms 改频模式:运行时按 TIM3 毫秒时间轴取频。 |
|
|
|
|
|
* 禁止在这里用脉冲递推模型二次拟合 T(FitRamp),否则规划与运行模型不一致, |
|
|
|
|
|
* 会出现中段拐折/扭曲、段末落不到设定 f_end。 |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/* 本段频率范围锁 PSC,升降只改 ARR;跨度过大则 LockPscRange 自动不锁 */ |
|
|
f_lo = s_accel_plan.f_tgt; |
|
|
f_lo = s_accel_plan.f_tgt; |
|
|
f_hi = s_accel_plan.f_tgt; |
|
|
f_hi = s_accel_plan.f_tgt; |
|
|
if (f_from > f_hi) |
|
|
if (f_from > f_hi) |
|
|
@@ -814,17 +648,9 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
f_lo = f_from; |
|
|
f_lo = f_from; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (s_accel_plan.f_tgt >= 1U) |
|
|
|
|
|
|
|
|
else |
|
|
{ |
|
|
{ |
|
|
f_lo = s_accel_plan.f_tgt / 20U; |
|
|
|
|
|
if (f_lo < 20U) |
|
|
|
|
|
{ |
|
|
|
|
|
f_lo = 20U; |
|
|
|
|
|
} |
|
|
|
|
|
if (f_lo > s_accel_plan.f_tgt) |
|
|
|
|
|
{ |
|
|
|
|
|
f_lo = s_accel_plan.f_tgt; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
f_lo = 1U; |
|
|
} |
|
|
} |
|
|
if (s_accel_plan.f_end > f_hi) |
|
|
if (s_accel_plan.f_end > f_hi) |
|
|
{ |
|
|
{ |
|
|
@@ -837,16 +663,11 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
f_lo = s_accel_plan.f_end; |
|
|
f_lo = s_accel_plan.f_end; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (s_accel_plan.f_tgt >= 1U) |
|
|
|
|
|
|
|
|
else |
|
|
{ |
|
|
{ |
|
|
uint32_t flo2 = s_accel_plan.f_tgt / 20U; |
|
|
|
|
|
if (flo2 < 20U) |
|
|
|
|
|
{ |
|
|
|
|
|
flo2 = 20U; |
|
|
|
|
|
} |
|
|
|
|
|
if (flo2 < f_lo) |
|
|
|
|
|
|
|
|
if (f_lo > 1U) |
|
|
{ |
|
|
{ |
|
|
f_lo = flo2; |
|
|
|
|
|
|
|
|
f_lo = 1U; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (f_lo < 1U) |
|
|
if (f_lo < 1U) |
|
|
@@ -877,22 +698,26 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
* 脉冲数由 EstimatePulses 决定;运行时按相时间取频, |
|
|
* 脉冲数由 EstimatePulses 决定;运行时按相时间取频, |
|
|
* 一拍周期盖住 T 时自然落到相终点。 |
|
|
* 一拍周期盖住 T 时自然落到相终点。 |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
/* |
|
|
|
|
|
* 纯减速段:已在目标速(或更高)且整段预算不超过 dec_n。 |
|
|
|
|
|
* 起速 < 目标速 时必须先 APPROACH(三角/profile),不能一上来 DECEL。 |
|
|
|
|
|
*/ |
|
|
if ((s_accel_plan.dec_n >= total) && |
|
|
if ((s_accel_plan.dec_n >= total) && |
|
|
(total > 0U) && |
|
|
(total > 0U) && |
|
|
(s_accel_plan.f_end != s_accel_plan.f_tgt)) |
|
|
|
|
|
|
|
|
(s_accel_plan.f_end != s_accel_plan.f_tgt) && |
|
|
|
|
|
(f_from >= s_accel_plan.f_tgt)) |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlEnterDecel(f_from, total); |
|
|
PlsrRunControlEnterDecel(f_from, total); |
|
|
} |
|
|
} |
|
|
else if (f_from == s_accel_plan.f_tgt) |
|
|
else if (f_from == s_accel_plan.f_tgt) |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlEnterPhase(PH_CONST, f_from); |
|
|
PlsrRunControlEnterPhase(PH_CONST, f_from); |
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
PlsrRunControlEnterPhase(PH_APPROACH, f_from); |
|
|
PlsrRunControlEnterPhase(PH_APPROACH, f_from); |
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void PlsrRunControlFinishAll(void) |
|
|
static void PlsrRunControlFinishAll(void) |
|
|
@@ -903,7 +728,6 @@ static void PlsrRunControlFinishAll(void) |
|
|
s_busy = 0U; |
|
|
s_busy = 0U; |
|
|
s_state = RC_IDLE; |
|
|
s_state = RC_IDLE; |
|
|
s_cur_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_pending_freq = 0U; |
|
|
|
|
|
s_pwm_on = 0U; |
|
|
s_pwm_on = 0U; |
|
|
s_follow_cont = 0U; |
|
|
s_follow_cont = 0U; |
|
|
s_chain_valid = 0U; |
|
|
s_chain_valid = 0U; |
|
|
@@ -995,14 +819,9 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0) |
|
|
|
|
|
|
|
|
if (s_follow_cont != 0U) |
|
|
if (s_follow_cont != 0U) |
|
|
{ |
|
|
{ |
|
|
uint32_t f1; |
|
|
|
|
|
|
|
|
|
|
|
PlsrPulseDriverClearOnePulseStop(); |
|
|
PlsrPulseDriverClearOnePulseStop(); |
|
|
/* PWM 仍在跑:只预装下一拍;再下一拍由 ISR look-ahead 补 */ |
|
|
|
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
f1 = PlsrRunControlCalcOutFreq(0U, (uint32_t)s_target); |
|
|
|
|
|
PlsrRunControlApplyOutFreq(f1, 0U); |
|
|
|
|
|
PlsrPulseDriverApplyPending(); |
|
|
|
|
|
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
|
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
s_state = RC_RUN; |
|
|
s_state = RC_RUN; |
|
|
s_follow_cont = 0U; |
|
|
s_follow_cont = 0U; |
|
|
PlsrRunControlArmActExtOnPulseStart(); |
|
|
PlsrRunControlArmActExtOnPulseStart(); |
|
|
@@ -1022,7 +841,6 @@ void PlsrRunControlInit(void) |
|
|
s_forward = 1U; |
|
|
s_forward = 1U; |
|
|
s_cur_seg = 0U; |
|
|
s_cur_seg = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_pending_freq = 0U; |
|
|
|
|
|
s_pwm_on = 0U; |
|
|
s_pwm_on = 0U; |
|
|
s_done = 0; |
|
|
s_done = 0; |
|
|
s_target = 0; |
|
|
s_target = 0; |
|
|
@@ -1033,7 +851,7 @@ void PlsrRunControlInit(void) |
|
|
s_run_accel_ms = 0U; |
|
|
s_run_accel_ms = 0U; |
|
|
s_run_decel_ms = 0U; |
|
|
s_run_decel_ms = 0U; |
|
|
s_phase = PH_CONST; |
|
|
s_phase = PH_CONST; |
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
s_approach_from = 0U; |
|
|
s_approach_from = 0U; |
|
|
s_decel_from = 0U; |
|
|
s_decel_from = 0U; |
|
|
s_act_armed = 0U; |
|
|
s_act_armed = 0U; |
|
|
@@ -1079,7 +897,6 @@ void PlsrRunControlStop(void) |
|
|
s_busy = 0U; |
|
|
s_busy = 0U; |
|
|
s_state = RC_IDLE; |
|
|
s_state = RC_IDLE; |
|
|
s_cur_freq = 0U; |
|
|
s_cur_freq = 0U; |
|
|
s_pending_freq = 0U; |
|
|
|
|
|
s_pwm_on = 0U; |
|
|
s_pwm_on = 0U; |
|
|
s_follow_cont = 0U; |
|
|
s_follow_cont = 0U; |
|
|
s_chain_valid = 0U; |
|
|
s_chain_valid = 0U; |
|
|
@@ -1111,6 +928,7 @@ uint8_t PlsrRunControlChangeFreq(uint32_t new_tgt_hz) |
|
|
s_run_accel_ms, s_run_decel_ms); |
|
|
s_run_accel_ms, s_run_decel_ms); |
|
|
s_target = (int32_t)remain; |
|
|
s_target = (int32_t)remain; |
|
|
s_done = 0; |
|
|
s_done = 0; |
|
|
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
return 1U; |
|
|
return 1U; |
|
|
} |
|
|
} |
|
|
@@ -1124,7 +942,8 @@ void PlsrRunControlTickMs(void) |
|
|
if (PlsrRunControlOsTimeReached(s_dir_deadline) != 0U) |
|
|
if (PlsrRunControlOsTimeReached(s_dir_deadline) != 0U) |
|
|
{ |
|
|
{ |
|
|
s_state = RC_RUN; |
|
|
s_state = RC_RUN; |
|
|
PlsrRunControlStartWithPreload(); |
|
|
|
|
|
|
|
|
s_seg_elapsed_ms = 0U; |
|
|
|
|
|
PlsrRunControlRefreshProfile(1U); |
|
|
PlsrRunControlArmActExtOnPulseStart(); |
|
|
PlsrRunControlArmActExtOnPulseStart(); |
|
|
} |
|
|
} |
|
|
return; |
|
|
return; |
|
|
@@ -1132,7 +951,7 @@ void PlsrRunControlTickMs(void) |
|
|
|
|
|
|
|
|
if (s_state == RC_RUN) |
|
|
if (s_state == RC_RUN) |
|
|
{ |
|
|
{ |
|
|
/* 加减速频率改由 PlsrRunControlOn1ms(TIM3) 更新;此处只处理 ACT/EXT */ |
|
|
|
|
|
|
|
|
/* 波形改频在 TIM3 On1ms;此处只处理 ACT/EXT */ |
|
|
seg = PlsrParamGetSeg(s_cur_seg); |
|
|
seg = PlsrParamGetSeg(s_cur_seg); |
|
|
|
|
|
|
|
|
if ((s_act_armed != 0U) && |
|
|
if ((s_act_armed != 0U) && |
|
|
@@ -1171,31 +990,48 @@ void PlsrRunControlTickMs(void) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* TIM3 1ms:仅推进 WAIT/ACT 用的毫秒钟(在 signal_io 里 ++s_ms)。 |
|
|
|
|
|
* 升降速改频改回每脉冲,避免低频下 1ms 改频把斜坡拉歪、减速只剩 1 拍。 |
|
|
|
|
|
|
|
|
* TIM3 1ms:段内时间累加 + 按时间轴 RefreshProfile 改频。 |
|
|
*/ |
|
|
*/ |
|
|
void PlsrRunControlOn1ms(void) |
|
|
void PlsrRunControlOn1ms(void) |
|
|
{ |
|
|
{ |
|
|
/* 有意留空:段波形不在 1ms 里改 */ |
|
|
|
|
|
|
|
|
if (s_state != RC_RUN) |
|
|
|
|
|
{ |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (s_seg_elapsed_ms < 0xFFFFFFFFUL) |
|
|
|
|
|
{ |
|
|
|
|
|
s_seg_elapsed_ms++; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((s_accel_plan.f_end == 0U) && |
|
|
|
|
|
(s_accel_plan.mode != PLSR_ACCEL_LINEAR) && |
|
|
|
|
|
(s_accel_plan.t_dec_ms >= 1U) && |
|
|
|
|
|
(s_seg_elapsed_ms >= |
|
|
|
|
|
(s_accel_plan.t_decel_start_ms + s_accel_plan.t_dec_ms))) |
|
|
|
|
|
{ |
|
|
|
|
|
if (s_done < s_target) |
|
|
|
|
|
{ |
|
|
|
|
|
s_target = s_done + 1; |
|
|
|
|
|
} |
|
|
|
|
|
if (PlsrRunControlWillFollowKeep(s_cur_seg) == 0U) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrPulseDriverArmOnePulseStop(); |
|
|
|
|
|
} |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
PlsrRunControlRefreshProfile(0U); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** 脉冲 UPDATE:只累计 s_done / s_acc_pulse,不改频 */ |
|
|
void PlsrRunControlOnPulseIsr(void) |
|
|
void PlsrRunControlOnPulseIsr(void) |
|
|
{ |
|
|
{ |
|
|
uint32_t completed_freq; |
|
|
|
|
|
uint32_t running_freq; |
|
|
|
|
|
uint32_t look_elapsed; |
|
|
|
|
|
uint32_t rem_prog; |
|
|
|
|
|
uint32_t next; |
|
|
|
|
|
uint32_t saved_elapsed; |
|
|
|
|
|
uint8_t entered_decel; |
|
|
|
|
|
|
|
|
|
|
|
if (s_state != RC_RUN) |
|
|
if (s_state != RC_RUN) |
|
|
{ |
|
|
{ |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 本拍刚结束:现行频率仍是完成拍的频率(pending 是影里给下一拍的) */ |
|
|
|
|
|
completed_freq = s_cur_freq; |
|
|
|
|
|
s_done++; |
|
|
s_done++; |
|
|
if (s_forward != 0U) |
|
|
if (s_forward != 0U) |
|
|
{ |
|
|
{ |
|
|
@@ -1212,71 +1048,13 @@ void PlsrRunControlOnPulseIsr(void) |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* 本 UPDATE 已把影寄存器装进现行 ARR:正在跑的是原 pending。 |
|
|
|
|
|
* ARPE 下此刻再写影寄存器,要到「再下一拍」才生效 → 必须 look-ahead。 |
|
|
|
|
|
*/ |
|
|
|
|
|
running_freq = s_pending_freq; |
|
|
|
|
|
s_cur_freq = running_freq; |
|
|
|
|
|
|
|
|
|
|
|
if (((s_phase == PH_APPROACH) || (s_phase == PH_DECEL)) && |
|
|
|
|
|
(completed_freq >= 1U)) |
|
|
|
|
|
{ |
|
|
|
|
|
uint32_t period_us = PlsrRunControlPeriodUs(completed_freq); |
|
|
|
|
|
if (s_phase_elapsed_us < (0xFFFFFFFFUL - period_us)) |
|
|
|
|
|
{ |
|
|
|
|
|
s_phase_elapsed_us += period_us; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
s_phase_elapsed_us = 0xFFFFFFF0UL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (s_done >= (s_target - 1)) |
|
|
if (s_done >= (s_target - 1)) |
|
|
{ |
|
|
{ |
|
|
/* 最后一拍已在跑(开跑预装或上次 look-ahead 已写好),不再改频 */ |
|
|
|
|
|
if (PlsrRunControlWillFollowKeep(s_cur_seg) == 0U) |
|
|
if (PlsrRunControlWillFollowKeep(s_cur_seg) == 0U) |
|
|
{ |
|
|
{ |
|
|
PlsrPulseDriverArmOnePulseStop(); |
|
|
PlsrPulseDriverArmOnePulseStop(); |
|
|
} |
|
|
} |
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 预装「再下一拍」= 第 (s_done+2) 拍 */ |
|
|
|
|
|
look_elapsed = s_phase_elapsed_us; |
|
|
|
|
|
if ((s_phase == PH_APPROACH) || (s_phase == PH_DECEL)) |
|
|
|
|
|
{ |
|
|
|
|
|
uint32_t add = PlsrRunControlPeriodUs(running_freq); |
|
|
|
|
|
if (look_elapsed < (0xFFFFFFFFUL - add)) |
|
|
|
|
|
{ |
|
|
|
|
|
look_elapsed += add; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
look_elapsed = 0xFFFFFFF0UL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
rem_prog = (uint32_t)(s_target - s_done - 1); |
|
|
|
|
|
|
|
|
|
|
|
saved_elapsed = s_phase_elapsed_us; |
|
|
|
|
|
entered_decel = (s_phase == PH_DECEL) ? 1U : 0U; |
|
|
|
|
|
next = PlsrRunControlCalcOutFreq(look_elapsed, rem_prog); |
|
|
|
|
|
if ((entered_decel == 0U) && (s_phase == PH_DECEL)) |
|
|
|
|
|
{ |
|
|
|
|
|
/* 本次 look-ahead 刚切入减速:相时间从 0 计 */ |
|
|
|
|
|
s_phase_elapsed_us = 0U; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
s_phase_elapsed_us = saved_elapsed; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((next != s_pending_freq) || (s_pwm_on == 0U)) |
|
|
|
|
|
{ |
|
|
|
|
|
PlsrRunControlApplyOutFreq(next, 0U); |
|
|
|
|
|
} |
|
|
} |
|
|
PlsrPulseDriverApplyPending(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uint8_t PlsrRunControlIsBusy(void) |
|
|
uint8_t PlsrRunControlIsBusy(void) |
|
|
|