Переглянути джерело

补充了部分注释

Signed-off-by: hanyongwei <2043702190@qq.com>
dev3
hanyongwei 2 тижднів тому
джерело
коміт
1d799e89d5
7 змінених файлів з 207 додано та 151 видалено
  1. +2
    -0
      modbus/modbus_rtu.c
  2. +37
    -9
      plsr/accel_curve/plsr_accel_curve.c
  3. +10
    -9
      plsr/command/plsr_command.c
  4. +2
    -2
      plsr/plsr.c
  5. +16
    -13
      plsr/pulse_driver/plsr_pulse_driver.c
  6. +1
    -1
      plsr/pulse_driver/plsr_pulse_driver.h
  7. +139
    -117
      plsr/run_control/plsr_run_control.c

+ 2
- 0
modbus/modbus_rtu.c Переглянути файл

@@ -441,7 +441,9 @@ static void WriteMultiRegs(const uint8_t *frame, uint16_t len)
g_modbus_tx_buf[5] = frame[5];
AppendCrcAndSend(g_modbus_tx_buf, 6U);

/*统计接受帧数,收满释放信号量*/
PlsrParamBlockOnHoldWrite(startAddr, quantity);
/* 动态改频率 */
PlsrCommandOnSegFreqHoldWrite(startAddr, quantity);
}



+ 37
- 9
plsr/accel_curve/plsr_accel_curve.c Переглянути файл

@@ -125,28 +125,32 @@ static void PlsrAccelRuntimeSelectFreqTable(PlsrAccelRuntime_t *runtime,
/* 公共 API */
/*============================================================================*/

/*计算起始频率*/
uint32_t PlsrAccelCurveResolveStartHz(uint32_t configured_freq_hz,
uint32_t target_freq_hz,
uint32_t default_speed_hz,
uint32_t accel_time_ms,
uint32_t decel_time_ms)
{
/*resolving_start=1 用 accel_time_ms 算 a;resolving_start=0 用 decel_time_ms(ResolveEndHz 止速侧)*/
return PlsrAccelCurveResolveBoundaryFreq(configured_freq_hz, target_freq_hz, default_speed_hz,
accel_time_ms, decel_time_ms, 1U);
}

/*计算终止频率*/
uint32_t PlsrAccelCurveResolveEndHz(uint32_t configured_freq_hz,
uint32_t target_freq_hz,
uint32_t default_speed_hz,
uint32_t accel_time_ms,
uint32_t decel_time_ms)
{
/*resolving_start=1 用 accel_time_ms 算 a;resolving_start=0 用 decel_time_ms(ResolveEndHz 止速侧)*/
return PlsrAccelCurveResolveBoundaryFreq(configured_freq_hz, target_freq_hz, default_speed_hz,
accel_time_ms, decel_time_ms, 0U);
}

/**
* @brief 规划一整段脉冲域(见 plsr_accel_curve.h)
* @brief 规划一整段脉冲
*/
void PlsrAccelCurvePlan(PlsrAccelPlan_t *plan,
uint32_t total_pulses,
@@ -163,7 +167,7 @@ void PlsrAccelCurvePlan(PlsrAccelPlan_t *plan,
uint32_t peak_freq_hz;
uint32_t accel_rate_hz_per_s;
uint32_t decel_rate_hz_per_s;
PlsrAccelMode_e selected_mode;
PlsrAccelMode_e selected_mode;/*曲线模式*/

if (plan == (PlsrAccelPlan_t *)0)
{
@@ -174,13 +178,16 @@ void PlsrAccelCurvePlan(PlsrAccelPlan_t *plan,
target_freq_hz = PlsrAccelCurveClampFreqHz(target_freq_hz);
end_freq_hz = PlsrAccelCurveClampFreqHz(end_freq_hz);

/*加减速曲线模式*/
selected_mode = (curve_mode > PLSR_ACCEL_SINE) ? PLSR_ACCEL_LINEAR : curve_mode;

/*起始频率小于1,计算一个合适的起始频率*/
if (start_freq_hz < 1U)
{
start_freq_hz = PlsrAccelCurveResolveStartHz(0U, target_freq_hz, default_speed_hz,
accel_time_ms, decel_time_ms);
}
/*终止频率小于1,计算一个合适的终止频率*/
if (end_freq_hz < 1U)
{
end_freq_hz = PlsrAccelCurveResolveEndHz(0U, target_freq_hz, default_speed_hz,
@@ -191,13 +198,14 @@ void PlsrAccelCurvePlan(PlsrAccelPlan_t *plan,
PlsrAccelCurveCalcRate(default_speed_hz,
start_freq_hz,
target_freq_hz,
accel_time_ms);
accel_time_ms);/*计算加速斜率*/
decel_rate_hz_per_s =
PlsrAccelCurveCalcRate(default_speed_hz,
target_freq_hz,
end_freq_hz,
decel_time_ms);
decel_time_ms);/*计算减速斜率*/

/*将结果写进规划结果*/
peak_freq_hz = target_freq_hz;

plan->start_freq_hz = start_freq_hz;
@@ -206,6 +214,7 @@ void PlsrAccelCurvePlan(PlsrAccelPlan_t *plan,
plan->accel_rate_hz_per_s = accel_rate_hz_per_s;
plan->decel_rate_hz_per_s = decel_rate_hz_per_s;

/*按峰值重算加速/减速脉冲预算*/
PlsrAccelCurveCalcPhasePulses(start_freq_hz,
peak_freq_hz,
end_freq_hz,
@@ -756,6 +765,7 @@ static uint32_t PlsrAccelCurveResolveBoundaryFreq(uint32_t configured_freq_hz,
uint32_t accel_hz_per_s;
uint32_t jump_freq_hz;

/* 验证频率是否超过100k */
configured_freq_hz = PlsrAccelCurveClampFreqHz(configured_freq_hz);
target_freq_hz = PlsrAccelCurveClampFreqHz(target_freq_hz);
if (target_freq_hz < 1U)
@@ -763,13 +773,14 @@ static uint32_t PlsrAccelCurveResolveBoundaryFreq(uint32_t configured_freq_hz,
return 1U;
}

/* 配置起/止速 > 目标:用配置速 */
/* 配置起始速度/终止止速 > 目标频率:用配置速 */
if (configured_freq_hz > target_freq_hz)
{
return configured_freq_hz;
}

ramp_time_ms = (resolving_start != 0U) ? accel_time_ms : decel_time_ms;
/*计算加速度*/
accel_hz_per_s =
PlsrAccelCurveCalcRate(default_speed_hz,
configured_freq_hz,
@@ -780,6 +791,7 @@ static uint32_t PlsrAccelCurveResolveBoundaryFreq(uint32_t configured_freq_hz,
return (configured_freq_hz >= 1U) ? configured_freq_hz : target_freq_hz;
}

/*按运动学公式计算起跳频率*/
jump_freq_hz = PlsrAccelCurveCalcJumpFreq(configured_freq_hz, accel_hz_per_s);

/* 目标 < 起跳 → 用目标;目标 >= 起跳 → 用起跳 */
@@ -790,6 +802,7 @@ static uint32_t PlsrAccelCurveResolveBoundaryFreq(uint32_t configured_freq_hz,
return jump_freq_hz;
}

/*线性插值*/
static uint32_t PlsrAccelCurveInterpolate(uint32_t start_val,
uint32_t end_val,
uint32_t ratio_permille)
@@ -1277,7 +1290,7 @@ static uint32_t PlsrAccelCurveTimedFreqAtPulse(
return cur_freq_hz;
}

/*仿真离散脉冲频率,算出该段加减速一共需要输出多少个脉冲*/
/*仿真离散脉冲频率,算出该段加/减速一共需要输出多少个脉冲*/
static uint32_t PlsrAccelCurveSimulateRampPulses(uint32_t start_freq_hz, uint32_t end_freq_hz,
uint32_t accel_hz_per_s,
PlsrAccelMode_e curve_mode)
@@ -1285,18 +1298,21 @@ static uint32_t PlsrAccelCurveSimulateRampPulses(uint32_t start_freq_hz, uint32_
PlsrAccelRuntime_t runtime;
uint32_t iteration_guard;

/*起始频率 = 终止频率,或者加速度=0,返回0*/
if (start_freq_hz == end_freq_hz || accel_hz_per_s == 0U)
{
return 0U;
}

/* 填写一个加速或减速相的运行数据 */
PlsrAccelRuntimeBeginRamp(&runtime,
start_freq_hz,
end_freq_hz,
0xFFFFFFFFUL,
0xFFFFFFFFUL,/*总脉冲数,填写最大值*/
accel_hz_per_s,
accel_hz_per_s,
curve_mode);
/* 算出来的斜坡时间是 0(无效)时,仍按至少 1 个脉冲处理。 */
if (runtime.ramp_time_us < 1U)
{
return 1U;
@@ -1306,14 +1322,16 @@ static uint32_t PlsrAccelCurveSimulateRampPulses(uint32_t start_freq_hz, uint32_
while ((runtime.is_active != 0U) && (iteration_guard < 5000000U))
{
iteration_guard++;
/* 单个脉冲仿真 */
PlsrAccelRuntimeSimulateOnePulse(&runtime);
}

/*使用的脉冲数至少为1个*/
if (runtime.completed_pulses == 0U)
{
return 1U;
}
return runtime.completed_pulses;
return runtime.completed_pulses; /*返回仿真的后的总脉冲数*/
}

/**
@@ -1368,6 +1386,7 @@ static uint32_t PlsrAccelNextFreqTimed(PlsrAccelRuntime_t *runtime)
/* 规划 */
/*============================================================================*/

/* S或者正弦,采用仿真方式,直线采用直接计算方式 */
static uint32_t PlsrAccelCurveCalcRampPulses(uint32_t start_freq_hz, uint32_t end_freq_hz,
uint32_t accel_hz_per_s,
PlsrAccelMode_e curve_mode)
@@ -1465,6 +1484,7 @@ static void PlsrAccelCurveCalcPhasePulses(uint32_t start_freq_hz,
uint32_t *accel_pulses,
uint32_t *decel_pulses)
{
/*如果起始频率 > 峰值频率,加速脉冲数*/
if (start_freq_hz > peak_freq_hz)
{
*accel_pulses = PlsrAccelCurveCalcRampPulses(start_freq_hz, peak_freq_hz, decel_rate_hz_per_s, curve_mode);
@@ -1534,6 +1554,7 @@ static uint32_t PlsrAccelCurveFitTargetToPulseBudget(uint32_t total_pulses,
/* 运行态 */
/*============================================================================*/

/* 运行时计算时间*/
static void PlsrAccelRuntimeCalcTimes(PlsrAccelRuntime_t *runtime)
{
runtime->elapsed_time_us = 0U;
@@ -1541,15 +1562,18 @@ static void PlsrAccelRuntimeCalcTimes(PlsrAccelRuntime_t *runtime)
runtime->const_accel_time_us = 0U;
runtime->ramp_time_us = 0U;

/*加速度小于1,或者起始频率 = 终止频率,直接结束*/
if ((runtime->accel_hz_per_s < 1U) || (runtime->start_freq_hz == runtime->end_freq_hz))
{
return;
}
/*S曲线计算时间*/
if (runtime->curve_mode == PLSR_ACCEL_S)
{
PlsrAccelCurveCalcSCurveTimes(runtime->start_freq_hz, runtime->end_freq_hz, runtime->accel_hz_per_s,
&runtime->jerk_time_us, &runtime->const_accel_time_us, &runtime->ramp_time_us);
}
/* 正弦曲线计算时间*/
else if (runtime->curve_mode == PLSR_ACCEL_SINE)
{
PlsrAccelCurveCalcSineCurveTime(runtime->start_freq_hz, runtime->end_freq_hz, runtime->accel_hz_per_s, &runtime->ramp_time_us);
@@ -1570,18 +1594,22 @@ static void PlsrAccelRuntimeBeginRamp(PlsrAccelRuntime_t *runtime,
runtime->cur_freq_hz = start_freq_hz;
runtime->completed_pulses = 0U;
runtime->total_pulses = total_pulses;
/*终点 > 起点,加速过程*/
runtime->freq_rising =
(end_freq_hz >= start_freq_hz) ? 1U : 0U;
/*加速度,上升用加速斜率,下降用减速斜率*/
runtime->accel_hz_per_s =
(runtime->freq_rising != 0U) ?
accel_rate_hz_per_s : decel_rate_hz_per_s;
/*曲线模式*/
runtime->curve_mode = curve_mode;
/* 1=当前相仍在运行 */
runtime->is_active = ((total_pulses > 0U) &&
(start_freq_hz != end_freq_hz)) ? 1U : 0U;
runtime->freq_table_id = 0U;
runtime->table_length = 0U;
runtime->table_stride = 1U;
PlsrAccelRuntimeCalcTimes(runtime);
PlsrAccelRuntimeCalcTimes(runtime);/*计算加速时间*/
}

/** 离散仿真一步:与建表 / 脉冲预算共用 */


+ 10
- 9
plsr/command/plsr_command.c Переглянути файл

@@ -191,13 +191,13 @@ void PlsrCommandPoll(void)

if ((ctrl & PLSR_CTRL_BIT_STOP) != 0U)
{
PlsrStop();
PlsrStop();/*停止输出*/
}

if ((ctrl & PLSR_CTRL_BIT_CLR) != 0U)
{
PlsrClearAccPulse();
PlsrCommandClearFault(); /* 清零累计时同步清故障码 */
PlsrClearAccPulse();/*清零累计脉冲与绝对原点*/
PlsrCommandClearFault(); /* 清零故障码同步清累计脉冲 */
}

/* 同时有停止位时不启动 */
@@ -209,18 +209,19 @@ void PlsrCommandPoll(void)
/* 0x0C:运行中重复 START,启动无效 */
PlsrCommandSetFault(PLSR_ERR_DUP_START);
}
else if (PlsrParamBlockApplyFromHold() == 0U)
{
/* 如果从modbus保持寄存器写入plsr结构体失败,暂不处理 */
}
/*如果禁止启动,使用停止指令*/
else if (PlsrCommandIsStartBlocked() != 0U)
{
/* 0x04~0x0B 故障码:禁止启动 */
PlsrStop();
}
/*如果允许运行,先停止清标志位,再开始输出*/
else
{
PlsrStop();
/*启动输出入口*/
(void)PlsrStart(PlsrParamGetStartSeg());
/*如果不需要精确等待,就跳过监控*/
if (PlsrRunControlIsPreciseWait() != 0U)
{
skip_monitor = 1U;
@@ -234,11 +235,11 @@ void PlsrCommandPoll(void)
{
uint32_t freq = s_live_freq_hz;
s_live_freq_req = 0U;
(void)PlsrChangeFreq(freq);
(void)PlsrChangeFreq(freq);/*动态改频函数入口*/
}

if (skip_monitor == 0U)
{
PlsrCommandPublishMonitor();
PlsrCommandPublishMonitor();/*刷新全部监控寄存器*/
}
}

+ 2
- 2
plsr/plsr.c Переглянути файл

@@ -71,9 +71,9 @@ void PlsrTask(void *pArg)
s_booted = 1U;
}

PlsrRunControlTickMs(); /* 优先:WAIT/换向到期立刻开表 */
PlsrRunControlTickMs(); /* 处理延时/外部信号输入,优先:WAIT/换向到期立刻开表 */
PlsrSignalIoDebouncePoll(); /* OS 节拍消抖确认 */
PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 */
PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 ,决定是否开pwm输出*/
PlsrPersistTickMonitor(); /* 监控区:运行态→hold→BKP(每 OS 节拍) */

/*


+ 16
- 13
plsr/pulse_driver/plsr_pulse_driver.c Переглянути файл

@@ -120,14 +120,10 @@ static void PlsrPulseDriverDirGpioInit(void)
HAL_GPIO_WritePin(PLSR_Y3_PORT, PLSR_Y3_PIN, GPIO_PIN_RESET);
}

/**
* 停表:不关复用、不关 CC1E。
* HAL_TIM_PWM_Stop 会清 CC1E,脚变成 AF 高阻,飞线接地的沿会耦合出极短脉冲。
* Forced inactive + 通道保持使能:TIM 推挽把脚主动拉低(段间空闲低)。
*/
/*关掉末拍下降沿再锁低这套 CC1 监听;脚怎么拉低在下面的两个函数*/
static void PlsrPulseDriverClearSegEndFallArm(TIM_HandleTypeDef *htim)
{
s_seg_end_fall_armed = 0U;
s_seg_end_fall_armed = 0U;/*末拍 CC1 下降沿后强制拉低 */
if ((htim == (TIM_HandleTypeDef *)0) || (htim->Instance == (TIM_TypeDef *)0))
{
return;
@@ -429,7 +425,9 @@ static void PlsrPulseDriverCalcPscArr(uint32_t clk_hz, uint32_t freq_hz,
PlsrPulseDriverCalcArrWithPsc(clk_hz, freq_hz, p, arr, ccr);
}

/** @brief 按频率跨度锁 PSC */
/** @brief 按频率跨度锁 PSC
* 1 个 tick = TIM 输入时钟的 1 个周期。ticks = 输出 1 个脉冲要占多少个这种小时钟周期。
*/
void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
{
uint32_t ticks_max;
@@ -437,6 +435,7 @@ void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
uint32_t psc_div_max;
uint32_t psc_div_min;
uint32_t div;
/*获取Y端子的时钟频率,Y0/Y1为168MHz,Y2为84MHz */
uint32_t clk_hz = PlsrPulseDriverTimClkHz(
PlsrPulseDriverHtimByY(PlsrPulseDriverSelectY()));

@@ -448,6 +447,7 @@ void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
{
f_max_hz = 1U;
}
/*如果最小值小于最大值,则交换最小值与最大值*/
if (f_max_hz < f_min_hz)
{
uint32_t temp = f_min_hz;
@@ -455,8 +455,9 @@ void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
f_max_hz = temp;
}

ticks_max = clk_hz / f_min_hz;
ticks_min = clk_hz / f_max_hz;
ticks_max = clk_hz / f_min_hz;/*最大tick数=系统频率/最小频率*/
ticks_min = clk_hz / f_max_hz;/*最小tick数=系统频率/最大频率*/
/*如果tick数小于2,则改为2,因为tick=(psc+1)(arr+1),psc可以为0,但arr不能为0,否则输出单一电平*/
if (ticks_max < 2UL)
{
ticks_max = 2UL;
@@ -466,16 +467,18 @@ void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
ticks_min = 2UL;
}

/* psc_div = PSC+1:低频要求 div 足够大,高频要求 div 足够小 */
/* psc_div = PSC+1:低频要求 psc 足够大,高频要求 psc 足够小 */
/* psc = tick / (ARR + 1) ,当arr+1最大时,psc为最小值,再小就不满足乘积=tick*/
psc_div_min = (ticks_max + 65535UL) / 65536UL;
if (psc_div_min < 1UL)
{
psc_div_min = 1UL;
}
/* psc = tick / (ARR + 1) ,当arr+1最小时,psc为最大值,再大就不满足乘积=tick*/
psc_div_max = ticks_min / 2UL;
if (psc_div_max < 1UL)
{
psc_div_max = 1UL;
psc_div_max = 1UL;/* psc的最大值最小为1,最小值可以为0 */
}

if (psc_div_min > psc_div_max)
@@ -489,7 +492,7 @@ void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
return;
}

div = psc_div_min;
div = psc_div_min;/*取最小的psc作为psc锁定,让arr尽可能大,提高分辨率*/
s_locked_psc = div - 1UL;
s_psc_locked = 1U;
}
@@ -1003,7 +1006,7 @@ void PlsrPulseDriverClearOnePulseStop(void)
return;
}
htim->Instance->CR1 &= (uint32_t)(~TIM_CR1_OPM);
PlsrPulseDriverClearSegEndFallArm(htim);
PlsrPulseDriverClearSegEndFallArm(htim);/*关掉末拍下降沿拉低标志*/
}

/** @brief OPM 段末 UPDATE 后立刻拉低,消除 CNT 回零 PWM1 假上升沿 */


+ 1
- 1
plsr/pulse_driver/plsr_pulse_driver.h Переглянути файл

@@ -38,7 +38,7 @@ extern TIM_HandleTypeDef htim13;
extern volatile uint32_t g_plsr_output_freq_hz;
extern volatile uint8_t g_plsr_pwm_running;
extern uint8_t g_plsr_direction_forward;
extern uint8_t g_plsr_direction_valid;
extern uint8_t g_plsr_direction_valid;/*方向脚有效*/

/**
* @brief 初始化三路脉冲 TIM + 方向 GPIO


+ 139
- 117
plsr/run_control/plsr_run_control.c Переглянути файл

@@ -38,28 +38,28 @@ typedef enum {
PH_DECEL
} RunPhase_e;

volatile uint8_t g_plsr_busy;
volatile uint16_t g_plsr_cur_seg_idx;
volatile int32_t g_plsr_accumulated_pulses;
static volatile RcState_e s_state;
static volatile uint8_t s_forward;/*当前端脉冲方向*/
static volatile int32_t s_seg_pulses_done;
static volatile int32_t s_seg_pulse_target;
static int32_t s_absolute_origin;
static uint8_t s_absolute_origin_locked;
static volatile uint8_t s_act_timer_armed;
static volatile uint8_t s_act_expired;
static volatile uint8_t s_act_waiting_for_pulse_boundary;
static volatile uint8_t s_keep_freq_after_act;
static volatile uint8_t s_wait_time_expired;
static uint8_t s_waiting_for_input_signal;
static volatile RunPhase_e s_phase;
static uint8_t s_continue_without_stopping;
static uint32_t s_next_seg_start_freq_hz;
static uint8_t s_next_seg_start_freq_valid;
static uint8_t s_stop_after_last_pulse;
static volatile uint8_t s_waiting_for_last_period;
static OS_EVENT *s_wake_sem;
volatile uint8_t g_plsr_busy; /* 运行忙标志(上位机监控) */
volatile uint16_t g_plsr_cur_seg_idx; /* 当前段下标(0-based) */
volatile int32_t g_plsr_accumulated_pulses; /* 全局累计脉冲(有符号) */
static volatile RcState_e s_state; /* 主状态机:IDLE/DIR_WAIT/RUN/WAIT_COND */
static volatile uint8_t s_forward; /* 当前段脉冲方向:1=正转,0=反转 */
static volatile int32_t s_seg_pulses_done; /* 本段已发脉冲数 */
static volatile int32_t s_seg_pulse_target; /* 本段目标脉冲数(绝对值) */
static int32_t s_absolute_origin; /* 绝对定位坐标原点 */
static uint8_t s_absolute_origin_locked; /* 原点是否已锁定(CLR 后重锁) */
static volatile uint8_t s_act_timer_armed; /* ACT 定时器是否已启动 */
static volatile uint8_t s_act_expired; /* ACT 到期请求(TickMs 消费) */
static volatile uint8_t s_act_waiting_for_pulse_boundary; /* ACT 到期后等脉冲边界切段 */
static volatile uint8_t s_keep_freq_after_act; /* ACT 切段后保持当前频率衔接 */
static volatile uint8_t s_wait_time_expired; /* 段后 WAIT 时间到期请求 */
static uint8_t s_waiting_for_input_signal; /* 段后等 WAIT/EXT 输入沿 */
static volatile RunPhase_e s_phase; /* 段内相:加速/匀速/减速 */
static uint8_t s_continue_without_stopping; /* 段间不停表衔接(FOLLOW/keep) */
static uint32_t s_next_seg_start_freq_hz; /* 段间衔接起始频率 Hz */
static uint8_t s_next_seg_start_freq_valid; /* 衔接频率是否有效 */
static uint8_t s_stop_after_last_pulse; /* 末拍后完整停表(完成模式) */
static volatile uint8_t s_waiting_for_last_period; /* 等末拍 UPDATE 再收尾 */
static OS_EVENT *s_wake_sem; /* 唤醒 PlsrTask 的信号量 */

/* 策略层解析后交给 PlanSeg 的段端点 */
typedef struct {
@@ -121,30 +121,30 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
/** @brief 运行控制初始化 */
void PlsrRunControlInit(void)
{
s_state = RC_IDLE;
g_plsr_busy = 0U;
s_forward = 1U;
g_plsr_cur_seg_idx = 0U;
s_seg_pulses_done = 0;
s_seg_pulse_target = 0;
g_plsr_accumulated_pulses = 0;
s_absolute_origin = 0;
s_absolute_origin_locked = 0U;
s_continue_without_stopping = 0U;
s_next_seg_start_freq_hz = 0U;
s_next_seg_start_freq_valid = 0U;
g_plsr_accel_plan.accel_pulses = 0U;
g_plsr_accel_plan.decel_pulses = 0U;
g_plsr_accel_runtime.total_pulses = 0U;
s_stop_after_last_pulse = 0U;
s_waiting_for_last_period = 0U;
s_phase = PH_CONST;
s_act_timer_armed = 0U;
s_act_expired = 0U;
s_act_waiting_for_pulse_boundary = 0U;
s_keep_freq_after_act = 0U;
s_wait_time_expired = 0U;
s_waiting_for_input_signal = 0U;
s_state = RC_IDLE; /* 主状态机:空闲 */
g_plsr_busy = 0U; /* 运行忙标志(上位机监控) */
s_forward = 1U; /* 当前段脉冲方向:1=正转 */
g_plsr_cur_seg_idx = 0U; /* 当前段下标(0-based) */
s_seg_pulses_done = 0; /* 本段已发脉冲数 */
s_seg_pulse_target = 0; /* 本段目标脉冲数(绝对值) */
g_plsr_accumulated_pulses = 0; /* 全局累计脉冲(有符号) */
s_absolute_origin = 0; /* 绝对定位坐标原点 */
s_absolute_origin_locked = 0U; /* 原点是否已锁定(CLR 后重锁) */
s_continue_without_stopping = 0U; /* 段间不停表衔接(FOLLOW/keep) */
s_next_seg_start_freq_hz = 0U; /* 段间衔接起始频率 Hz */
s_next_seg_start_freq_valid = 0U; /* 衔接频率是否有效 */
g_plsr_accel_plan.accel_pulses = 0U; /* 规划:加速相脉冲预算 */
g_plsr_accel_plan.decel_pulses = 0U; /* 规划:减速相脉冲预算 */
g_plsr_accel_runtime.total_pulses = 0U; /* 当前相计划总脉冲 */
s_stop_after_last_pulse = 0U; /* 末拍后完整停表(完成模式) */
s_waiting_for_last_period = 0U; /* 等末拍 UPDATE 再收尾 */
s_phase = PH_CONST; /* 段内相:加速/匀速/减速 */
s_act_timer_armed = 0U; /* ACT 定时器是否已启动 */
s_act_expired = 0U; /* ACT 到期请求(TickMs 消费) */
s_act_waiting_for_pulse_boundary = 0U; /* ACT 到期后等脉冲边界切段 */
s_keep_freq_after_act = 0U; /* ACT 切段后保持当前频率衔接 */
s_wait_time_expired = 0U; /* 段后 WAIT 时间到期请求 */
s_waiting_for_input_signal = 0U; /* 段后等 WAIT/EXT 输入沿 */
/* s_wake_sem 在 OSInit 后由 WakeInit 创建 */
}

@@ -200,21 +200,21 @@ uint8_t PlsrStart(uint16_t start_seg)
{
uint16_t n;
uint16_t first_seg;
uint32_t f_chk;
uint32_t f_chk;/* 解析后的首段目标频率;此处仅作合法性检查,结果不用 */

if (g_plsr_busy != 0U)
{
return 0U;
}

n = PlsrParamGetSegCount();
n = PlsrParamGetSegCount();/*获取段的数量*/
if (n < 1U)
{
return 0U;
}
if ((start_seg < 1U) || (start_seg > n))
{
start_seg = PlsrParamGetStartSeg();
start_seg = PlsrParamGetStartSeg();/*获取起始段*/
}

first_seg = (uint16_t)(start_seg - 1U);
@@ -226,20 +226,20 @@ uint8_t PlsrStart(uint16_t start_seg)
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL);
return 0U;
}
s_continue_without_stopping = 0U;
s_next_seg_start_freq_valid = 0U;
s_next_seg_start_freq_hz = 0U;
s_continue_without_stopping = 0U;/* 清段间不停表衔接标志 */
s_next_seg_start_freq_valid = 0U;/* 清段间衔接频率有效标志 */
s_next_seg_start_freq_hz = 0U;/*段间衔接频率置零*/
/*
* 绝对原点:仅在首次 Start(或 ClearAccPulse 之后的第一次)锁定。
* 相对跑完再切绝对,仍相对「第一次启动时刻」坐标,不以当前位置重定原点。
*/
if (s_absolute_origin_locked == 0U)
{
s_absolute_origin = g_plsr_accumulated_pulses;
s_absolute_origin_locked = 1U;
s_absolute_origin = g_plsr_accumulated_pulses;/*已经累计的脉冲*/
s_absolute_origin_locked = 1U;/*绝对原点锁定标志*/
}
PlsrSignalIoClearEdges();
PlsrRunControlBeginSeg(first_seg);
PlsrSignalIoClearEdges();/*清除io信号边沿*/
PlsrRunControlBeginSeg(first_seg);/*根据段号开一段*/
return 1U;
}

@@ -290,7 +290,7 @@ uint8_t PlsrChangeFreq(uint32_t new_tgt_hz)
g_plsr_config.accel_ms, g_plsr_config.decel_ms);
s_seg_pulse_target = (int32_t)remain;
s_seg_pulses_done = 0;
PlsrRunControlRefreshProfile(0U);
PlsrRunControlRefreshProfile(0U);/*刷新下一拍频率*/
return 1U;
}

@@ -313,15 +313,17 @@ void PlsrRunControlRestoreAccPulse(int32_t acc_pulse)
/** @brief 毫秒任务节拍 */
void PlsrRunControlTickMs(void)
{
/* act时间到期或者act切段后需要保持频率*/
if (s_act_expired != 0U)
{
s_act_expired = 0U;
if ((s_state == RC_RUN) || (s_keep_freq_after_act != 0U))
{
PlsrRunControlActExpire();
PlsrRunControlActExpire();/*act时间到期处理函数*/
}
return;
}
/*wait时间到期,清标志位,规划下一段*/
if (s_wait_time_expired != 0U)
{
s_wait_time_expired = 0U;
@@ -331,28 +333,29 @@ void PlsrRunControlTickMs(void)
}
return;
}
/*方向延时直接等待*/
if (s_state == RC_DIR_WAIT)
{
/* 精确延时只靠 TIM5;此处占位,避免任务空转改状态 */
return;
}
/*运行态先处理改频请求,如果时EXT/EXT或脉冲发送完成,需要读取下降沿*/
if (s_state == RC_RUN)
{
PlsrPulseDriverApplyPending();
PlsrPulseDriverApplyPending();//消费挂起改频

if ((g_plsr_segs[g_plsr_cur_seg_idx].wait_type == PLSR_WAIT_EXT) ||
(g_plsr_segs[g_plsr_cur_seg_idx].wait_type == PLSR_WAIT_EXT_OR_DONE))
{
if (PlsrSignalIoTakeExtFalling() != 0U)
{
PlsrRunControlCutSegToNext();
PlsrRunControlCutSegToNext();/*EXT信号触发切段*/
return;
}
}
return;
}
/*等待条件状态要读取下降沿,去下一段或者结束*/
if (s_state == RC_WAIT_COND)
{
if (s_waiting_for_input_signal != 0U)
@@ -385,9 +388,9 @@ void PlsrRunControlOnDelayTimer(void)
if (s_state == RC_DIR_WAIT)
{
s_state = RC_RUN;
PlsrRunControlRefreshProfile(1U);
PlsrRunControlArmActExtOnPulseStart();
PlsrRunControlWakePost();
PlsrRunControlRefreshProfile(1U);/*刷新频率*/
PlsrRunControlArmActExtOnPulseStart();/*开始输出时:EXT 类清旧沿;ACT 类启动段内定时 */
PlsrRunControlWakePost();/*释放信号量,唤醒plsr任务*/
return;
}

@@ -686,7 +689,7 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)
uint32_t f_tgt;
uint32_t total;
PlsrSegPlanEndpoints_t endpoints;
/*如果段号大于总段数,直接结束输出*/
if (seg_idx >= PlsrParamGetSegCount())
{
PlsrRunControlFinishAll();
@@ -694,9 +697,10 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)
}

g_plsr_cur_seg_idx = seg_idx;
s_waiting_for_last_period = 0U;
cnt = g_plsr_segs[seg_idx].pulse_cnt;
s_waiting_for_last_period = 0U;/* 等末拍 UPDATE 再收尾标志 */
cnt = g_plsr_segs[seg_idx].pulse_cnt;/*读取总脉冲数*/

/*读取运行模式,绝对模式以启动位置为绝对原点*/
if (g_plsr_config.run_mode == PLSR_POS_ABSOLUTE)
{
/* 以首次启动锁定原点:move = 段目标 − 相对原点位置 */
@@ -704,7 +708,7 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)
}
else
{
move = cnt;
move = cnt;/*行对模式下位移量=脉冲数*/
}

if (move == 0)
@@ -713,14 +717,14 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)
g_plsr_busy = 1U;
s_seg_pulse_target = 0;
s_seg_pulses_done = 0;
PlsrRunControlAfterSegDone();
PlsrRunControlAfterSegDone();/*段正常结束*/
return;
}

if (move >= 0)
{
s_forward = 1U;
s_seg_pulse_target = move;
s_forward = 1U;/*设置方向标志,正向1,反向0*/
s_seg_pulse_target = move;/*脉冲目标数=移动量*/
}
else
{
@@ -732,11 +736,11 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)
if (move == (int32_t)(-2147483647L - 1L))
{
PlsrCommandSetFault(PLSR_ERR_PULSE_RANGE);
PlsrRunControlFinishAll();
PlsrRunControlFinishAll();/*全段结束*/
return;
}
s_forward = 0U;
s_seg_pulse_target = -move;
s_forward = 0U;/* 反向移动 */
s_seg_pulse_target = -move;/* 移动量负脉冲个数 */
}
/* 0x04:本段(或默认速度)频率非法 */
@@ -752,10 +756,13 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)
(void)PlsrRunControlResolveSegPlanEndpoints(seg_idx, f_tgt, &endpoints);

total = (uint32_t)s_seg_pulse_target;
/*规划本段并锁 PSC / 进初始相*/
PlsrRunControlPlanSeg(total, endpoints.freq_start_hz, f_tgt, endpoints.freq_end_hz,
endpoints.accel_ms, endpoints.decel_ms);
s_seg_pulses_done = 0;
g_plsr_busy = 1U;
s_seg_pulses_done = 0;/*已发脉冲数清零*/
g_plsr_busy = 1U;/*运行状态置1*/
{
/* 用本段结束后的坐标判 keep,与 AfterSegDone 一致;结果锁进 s_stop_after_last_pulse */
int32_t end_pos = PlsrRunControlAbsLocalPos();
@@ -774,43 +781,48 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)

if (total == 0U)
{
PlsrRunControlAfterSegDone();
PlsrRunControlAfterSegDone();/*单段正常结束*/
return;
}

/*段间不停表衔接(后续模式/ACT切段)*/
if (s_continue_without_stopping != 0U)
{
/* 分支 A:段间无缝(后续模式或 ACT切段) */
PlsrPulseDriverClearOnePulseStop();
PlsrPulseDriverClearOnePulseStop();/*清掉单脉冲停止*/
/*
* 必须先 RC_RUN 再 RefreshProfile/Start:否则冷启动首拍 UPDATE 时
* OnPulseIsr 仍见非 RUN 直接 return,影子停在起跳频,第 1、2 拍同频。
*/
s_state = RC_RUN;
s_continue_without_stopping = 0U;
s_continue_without_stopping = 0U;/*段间不停表标志置0*/
/*
* FOLLOW 真不停表:do_start=0 只改频。
* ACT 经 OPM 边界停表后 g_plsr_pwm_running 已为 0:须 Start 重开,否则无脉冲卡死。
*/
* 1需要开始pwm输出,0已经在运行。只刷新下一拍频率*/
PlsrRunControlRefreshProfile((g_plsr_pwm_running == 0U) ? 1U : 0U);
/*开始输出时:EXT 类清旧沿;ACT 类启动段内定时 */
PlsrRunControlArmActExtOnPulseStart();
}
else if ((g_plsr_direction_valid != 0U) && (s_forward == g_plsr_direction_forward))
{
/* 分支 B:真换向但本段与上一段同向,方向脚已正确,跳过延时 */
PlsrPulseDriverSetDir(s_forward);
PlsrPulseDriverSetDir(s_forward);/*跳过方向延时*/
s_state = RC_RUN;
PlsrRunControlRefreshProfile(1U);
PlsrRunControlRefreshProfile(1U);/*传1,已运行,只刷新频率*/
/*开始输出时:EXT 类清旧沿;ACT 类启动段内定时 */
PlsrRunControlArmActExtOnPulseStart();
}
else
{
/* 分支 C:需要换向或首次开跑 — 先打方向,再决定立刻开或 DIR_WAIT */
PlsrPulseDriverSetDir(s_forward);
PlsrPulseDriverSetDir(s_forward);/*设置方向*/
if (g_plsr_config.dir_delay_ms == 0U)
{
s_state = RC_RUN;
/*传1,已运行,只刷新频率*/
PlsrRunControlRefreshProfile(1U);
/*开始输出时:EXT 类清旧沿;ACT 类启动段内定时 */
PlsrRunControlArmActExtOnPulseStart();
}
else
@@ -820,9 +832,11 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)
*/
s_state = RC_DIR_WAIT;
PlsrRunControlWakeDrain();
/*设置方向延时*/
PlsrSignalIoScheduleDelayMs((uint32_t)g_plsr_config.dir_delay_ms);
if (g_plsr_accel_runtime.cur_freq_hz >= 1U)
{
/*换向延时期间预装寄存器、CEN 保持关 */
PlsrPulseDriverPrepare(g_plsr_accel_runtime.cur_freq_hz);
}
}
@@ -941,18 +955,21 @@ static void PlsrRunControlArmActExtOnPulseStart(void)
{
uint16_t act_time_ms;
/*EXT信号/EXT或脉冲发送完成,清掉X4,X5信号的边沿,防止误触*/
if ((g_plsr_segs[g_plsr_cur_seg_idx].wait_type == PLSR_WAIT_EXT) ||
(g_plsr_segs[g_plsr_cur_seg_idx].wait_type == PLSR_WAIT_EXT_OR_DONE))
{
PlsrSignalIoClearEdges();
}
s_act_timer_armed = 0U;
s_act_expired = 0U;
s_act_waiting_for_pulse_boundary = 0U;
s_keep_freq_after_act = 0U;
s_wait_time_expired = 0U;
/*清掉ACT定时的相关标志*/
s_act_timer_armed = 0U;/*启用定时器*/
s_act_expired = 0U;/*act定时到期*/
s_act_waiting_for_pulse_boundary = 0U;/*等待脉冲边界*/
s_keep_freq_after_act = 0U;/*act切断后保持频率*/
s_wait_time_expired = 0U;/*wait时间到期标志*/
/*act时间切段置标志位,开定时*/
if (g_plsr_segs[g_plsr_cur_seg_idx].wait_type == PLSR_WAIT_ACT)
{
act_time_ms = g_plsr_segs[g_plsr_cur_seg_idx].act_ms;
@@ -994,9 +1011,9 @@ static void PlsrRunControlActExpire(void)
s_act_expired = 0U;
s_wait_time_expired = 0U;
s_state = RC_IDLE;
/*同向且有有效频率则不停表衔接,否则停表清链,传入1需要频率衔接*/
PlsrRunControlApplyKeepOrStop(1U);
s_keep_freq_after_act = 0U;
s_keep_freq_after_act = 0U;/*保持频率衔接标志位置0*/

PlsrRunControlGotoNextOrFinish(g_plsr_cur_seg_idx);
}
@@ -1063,7 +1080,7 @@ static void PlsrRunControlEnterPostWaitOrNext(void)
}

/**
* @brief 段正常结束:诊断 → 链式频率 → FOLLOW keep 或停表 → EnterPostWaitOrNext
* @brief 段正常结束:诊断 → 链式频率 → FOLLOW keep 或停表 → EnterPostWaitOrNext
*/
static void PlsrRunControlAfterSegDone(void)
{
@@ -1210,8 +1227,8 @@ static void PlsrRunControlOnApproachDone(void)

/**
* 解析段目标频率。
* freq_hz==0 用公共默认速度;结果须落在 [1, 100000],否则返回 0(调用方写 0x04)。
*/
* freq_hz==0 用返回default_freq;结果须落在 [1, 100000],否则返回 0(调用方写 0x04)。
* 返回1/0表示频率能不能用,能用返回1,不能用返回0*/
static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz,
uint32_t default_spd,
uint32_t *out_hz)
@@ -1220,22 +1237,22 @@ static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz,

if (freq_hz < 0)
{
return 0U;
return 0U;/*频率小于0,直接结束*/
}
if (freq_hz == 0)
{
f = default_spd;
f = default_spd;/*频率为零,替换为默认速度*/
}
else
{
f = (uint32_t)freq_hz;
f = (uint32_t)freq_hz;/*频率不为零,替换为传入的频率*/
}
/* 合法范围:1Hz ~ 100kHz(含) */
if ((f < 1U) || (f > 100000U))
{
return 0U;
return 0U;/*频率范围不合法直接结束*/
}
*out_hz = f;
*out_hz = f;/*将最终的频率传回去*/
return 1U;
}

@@ -1409,7 +1426,7 @@ static void PlsrRunControlEnterConstHoldIsr(void)
}

/**
* 任务侧:按当前段内相 s_phase,决定开表/改频用哪个频率。
* 任务侧:按当前段内相 s_phase,决定开表/改频用哪个频率。刷新频率
* @param do_start 1=需要 Start PWM(RefreshProfile(1));0=已在跑只改频
*/
static void PlsrRunControlRefreshProfile(uint8_t do_start)
@@ -1507,14 +1524,14 @@ static uint8_t PlsrRunControlResolveSegPlanEndpoints(uint16_t seg_idx, uint32_t
endpoints->accel_ms = g_plsr_config.accel_ms;
endpoints->decel_ms = g_plsr_config.decel_ms;

if ((s_continue_without_stopping != 0U) && (g_plsr_output_freq_hz >= 1U))
{
endpoints->freq_start_hz = g_plsr_output_freq_hz;
}
else if ((g_plsr_pwm_running != 0U) && (g_plsr_output_freq_hz >= 1U))
/*不停表衔接且输出频率>1或者下一段运行中,下一段的起始频率为当前输出频率*/
if (((s_continue_without_stopping != 0U) || (g_plsr_pwm_running != 0U))
&& (g_plsr_output_freq_hz >= 1U))
{
endpoints->freq_start_hz = g_plsr_output_freq_hz;
}
/*如果下一段的起始频率有效且>1,下一段的起始频率为起始频率 */
else if ((s_next_seg_start_freq_valid != 0U) && (s_next_seg_start_freq_hz >= 1U))
{
/* 完成模式段末停表后:用本段落地频作起速(如 EXT_OR_DONE 的匀速峰值) */
@@ -1596,6 +1613,7 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
uint32_t f_min;
uint32_t f_max;

/*传给曲线规划模块进行曲线规划*/
PlsrAccelCurvePlan(&g_plsr_accel_plan,
total,
f_from,
@@ -1616,7 +1634,7 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
PlsrCommandSetFault(PLSR_ERR_FREQ_UNREACH);
}

g_plsr_accel_runtime.total_pulses = 0U;
g_plsr_accel_runtime.total_pulses = 0U;/*开始运行前当前相计划步进的脉冲数清零*/

/* S/正弦:在任务上下文预建频率表,ISR 只查表 */
PlsrAccelPrebuildFreqTables(&g_plsr_accel_plan);
@@ -1629,46 +1647,50 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
/* 本段可能出现的最低/最高频率,取 入口、目标、出口 三者的 min/max */
f_min = g_plsr_accel_plan.target_freq_hz;
f_max = g_plsr_accel_plan.target_freq_hz;
/*先找入口的最大最小频率*/
if (f_start > f_max)
{
f_max = f_start;
f_max = f_start;/*起始频率大于目标频率时,最大频率用起始频率*/
}
if (f_start >= 1U)
{
if (f_start < f_min)
{
f_min = f_start;
f_min = f_start;/*起始频率小于目标频率,最小频率使用起始频率*/
}
}
else
{
f_min = 1U;
f_min = 1U;/* 否则最小频率为1 */
}
/*找出口的最大最小频率*/
if (g_plsr_accel_plan.end_freq_hz > f_max)
{
f_max = g_plsr_accel_plan.end_freq_hz;
f_max = g_plsr_accel_plan.end_freq_hz;/*出口频率大于最大值,则成为最大值*/
}
if (g_plsr_accel_plan.end_freq_hz >= 1U)
{
if (g_plsr_accel_plan.end_freq_hz < f_min)
{
f_min = g_plsr_accel_plan.end_freq_hz;
f_min = g_plsr_accel_plan.end_freq_hz;/*出口频率小于小值,则成为最小值*/
}
}
else
{
if (f_min > 1U)
{
f_min = 1U;
f_min = 1U;/* 否则,最小值为1 */
}
}
if (f_min < 1U)
{
f_min = 1U;
f_min = 1U;/*如果最小值小于1,则最小值改为1*/
}
if (f_max < f_min)
{
f_max = f_min;
f_max = f_min;/*如果找出来的最大值小于最小值,让最大值等于最小值*/
}
/* 后续同向不停表时 PWM 仍在跑:禁止重锁 PSC */
if (g_plsr_pwm_running == 0U)
@@ -1687,12 +1709,12 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
}
else if (f_start == g_plsr_accel_plan.target_freq_hz)
{
s_phase = PH_CONST;
s_phase = PH_CONST;/*匀速段*/
PlsrAccelBeginConstSpeed(&g_plsr_accel_runtime, &g_plsr_accel_plan);
}
else
{
s_phase = PH_APPROACH;
s_phase = PH_APPROACH;/*加速段*/
PlsrAccelBeginAccel(&g_plsr_accel_runtime, &g_plsr_accel_plan);
}
}


Завантаження…
Відмінити
Зберегти