|
|
|
@@ -77,6 +77,11 @@ static uint8_t s_pwm_on; |
|
|
|
static uint16_t s_run_accel_ms; |
|
|
|
static uint16_t s_run_decel_ms; |
|
|
|
|
|
|
|
/* 规划锁定的加/减速脉冲预算(EnterDecel 会改写 plan.dec_n,故另存) */ |
|
|
|
static uint32_t s_plan_acc_n; |
|
|
|
static uint32_t s_plan_dec_n; |
|
|
|
static uint32_t s_decel_budget; /* 进入减速时的 remain,用于 0x03 */ |
|
|
|
|
|
|
|
/** 策略层交给段处理的接口参数 */ |
|
|
|
typedef struct { |
|
|
|
uint32_t f_from; |
|
|
|
@@ -102,6 +107,10 @@ 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 PlsrRunControlCheckPulseCntFault(void); |
|
|
|
static void PlsrRunControlCheckApproachCurveFault(uint8_t by_pulse_budget); |
|
|
|
static void PlsrRunControlOnApproachDone(void); |
|
|
|
static void PlsrRunControlCheckDecelCurveFault(void); |
|
|
|
static int32_t PlsrRunControlAbsLocalPos(void); |
|
|
|
static uint32_t PlsrRunControlClampSpeed(uint32_t spd); |
|
|
|
static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz, |
|
|
|
@@ -320,12 +329,57 @@ static void PlsrRunControlGotoNextOrFinish(uint16_t cur_seg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** 0x01:段正常结束时实际脉冲 ≠ 本段目标(告警,不停) */ |
|
|
|
static void PlsrRunControlCheckPulseCntFault(void) |
|
|
|
{ |
|
|
|
if ((s_target > 0) && (s_done != s_target)) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_PULSE_CNT); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 0x03:加速段结束时,相内脉冲与规划 acc_n 不一致。 |
|
|
|
* by_pulse_budget:因 n 走到预算而收尾,须精确相等;因频率提前到位则仅超额时报。 |
|
|
|
*/ |
|
|
|
static void PlsrRunControlCheckApproachCurveFault(uint8_t by_pulse_budget) |
|
|
|
{ |
|
|
|
if (s_plan_acc_n == 0U) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
if (by_pulse_budget != 0U) |
|
|
|
{ |
|
|
|
if (s_pulse_rt.n != s_plan_acc_n) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_CURVE_MISMATCH); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (s_pulse_rt.n > s_plan_acc_n) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_CURVE_MISMATCH); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** 0x03:减速段在段末核对相内脉冲与进入减速时的预算 */ |
|
|
|
static void PlsrRunControlCheckDecelCurveFault(void) |
|
|
|
{ |
|
|
|
if ((s_phase == PH_DECEL) && (s_decel_budget > 0U) && |
|
|
|
(s_pulse_rt.n != s_decel_budget)) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_CURVE_MISMATCH); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void PlsrRunControlAfterSegDone(void) |
|
|
|
{ |
|
|
|
PlsrCfg_t *cfg = PlsrParamGetCfg(); |
|
|
|
PlsrSeg_t *seg = PlsrParamGetSeg(s_cur_seg); |
|
|
|
uint8_t keep_pwm; |
|
|
|
|
|
|
|
PlsrRunControlCheckPulseCntFault(); |
|
|
|
PlsrRunControlCheckDecelCurveFault(); |
|
|
|
|
|
|
|
/* 先脱离 RUN,避免脉冲 ISR 重入 */ |
|
|
|
s_state = RC_IDLE; |
|
|
|
|
|
|
|
@@ -421,7 +475,7 @@ static uint8_t PlsrRunControlBlocksFollowKeep(uint16_t cur_seg) |
|
|
|
* 调用/等待策略:根据发送模式、等待条件、衔接状态,解析本段 |
|
|
|
* f_from / f_end / accel_ms / decel_ms。段内处理不读 wait_type。 |
|
|
|
* |
|
|
|
* @return 1 成功;0 下一段目标频非法(仅后续无缝衔接时) |
|
|
|
* @return 1 成功 |
|
|
|
*/ |
|
|
|
static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
|
PlsrSegCallIo_t *io) |
|
|
|
@@ -498,7 +552,14 @@ static uint8_t PlsrRunControlResolveSegCallIo(uint16_t seg_0, uint32_t f_tgt, |
|
|
|
cfg->default_speed, |
|
|
|
&io->f_end) == 0U) |
|
|
|
{ |
|
|
|
return 0U; |
|
|
|
/* 下一段频率非法:本段先止速收尾,下一段 Begin 再报 0x04 */ |
|
|
|
io->f_end = PlsrAccelCurveResolveEndHz(cfg->end_speed, |
|
|
|
f_tgt, |
|
|
|
cfg->default_speed, |
|
|
|
cfg->start_speed, |
|
|
|
cfg->end_speed, |
|
|
|
io->accel_ms, |
|
|
|
io->decel_ms); |
|
|
|
} |
|
|
|
} |
|
|
|
return 1U; |
|
|
|
@@ -686,6 +747,7 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
|
{ |
|
|
|
PlsrRunControlEnterPhase(PH_DECEL, from_hz); |
|
|
|
|
|
|
|
s_decel_budget = remain_pulses; |
|
|
|
s_accel_plan.acc_n = 0U; |
|
|
|
s_accel_plan.const_n = 0U; |
|
|
|
s_accel_plan.dec_n = remain_pulses; |
|
|
|
@@ -712,6 +774,19 @@ static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** 离开加速相时做 0x03 诊断 */ |
|
|
|
static void PlsrRunControlOnApproachDone(void) |
|
|
|
{ |
|
|
|
uint8_t by_budget; |
|
|
|
|
|
|
|
if (s_phase != PH_APPROACH) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
by_budget = ((s_plan_acc_n > 0U) && (s_pulse_rt.n >= s_plan_acc_n)) ? 1U : 0U; |
|
|
|
PlsrRunControlCheckApproachCurveFault(by_budget); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 进匀速:写一次 f_tgt,之后 ISR 不改 ARR(复用缓存)。 |
|
|
|
*/ |
|
|
|
@@ -789,6 +864,7 @@ static void PlsrRunControlRefreshProfile(uint8_t do_start) |
|
|
|
(next <= s_accel_plan.f_tgt))) |
|
|
|
{ |
|
|
|
next = s_accel_plan.f_tgt; |
|
|
|
PlsrRunControlOnApproachDone(); |
|
|
|
if ((PlsrRunControlHasDecel() != 0U) && |
|
|
|
(remain <= s_accel_plan.dec_n)) |
|
|
|
{ |
|
|
|
@@ -837,6 +913,24 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from, |
|
|
|
decel_ms, |
|
|
|
cfg->accel_mode); |
|
|
|
|
|
|
|
/* |
|
|
|
* 0x02:规划后峰值低于设定目标 → 脉冲不够爬到目标频(三角等) |
|
|
|
* 告警,仍按当前规划继续跑。 |
|
|
|
*/ |
|
|
|
if ((f_tgt > f_from) && (s_accel_plan.f_tgt < f_tgt)) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_FREQ_UNREACH); |
|
|
|
} |
|
|
|
else if ((f_tgt < f_from) && (s_accel_plan.f_tgt > f_tgt)) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_FREQ_UNREACH); |
|
|
|
} |
|
|
|
|
|
|
|
/* 0x03 对照用:规划预算(运行中 s_accel_plan.acc_n 可能被改写) */ |
|
|
|
s_plan_acc_n = s_accel_plan.acc_n; |
|
|
|
s_plan_dec_n = s_accel_plan.dec_n; |
|
|
|
s_decel_budget = 0U; |
|
|
|
|
|
|
|
/* 运行层使用规划后的实际起始频率。 */ |
|
|
|
f_start = s_accel_plan.f_cur; |
|
|
|
|
|
|
|
@@ -1003,24 +1097,14 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0) |
|
|
|
|
|
|
|
if (PlsrRunControlGetSegTargetFreq(seg->freq_hz, cfg->default_speed, &f_tgt) == 0U) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_SEG_FREQ); |
|
|
|
s_busy = 1U; |
|
|
|
s_target = 0; |
|
|
|
s_done = 0; |
|
|
|
PlsrRunControlAfterSegDone(); |
|
|
|
/* 0x04:频率非法,禁止启动/切段 */ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); |
|
|
|
PlsrRunControlFinishAll(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* 策略层解析起/止速与加减速;段内只跑 PlanSeg */ |
|
|
|
if (PlsrRunControlResolveSegCallIo(seg_0, f_tgt, &io) == 0U) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_SEG_FREQ); |
|
|
|
s_busy = 1U; |
|
|
|
s_target = 0; |
|
|
|
s_done = 0; |
|
|
|
PlsrRunControlAfterSegDone(); |
|
|
|
return; |
|
|
|
} |
|
|
|
(void)PlsrRunControlResolveSegCallIo(seg_0, f_tgt, &io); |
|
|
|
|
|
|
|
total = (uint32_t)s_target; |
|
|
|
PlsrRunControlPlanSeg(total, io.f_from, f_tgt, io.f_end, |
|
|
|
@@ -1102,6 +1186,19 @@ uint8_t PlsrRunControlStart(uint16_t start_seg_1based) |
|
|
|
} |
|
|
|
|
|
|
|
cfg = PlsrParamGetCfg(); |
|
|
|
{ |
|
|
|
PlsrSeg_t *seg = PlsrParamGetSeg((uint16_t)(start_seg_1based - 1U)); |
|
|
|
uint32_t f_chk; |
|
|
|
|
|
|
|
/* 启动前校验首段频率;非法则写 0x04 且不进入运行 */ |
|
|
|
if (PlsrRunControlGetSegTargetFreq(seg->freq_hz, |
|
|
|
cfg->default_speed, |
|
|
|
&f_chk) == 0U) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); |
|
|
|
return 0U; |
|
|
|
} |
|
|
|
} |
|
|
|
s_follow_cont = 0U; |
|
|
|
s_chain_valid = 0U; |
|
|
|
s_chain_freq = 0U; |
|
|
|
@@ -1145,6 +1242,7 @@ uint8_t PlsrRunControlChangeFreq(uint32_t new_tgt_hz) |
|
|
|
} |
|
|
|
if ((new_tgt_hz < 1U) || (new_tgt_hz > 100000U)) |
|
|
|
{ |
|
|
|
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); |
|
|
|
return 0U; |
|
|
|
} |
|
|
|
if (s_done >= s_target) |
|
|
|
@@ -1342,6 +1440,7 @@ void PlsrRunControlOnPulseIsr(void) |
|
|
|
(next <= s_accel_plan.f_tgt))) |
|
|
|
{ |
|
|
|
next = s_accel_plan.f_tgt; |
|
|
|
PlsrRunControlOnApproachDone(); |
|
|
|
if ((PlsrRunControlHasDecel() != 0U) && |
|
|
|
(remain <= s_accel_plan.dec_n)) |
|
|
|
{ |
|
|
|
|