소스 검색

补充了部分注释

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]; g_modbus_tx_buf[5] = frame[5];
AppendCrcAndSend(g_modbus_tx_buf, 6U); AppendCrcAndSend(g_modbus_tx_buf, 6U);


/*统计接受帧数,收满释放信号量*/
PlsrParamBlockOnHoldWrite(startAddr, quantity); PlsrParamBlockOnHoldWrite(startAddr, quantity);
/* 动态改频率 */
PlsrCommandOnSegFreqHoldWrite(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 */ /* 公共 API */
/*============================================================================*/ /*============================================================================*/


/*计算起始频率*/
uint32_t PlsrAccelCurveResolveStartHz(uint32_t configured_freq_hz, uint32_t PlsrAccelCurveResolveStartHz(uint32_t configured_freq_hz,
uint32_t target_freq_hz, uint32_t target_freq_hz,
uint32_t default_speed_hz, uint32_t default_speed_hz,
uint32_t accel_time_ms, uint32_t accel_time_ms,
uint32_t decel_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, return PlsrAccelCurveResolveBoundaryFreq(configured_freq_hz, target_freq_hz, default_speed_hz,
accel_time_ms, decel_time_ms, 1U); accel_time_ms, decel_time_ms, 1U);
} }


/*计算终止频率*/
uint32_t PlsrAccelCurveResolveEndHz(uint32_t configured_freq_hz, uint32_t PlsrAccelCurveResolveEndHz(uint32_t configured_freq_hz,
uint32_t target_freq_hz, uint32_t target_freq_hz,
uint32_t default_speed_hz, uint32_t default_speed_hz,
uint32_t accel_time_ms, uint32_t accel_time_ms,
uint32_t decel_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, return PlsrAccelCurveResolveBoundaryFreq(configured_freq_hz, target_freq_hz, default_speed_hz,
accel_time_ms, decel_time_ms, 0U); accel_time_ms, decel_time_ms, 0U);
} }


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


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


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


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


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


plan->start_freq_hz = start_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->accel_rate_hz_per_s = accel_rate_hz_per_s;
plan->decel_rate_hz_per_s = decel_rate_hz_per_s; plan->decel_rate_hz_per_s = decel_rate_hz_per_s;


/*按峰值重算加速/减速脉冲预算*/
PlsrAccelCurveCalcPhasePulses(start_freq_hz, PlsrAccelCurveCalcPhasePulses(start_freq_hz,
peak_freq_hz, peak_freq_hz,
end_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 accel_hz_per_s;
uint32_t jump_freq_hz; uint32_t jump_freq_hz;


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


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


ramp_time_ms = (resolving_start != 0U) ? accel_time_ms : decel_time_ms; ramp_time_ms = (resolving_start != 0U) ? accel_time_ms : decel_time_ms;
/*计算加速度*/
accel_hz_per_s = accel_hz_per_s =
PlsrAccelCurveCalcRate(default_speed_hz, PlsrAccelCurveCalcRate(default_speed_hz,
configured_freq_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; return (configured_freq_hz >= 1U) ? configured_freq_hz : target_freq_hz;
} }


/*按运动学公式计算起跳频率*/
jump_freq_hz = PlsrAccelCurveCalcJumpFreq(configured_freq_hz, accel_hz_per_s); 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; return jump_freq_hz;
} }


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


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


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


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


/*使用的脉冲数至少为1个*/
if (runtime.completed_pulses == 0U) if (runtime.completed_pulses == 0U)
{ {
return 1U; 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, static uint32_t PlsrAccelCurveCalcRampPulses(uint32_t start_freq_hz, uint32_t end_freq_hz,
uint32_t accel_hz_per_s, uint32_t accel_hz_per_s,
PlsrAccelMode_e curve_mode) PlsrAccelMode_e curve_mode)
@@ -1465,6 +1484,7 @@ static void PlsrAccelCurveCalcPhasePulses(uint32_t start_freq_hz,
uint32_t *accel_pulses, uint32_t *accel_pulses,
uint32_t *decel_pulses) uint32_t *decel_pulses)
{ {
/*如果起始频率 > 峰值频率,加速脉冲数*/
if (start_freq_hz > peak_freq_hz) if (start_freq_hz > peak_freq_hz)
{ {
*accel_pulses = PlsrAccelCurveCalcRampPulses(start_freq_hz, peak_freq_hz, decel_rate_hz_per_s, curve_mode); *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) static void PlsrAccelRuntimeCalcTimes(PlsrAccelRuntime_t *runtime)
{ {
runtime->elapsed_time_us = 0U; runtime->elapsed_time_us = 0U;
@@ -1541,15 +1562,18 @@ static void PlsrAccelRuntimeCalcTimes(PlsrAccelRuntime_t *runtime)
runtime->const_accel_time_us = 0U; runtime->const_accel_time_us = 0U;
runtime->ramp_time_us = 0U; runtime->ramp_time_us = 0U;


/*加速度小于1,或者起始频率 = 终止频率,直接结束*/
if ((runtime->accel_hz_per_s < 1U) || (runtime->start_freq_hz == runtime->end_freq_hz)) if ((runtime->accel_hz_per_s < 1U) || (runtime->start_freq_hz == runtime->end_freq_hz))
{ {
return; return;
} }
/*S曲线计算时间*/
if (runtime->curve_mode == PLSR_ACCEL_S) if (runtime->curve_mode == PLSR_ACCEL_S)
{ {
PlsrAccelCurveCalcSCurveTimes(runtime->start_freq_hz, runtime->end_freq_hz, runtime->accel_hz_per_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); &runtime->jerk_time_us, &runtime->const_accel_time_us, &runtime->ramp_time_us);
} }
/* 正弦曲线计算时间*/
else if (runtime->curve_mode == PLSR_ACCEL_SINE) 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); 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->cur_freq_hz = start_freq_hz;
runtime->completed_pulses = 0U; runtime->completed_pulses = 0U;
runtime->total_pulses = total_pulses; runtime->total_pulses = total_pulses;
/*终点 > 起点,加速过程*/
runtime->freq_rising = runtime->freq_rising =
(end_freq_hz >= start_freq_hz) ? 1U : 0U; (end_freq_hz >= start_freq_hz) ? 1U : 0U;
/*加速度,上升用加速斜率,下降用减速斜率*/
runtime->accel_hz_per_s = runtime->accel_hz_per_s =
(runtime->freq_rising != 0U) ? (runtime->freq_rising != 0U) ?
accel_rate_hz_per_s : decel_rate_hz_per_s; accel_rate_hz_per_s : decel_rate_hz_per_s;
/*曲线模式*/
runtime->curve_mode = curve_mode; runtime->curve_mode = curve_mode;
/* 1=当前相仍在运行 */
runtime->is_active = ((total_pulses > 0U) && runtime->is_active = ((total_pulses > 0U) &&
(start_freq_hz != end_freq_hz)) ? 1U : 0U; (start_freq_hz != end_freq_hz)) ? 1U : 0U;
runtime->freq_table_id = 0U; runtime->freq_table_id = 0U;
runtime->table_length = 0U; runtime->table_length = 0U;
runtime->table_stride = 1U; 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) if ((ctrl & PLSR_CTRL_BIT_STOP) != 0U)
{ {
PlsrStop();
PlsrStop();/*停止输出*/
} }


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


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


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

+ 2
- 2
plsr/plsr.c 파일 보기

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


PlsrRunControlTickMs(); /* 优先:WAIT/换向到期立刻开表 */
PlsrRunControlTickMs(); /* 处理延时/外部信号输入,优先:WAIT/换向到期立刻开表 */
PlsrSignalIoDebouncePoll(); /* OS 节拍消抖确认 */ PlsrSignalIoDebouncePoll(); /* OS 节拍消抖确认 */
PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 */
PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 ,决定是否开pwm输出*/
PlsrPersistTickMonitor(); /* 监控区:运行态→hold→BKP(每 OS 节拍) */ 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); 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) 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)) if ((htim == (TIM_HandleTypeDef *)0) || (htim->Instance == (TIM_TypeDef *)0))
{ {
return; return;
@@ -429,7 +425,9 @@ static void PlsrPulseDriverCalcPscArr(uint32_t clk_hz, uint32_t freq_hz,
PlsrPulseDriverCalcArrWithPsc(clk_hz, freq_hz, p, arr, ccr); 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) void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
{ {
uint32_t ticks_max; 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_max;
uint32_t psc_div_min; uint32_t psc_div_min;
uint32_t div; uint32_t div;
/*获取Y端子的时钟频率,Y0/Y1为168MHz,Y2为84MHz */
uint32_t clk_hz = PlsrPulseDriverTimClkHz( uint32_t clk_hz = PlsrPulseDriverTimClkHz(
PlsrPulseDriverHtimByY(PlsrPulseDriverSelectY())); PlsrPulseDriverHtimByY(PlsrPulseDriverSelectY()));


@@ -448,6 +447,7 @@ void PlsrPulseDriverLockPscRange(uint32_t f_min_hz, uint32_t f_max_hz)
{ {
f_max_hz = 1U; f_max_hz = 1U;
} }
/*如果最小值小于最大值,则交换最小值与最大值*/
if (f_max_hz < f_min_hz) if (f_max_hz < f_min_hz)
{ {
uint32_t temp = 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; 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) if (ticks_max < 2UL)
{ {
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; 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; psc_div_min = (ticks_max + 65535UL) / 65536UL;
if (psc_div_min < 1UL) if (psc_div_min < 1UL)
{ {
psc_div_min = 1UL; psc_div_min = 1UL;
} }
/* psc = tick / (ARR + 1) ,当arr+1最小时,psc为最大值,再大就不满足乘积=tick*/
psc_div_max = ticks_min / 2UL; psc_div_max = ticks_min / 2UL;
if (psc_div_max < 1UL) if (psc_div_max < 1UL)
{ {
psc_div_max = 1UL;
psc_div_max = 1UL;/* psc的最大值最小为1,最小值可以为0 */
} }


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


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


/** @brief OPM 段末 UPDATE 后立刻拉低,消除 CNT 回零 PWM1 假上升沿 */ /** @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 uint32_t g_plsr_output_freq_hz;
extern volatile uint8_t g_plsr_pwm_running; extern volatile uint8_t g_plsr_pwm_running;
extern uint8_t g_plsr_direction_forward; extern uint8_t g_plsr_direction_forward;
extern uint8_t g_plsr_direction_valid;
extern uint8_t g_plsr_direction_valid;/*方向脚有效*/


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


+ 139
- 117
plsr/run_control/plsr_run_control.c 파일 보기

@@ -38,28 +38,28 @@ typedef enum {
PH_DECEL PH_DECEL
} RunPhase_e; } 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 的段端点 */ /* 策略层解析后交给 PlanSeg 的段端点 */
typedef struct { typedef struct {
@@ -121,30 +121,30 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
/** @brief 运行控制初始化 */ /** @brief 运行控制初始化 */
void PlsrRunControlInit(void) 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 创建 */ /* s_wake_sem 在 OSInit 后由 WakeInit 创建 */
} }


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


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


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


first_seg = (uint16_t)(start_seg - 1U); first_seg = (uint16_t)(start_seg - 1U);
@@ -226,20 +226,20 @@ uint8_t PlsrStart(uint16_t start_seg)
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL);
return 0U; 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 之后的第一次)锁定。 * 绝对原点:仅在首次 Start(或 ClearAccPulse 之后的第一次)锁定。
* 相对跑完再切绝对,仍相对「第一次启动时刻」坐标,不以当前位置重定原点。 * 相对跑完再切绝对,仍相对「第一次启动时刻」坐标,不以当前位置重定原点。
*/ */
if (s_absolute_origin_locked == 0U) 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; return 1U;
} }


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


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


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


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


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


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


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


total = (uint32_t)s_seg_pulse_target; total = (uint32_t)s_seg_pulse_target;
/*规划本段并锁 PSC / 进初始相*/
PlsrRunControlPlanSeg(total, endpoints.freq_start_hz, f_tgt, endpoints.freq_end_hz, PlsrRunControlPlanSeg(total, endpoints.freq_start_hz, f_tgt, endpoints.freq_end_hz,
endpoints.accel_ms, endpoints.decel_ms); 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 */ /* 用本段结束后的坐标判 keep,与 AfterSegDone 一致;结果锁进 s_stop_after_last_pulse */
int32_t end_pos = PlsrRunControlAbsLocalPos(); int32_t end_pos = PlsrRunControlAbsLocalPos();
@@ -774,43 +781,48 @@ static void PlsrRunControlBeginSeg(uint16_t seg_idx)


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

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


PlsrRunControlGotoNextOrFinish(g_plsr_cur_seg_idx); 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) 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, static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz,
uint32_t default_spd, uint32_t default_spd,
uint32_t *out_hz) uint32_t *out_hz)
@@ -1220,22 +1237,22 @@ static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz,


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


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


/** /**
* 任务侧:按当前段内相 s_phase,决定开表/改频用哪个频率。
* 任务侧:按当前段内相 s_phase,决定开表/改频用哪个频率。刷新频率
* @param do_start 1=需要 Start PWM(RefreshProfile(1));0=已在跑只改频 * @param do_start 1=需要 Start PWM(RefreshProfile(1));0=已在跑只改频
*/ */
static void PlsrRunControlRefreshProfile(uint8_t do_start) 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->accel_ms = g_plsr_config.accel_ms;
endpoints->decel_ms = g_plsr_config.decel_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; 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)) else if ((s_next_seg_start_freq_valid != 0U) && (s_next_seg_start_freq_hz >= 1U))
{ {
/* 完成模式段末停表后:用本段落地频作起速(如 EXT_OR_DONE 的匀速峰值) */ /* 完成模式段末停表后:用本段落地频作起速(如 EXT_OR_DONE 的匀速峰值) */
@@ -1596,6 +1613,7 @@ static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
uint32_t f_min; uint32_t f_min;
uint32_t f_max; uint32_t f_max;


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


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


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


불러오는 중...
취소
저장