Selaa lähdekoodia

移除对os节拍的依赖,纯脉冲计数改频

dev1
hanyongwei 1 kuukausi sitten
vanhempi
commit
584280033e
7 muutettua tiedostoa jossa 442 lisäystä ja 78 poistoa
  1. +240
    -0
      plsr/accel_curve/plsr_accel_curve.c
  2. +33
    -3
      plsr/accel_curve/plsr_accel_curve.h
  3. +1
    -1
      plsr/plsr.c
  4. +62
    -0
      plsr/pulse_driver/plsr_pulse_driver.c
  5. +6
    -0
      plsr/pulse_driver/plsr_pulse_driver.h
  6. +98
    -72
      plsr/run_control/plsr_run_control.c
  7. +2
    -2
      plsr/run_control/plsr_run_control.h

+ 240
- 0
plsr/accel_curve/plsr_accel_curve.c Näytä tiedosto

@@ -1119,3 +1119,243 @@ uint32_t PlsrAccelCurveFreqAtSegTime(const PlsrAccelPlan_t *plan,
approx_n = (uint32_t)(((uint64_t)seg_elapsed_ms * (uint64_t)f_ref) / 1000ULL);
return PlsrAccelCurveFreqAtPulse(plan, approx_n);
}

static void PlsrAccelPulseRtSetupShape(PlsrAccelPulseRt_t *rt, uint32_t n_total)
{
if (n_total < 1U)
{
rt->step_q24 = 0U;
rt->step_rem = 0U;
return;
}
/* (1<<24)/N 商余:逐拍累加,避免每拍 index/total 除法 */
rt->step_q24 = 16777216UL / n_total;
rt->step_rem = 16777216UL % n_total;
rt->phase_q24 = 0U;
rt->rem_acc = 0U;
}

void PlsrAccelPulseRtBeginAcc(PlsrAccelPulseRt_t *rt,
const PlsrAccelPlan_t *plan)
{
if ((rt == (PlsrAccelPulseRt_t *)0) || (plan == (const PlsrAccelPlan_t *)0))
{
return;
}
rt->f0 = plan->f_cur;
rt->f1 = plan->f_tgt;
rt->f = plan->f_cur;
rt->a = plan->a_acc;
rt->n = 0U;
rt->n_total = plan->acc_n;
rt->rising = (plan->f_tgt >= plan->f_cur) ? 1U : 0U;
rt->mode = plan->mode;
rt->active = (plan->acc_n > 0U) && (plan->f_cur != plan->f_tgt) ? 1U : 0U;
PlsrAccelPulseRtSetupShape(rt, rt->n_total);
}

void PlsrAccelPulseRtBeginDec(PlsrAccelPulseRt_t *rt,
const PlsrAccelPlan_t *plan)
{
if ((rt == (PlsrAccelPulseRt_t *)0) || (plan == (const PlsrAccelPlan_t *)0))
{
return;
}
rt->f0 = plan->f_tgt;
rt->f1 = plan->f_end;
rt->f = plan->f_tgt;
rt->a = plan->a_dec;
rt->n = 0U;
rt->n_total = plan->dec_n;
rt->rising = (plan->f_end >= plan->f_tgt) ? 1U : 0U;
rt->mode = plan->mode;
rt->active = (plan->dec_n > 0U) && (plan->f_tgt != plan->f_end) ? 1U : 0U;
PlsrAccelPulseRtSetupShape(rt, rt->n_total);
}

void PlsrAccelPulseRtBeginConst(PlsrAccelPulseRt_t *rt,
const PlsrAccelPlan_t *plan)
{
if ((rt == (PlsrAccelPulseRt_t *)0) || (plan == (const PlsrAccelPlan_t *)0))
{
return;
}
rt->f0 = plan->f_tgt;
rt->f1 = plan->f_tgt;
rt->f = plan->f_tgt;
rt->a = 0U;
rt->n = 0U;
rt->n_total = plan->const_n;
rt->rising = 1U;
rt->mode = plan->mode;
rt->active = 0U; /* 匀速:确认频率没变 → 复用 → 结束 */
rt->step_q24 = 0U;
rt->step_rem = 0U;
rt->phase_q24 = 0U;
rt->rem_acc = 0U;
}

/**
* 直线:用上一拍 f ±1 逼近 target_sq,不全量开方。
* 低频 df/dn 大时循环次数多,但周期也长,ISR 仍可承受。
*/
static uint32_t PlsrAccelPulseRtSquareStep(PlsrAccelPulseRt_t *rt)
{
uint64_t target_sq;
uint64_t f_sq;
uint64_t f0_sq;
uint32_t f;
uint32_t guard;

f0_sq = (uint64_t)rt->f0 * (uint64_t)rt->f0;
if (rt->rising != 0U)
{
target_sq = f0_sq + (2ULL * (uint64_t)rt->a * (uint64_t)rt->n);
}
else
{
uint64_t drop = 2ULL * (uint64_t)rt->a * (uint64_t)rt->n;
target_sq = (drop >= f0_sq) ? 0ULL : (f0_sq - drop);
}

f = rt->f;
if (f < 1U)
{
f = 1U;
}

for (guard = 0U; guard < 2048U; guard++)
{
f_sq = (uint64_t)f * (uint64_t)f;
if (rt->rising != 0U)
{
if ((f < rt->f1) && (((uint64_t)(f + 1U) * (uint64_t)(f + 1U)) <= target_sq))
{
f++;
continue;
}
if ((f > 1U) && (f_sq > target_sq))
{
f--;
continue;
}
break;
}
else
{
if ((f > rt->f1) && (f_sq > target_sq))
{
f--;
continue;
}
if ((f < 100000U) &&
(((uint64_t)(f + 1U) * (uint64_t)(f + 1U)) < target_sq))
{
f++;
continue;
}
break;
}
}

if (rt->rising != 0U)
{
if (f > rt->f1)
{
f = rt->f1;
}
}
else
{
if (f < rt->f1)
{
f = rt->f1;
}
}
if (f < 1U)
{
f = 1U;
}
return PlsrAccelCurveClampFreq(f);
}

static uint32_t PlsrAccelPulseRtShapeStep(PlsrAccelPulseRt_t *rt)
{
uint32_t ratio;
uint32_t f;

if (rt->n_total < 1U)
{
return PlsrAccelCurveClampFreq(rt->f1);
}

if (rt->n >= rt->n_total)
{
return PlsrAccelCurveClampFreq(rt->f1);
}

rt->phase_q24 += rt->step_q24;
rt->rem_acc += rt->step_rem;
if (rt->rem_acc >= rt->n_total)
{
rt->rem_acc -= rt->n_total;
rt->phase_q24 += 1U;
}
if (rt->phase_q24 > 16777216UL)
{
rt->phase_q24 = 16777216UL;
}

ratio = (uint32_t)(((uint64_t)rt->phase_q24 * 1000ULL) / 16777216ULL);
if (ratio > 1000U)
{
ratio = 1000U;
}
ratio = PlsrAccelCurveShapePermille(ratio, rt->mode);
f = PlsrAccelCurveLerp(rt->f0, rt->f1, ratio);
if (f < 1U)
{
f = 1U;
}
return PlsrAccelCurveClampFreq(f);
}

uint32_t PlsrAccelPulseRtStep(PlsrAccelPulseRt_t *rt)
{
if (rt == (PlsrAccelPulseRt_t *)0)
{
return 0U;
}
if (rt->active == 0U)
{
return PlsrAccelCurveClampFreq(rt->f);
}

if (rt->n < 0xFFFFFFFFUL)
{
rt->n++;
}

if (rt->mode == PLSR_ACCEL_LINEAR)
{
if (rt->a == 0U)
{
rt->f = rt->f1;
}
else
{
rt->f = PlsrAccelPulseRtSquareStep(rt);
}
}
else
{
rt->f = PlsrAccelPulseRtShapeStep(rt);
}

if ((rt->n_total > 0U) && (rt->n >= rt->n_total))
{
rt->f = rt->f1;
rt->active = 0U;
}
return rt->f;
}

+ 33
- 3
plsr/accel_curve/plsr_accel_curve.h Näytä tiedosto

@@ -107,14 +107,44 @@ void PlsrAccelCurvePlan(PlsrAccelPlan_t *plan,
PlsrAccelMode_e mode);

/**
* 按已完成脉冲数取频(任务上下文调用,勿进脉冲 ISR)。
* pulse_done = 本段已发完的脉冲数(与 s_done 一致)。
* 按已完成脉冲数取频(任务/预览可用)。
* 运行热路径请用 PlsrAccelPulseRt(逐拍 ±1 / Q24,可进 ISR)。
*/
uint32_t PlsrAccelCurveFreqAtPulse(const PlsrAccelPlan_t *plan,
uint32_t pulse_done);

/** @deprecated 时间轴取频;保留给旧预览,运行请用 FreqAtPulse */
/** @deprecated 时间轴取频;保留给旧预览,运行请用脉冲域 */
uint32_t PlsrAccelCurveFreqAtSegTime(const PlsrAccelPlan_t *plan,
uint32_t seg_elapsed_ms);

/**
* 逐拍运行态(ISR 热路径):
* - 直线:上一拍频率 ±1 逼近 sqrt(f0^2±2an),不全量 Isqrt64
* - S/正弦:Begin 时算 Q24 步长,逐拍商余累加,不做 index/total 除法
*/
typedef struct {
uint32_t f; /* 当前命令频率 */
uint32_t f0; /* 本相起点频率 */
uint32_t f1; /* 本相终点频率 */
uint32_t a; /* Hz/s;直线用 */
uint32_t n; /* 本相已完成脉冲 */
uint32_t n_total; /* 本相总脉冲(距离只在 Begin 算) */
uint32_t phase_q24; /* S/正弦进度 0..(1<<24) */
uint32_t step_q24;
uint32_t step_rem; /* (1<<24) % n_total */
uint32_t rem_acc;
uint8_t rising;
uint8_t active; /* 0=匀速保持,不 Step */
PlsrAccelMode_e mode;
} PlsrAccelPulseRt_t;

void PlsrAccelPulseRtBeginAcc(PlsrAccelPulseRt_t *rt,
const PlsrAccelPlan_t *plan);
void PlsrAccelPulseRtBeginDec(PlsrAccelPulseRt_t *rt,
const PlsrAccelPlan_t *plan);
void PlsrAccelPulseRtBeginConst(PlsrAccelPulseRt_t *rt,
const PlsrAccelPlan_t *plan);
/** 本相前进 1 脉冲,返回下一拍命令频率(匀速直接返回缓存 f) */
uint32_t PlsrAccelPulseRtStep(PlsrAccelPulseRt_t *rt);

#endif

+ 1
- 1
plsr/plsr.c Näytä tiedosto

@@ -88,7 +88,7 @@ void PlsrTask(void *pArg)

PlsrCommandPoll(); /* 收 START/STOP 等,回写忙闲状态 */
PlsrPersistPoll(); /* 公共参数有改且空闲则追加写入 Flash */
PlsrRunControlTickMs(); /* 方向延时、段间等待到期处理 */
PlsrRunControlTickMs(); /* ACT/WAIT/EXT;改频在脉冲 ISR */

#if (PLSR_LOOP_TEST_EN != 0)
/* 调试:空闲满 1s 自动从第 1 段再启 */


+ 62
- 0
plsr/pulse_driver/plsr_pulse_driver.c Näytä tiedosto

@@ -550,6 +550,68 @@ void PlsrPulseDriverSetFreq(uint32_t freq_hz)
s_last_arr = arr;
}

void PlsrPulseDriverSetFreqIsr(uint32_t freq_hz)
{
uint32_t psc;
uint32_t arr;
uint32_t ccr;
uint32_t clk_hz;
TIM_HandleTypeDef *htim;

/* 匀速热路径:频率未变 → 不算量化、不写寄存器 */
if (freq_hz == s_last_freq)
{
return;
}

if (freq_hz == 0U)
{
s_req_freq = 0U;
s_req_pending = 1U;
return;
}

htim = s_active_htim;
if (htim == (TIM_HandleTypeDef *)0)
{
s_req_freq = freq_hz;
s_req_pending = 1U;
return;
}

clk_hz = PlsrPulseDriverTimClkHz(htim);

if (s_psc_locked != 0U)
{
psc = s_locked_psc;
PlsrPulseDriverCalcArrWithPsc(clk_hz, freq_hz, psc, &arr, &ccr);
}
else
{
PlsrPulseDriverCalcPscArr(clk_hz, freq_hz, &psc, &arr, &ccr);
if (psc != s_last_psc)
{
/* ISR 内禁止停表换 PSC,留给任务 */
s_req_freq = freq_hz;
s_req_pending = 1U;
return;
}
}

if ((psc == s_last_psc) && (arr == s_last_arr))
{
s_last_freq = freq_hz;
return;
}

__HAL_TIM_SET_AUTORELOAD(htim, arr);
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, ccr);

s_last_freq = freq_hz;
s_last_psc = psc;
s_last_arr = arr;
}

void PlsrPulseDriverRequestFreq(uint32_t freq_hz)
{
s_req_freq = freq_hz;


+ 6
- 0
plsr/pulse_driver/plsr_pulse_driver.h Näytä tiedosto

@@ -33,6 +33,12 @@ void PlsrPulseDriverUnlockPsc(void);
void PlsrPulseDriverStart(uint32_t freq_hz);
void PlsrPulseDriverStartFreeRun(uint32_t freq_hz);
void PlsrPulseDriverSetFreq(uint32_t freq_hz);
/**
* 脉冲 ISR 改频:仅写 ARR/CCR(预装载,下一拍生效)。
* PSC 不变时直接改;若必须换 PSC 则挂起,由任务 ApplyPending。
* 频率未变或 ARR 未变则立即返回(匀速热路径)。
*/
void PlsrPulseDriverSetFreqIsr(uint32_t freq_hz);
/** 请求改频(ISR 周期边界再落到硬件) */
void PlsrPulseDriverRequestFreq(uint32_t freq_hz);
/** 在更新中断里调用:应用挂起频率 */


+ 98
- 72
plsr/run_control/plsr_run_control.c Näytä tiedosto

@@ -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)


+ 2
- 2
plsr/run_control/plsr_run_control.h Näytä tiedosto

@@ -12,8 +12,8 @@ uint8_t PlsrRunControlStart(uint16_t start_seg_1based);
void PlsrRunControlStop(void);
uint8_t PlsrRunControlChangeFreq(uint32_t new_tgt_hz);
void PlsrRunControlOn1ms(void); /* TIM3 1ms:仅 ACT/WAIT 时基 */
void PlsrRunControlOnPulseIsr(void); /* 脉冲 UPDATE:计脉冲 + dirty */
void PlsrRunControlTickMs(void); /* 任务:脉冲域改频 + EXT/到期切段 */
void PlsrRunControlOnPulseIsr(void); /* 脉冲 UPDATE:计数 + 逐拍改频 */
void PlsrRunControlTickMs(void); /* 任务:ACT/WAIT/EXT + ApplyPending */
uint8_t PlsrRunControlIsBusy(void);
int32_t PlsrRunControlGetAccPulse(void);
void PlsrRunControlClearAccPulse(void);


Ladataan…
Peruuta
Tallenna