diff --git a/iar/plsr.dep b/iar/plsr.dep index 3f68f93..f3b7632 100644 --- a/iar/plsr.dep +++ b/iar/plsr.dep @@ -3092,10 +3092,6 @@ BICOMP 283 - - ICCARM - 33 - __cstat 268 diff --git a/plsr/command/plsr_command.c b/plsr/command/plsr_command.c index bb0b118..d5bc00b 100644 --- a/plsr/command/plsr_command.c +++ b/plsr/command/plsr_command.c @@ -99,6 +99,7 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity) ((uint32_t)ReadHoldReg((uint16_t)(start_addr + 1U)) << 16); if ((f < 1U) || (f > 100000U)) { + PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); return; } diff --git a/plsr/command/plsr_command.h b/plsr/command/plsr_command.h index 958b3f8..37cfdb0 100644 --- a/plsr/command/plsr_command.h +++ b/plsr/command/plsr_command.h @@ -25,8 +25,11 @@ #define PLSR_CTRL_BIT_STOP (1U << 1) /* 停止脉冲 */ #define PLSR_CTRL_BIT_CLR (1U << 2) /* 清除状态信息 */ -#define PLSR_ERR_NONE 0U -#define PLSR_ERR_SEG_FREQ 1U /* 段频率非法(非 0 且越界,或解析后不在 1~100k) */ +#define PLSR_ERR_NONE 0x00U /* 无故障 */ +#define PLSR_ERR_PULSE_CNT 0x01U /* 脉冲输出个数与设置不一致(告警,继续) */ +#define PLSR_ERR_FREQ_UNREACH 0x02U /* 输出频率与设置不一致/三角达不到(告警,继续) */ +#define PLSR_ERR_CURVE_MISMATCH 0x03U /* 加减速曲线与设置不一致(告警,继续) */ +#define PLSR_ERR_FREQ_ILLEGAL 0x04U /* 脉冲频率非法(1~100k)(告警,禁止启动) */ void PlsrCommandInit(void); void PlsrCommandPoll(void); diff --git a/plsr/run_control/plsr_run_control.c b/plsr/run_control/plsr_run_control.c index 34c026e..2991a99 100644 --- a/plsr/run_control/plsr_run_control.c +++ b/plsr/run_control/plsr_run_control.c @@ -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)) {