Procházet zdrojové kódy

最后一个脉冲下降沿强制拉低电平,避免出现极窄的脉冲

Signed-off-by: hanyongwei <2043702190@qq.com>
dev1
hanyongwei před 3 týdny
rodič
revize
2f3ae275d9
6 změnil soubory, kde provedl 138 přidání a 42 odebrání
  1. +1
    -0
      iar/plsr.dep
  2. +35
    -35
      plsr/param/plsr_param.c
  3. +1
    -1
      plsr/plsr.c
  4. +80
    -1
      plsr/pulse_driver/plsr_pulse_driver.c
  5. +12
    -0
      plsr/pulse_driver/plsr_pulse_driver.h
  6. +9
    -5
      plsr/run_control/plsr_run_control.c

+ 1
- 0
iar/plsr.dep Zobrazit soubor

@@ -474,6 +474,7 @@
<file>$PROJ_DIR$\Debug\Obj\stm32f4xx_hal_sdram.xcl</file> <file>$PROJ_DIR$\Debug\Obj\stm32f4xx_hal_sdram.xcl</file>
<file>$PROJ_DIR$\Debug\Obj\startup_stm32f407xx.o</file> <file>$PROJ_DIR$\Debug\Obj\startup_stm32f407xx.o</file>
<file>$PROJ_DIR$\Debug\Obj\os_cpu_c.xcl</file> <file>$PROJ_DIR$\Debug\Obj\os_cpu_c.xcl</file>
<file>$PROJ_DIR$\..\..\..\Desktop\plsr\app\main.c</file>
</outputs> </outputs>
<file> <file>
<name>[ROOT_NODE]</name> <name>[ROOT_NODE]</name>


+ 35
- 35
plsr/param/plsr_param.c Zobrazit soubor

@@ -39,41 +39,41 @@ static volatile uint8_t s_xfer_active; /* 1=正在接收一批分帧 */
* @brief 出厂默认参数(见 plsr_param.h) * @brief 出厂默认参数(见 plsr_param.h)
* @note 与上位机 initCommonDefaults 约定一致,便于未写 PLC 时行为可预期 * @note 与上位机 initCommonDefaults 约定一致,便于未写 PLC 时行为可预期
*/ */
void PlsrParamInitDefault(void)
{
uint16_t i;
memset(&s_cfg, 0, sizeof(s_cfg));
memset(s_seg, 0, sizeof(s_seg));
/* 与上位机默认约定一致;真正运行参数由 ApplyFromHold / PersistLoad 覆盖 */
s_cfg.pulse_y = 0U;
s_cfg.dir_y = 3U;
s_cfg.wait_x_sel = 0U;
s_cfg.ext_x_sel = 0U;
s_cfg.send_mode = PLSR_SEND_COMPLETE;
s_cfg.dir_delay_ms = 10U;
s_cfg.dir_logic = PLSR_DIR_LOGIC_POS;
s_cfg.accel_mode = PLSR_ACCEL_LINEAR;
s_cfg.run_mode = PLSR_POS_RELATIVE;
s_cfg.seg_count = 0U;
s_cfg.start_seg = 1U;
s_cfg.default_speed = 1000UL;
s_cfg.start_speed = 0UL;
s_cfg.end_speed = 0UL;
s_cfg.accel_ms = 100U;
s_cfg.decel_ms = 100U;
for (i = 0U; i < PLSR_SEG_MAX; i++)
{
s_seg[i].freq_hz = 0;
s_seg[i].pulse_cnt = 0;
s_seg[i].wait_type = PLSR_WAIT_TIME;
s_seg[i].wait_ms = 0U;
s_seg[i].act_ms = 0U;
s_seg[i].jump_seg = 0U;
}
}
//void PlsrParamInitDefault(void)
//{
// uint16_t i;
//
// memset(&s_cfg, 0, sizeof(s_cfg));
// memset(s_seg, 0, sizeof(s_seg));
//
// /* 与上位机默认约定一致;真正运行参数由 ApplyFromHold / PersistLoad 覆盖 */
// s_cfg.pulse_y = 0U;
// s_cfg.dir_y = 3U;
// s_cfg.wait_x_sel = 0U;
// s_cfg.ext_x_sel = 0U;
// s_cfg.send_mode = PLSR_SEND_COMPLETE;
// s_cfg.dir_delay_ms = 10U;
// s_cfg.dir_logic = PLSR_DIR_LOGIC_POS;
// s_cfg.accel_mode = PLSR_ACCEL_LINEAR;
// s_cfg.run_mode = PLSR_POS_RELATIVE;
// s_cfg.seg_count = 0U;
// s_cfg.start_seg = 1U;
// s_cfg.default_speed = 1000UL;
// s_cfg.start_speed = 0UL;
// s_cfg.end_speed = 0UL;
// s_cfg.accel_ms = 100U;
// s_cfg.decel_ms = 100U;
//
// for (i = 0U; i < PLSR_SEG_MAX; i++)
// {
// s_seg[i].freq_hz = 0;
// s_seg[i].pulse_cnt = 0;
// s_seg[i].wait_type = PLSR_WAIT_TIME;
// s_seg[i].wait_ms = 0U;
// s_seg[i].act_ms = 0U;
// s_seg[i].jump_seg = 0U;
// }
//}


/** @return 公共参数映像指针(见 plsr_param.h) */ /** @return 公共参数映像指针(见 plsr_param.h) */
PlsrCfg_t *PlsrParamGetCfg(void) PlsrCfg_t *PlsrParamGetCfg(void)


+ 1
- 1
plsr/plsr.c Zobrazit soubor

@@ -29,7 +29,7 @@
*/ */
void PlsrInit(void) void PlsrInit(void)
{ {
PlsrParamInitDefault();
//PlsrParamInitDefault();
PlsrPersistLoad(); /* BKPSRAM 稀疏映像 → g_hold_reg */ PlsrPersistLoad(); /* BKPSRAM 稀疏映像 → g_hold_reg */
(void)PlsrParamBlockApplyFromHold(); (void)PlsrParamBlockApplyFromHold();
PlsrPulseDriverInit(); PlsrPulseDriverInit();


+ 80
- 1
plsr/pulse_driver/plsr_pulse_driver.c Zobrazit soubor

@@ -55,6 +55,7 @@ static volatile uint8_t s_req_pending;
* 1=DIR_WAIT 已装载寄存器且 CEN 关:到期 Commit 前必须 CNT=0 再开 PWM。 * 1=DIR_WAIT 已装载寄存器且 CEN 关:到期 Commit 前必须 CNT=0 再开 PWM。
*/ */
static uint8_t s_regs_prepared; static uint8_t s_regs_prepared;
static volatile uint8_t s_seg_end_fall_armed; /* 1=末拍 CC1 下降沿后强制拉低 */


/*============================================================================*/ /*============================================================================*/
/* 路选择 / 时钟 / GPIO */ /* 路选择 / 时钟 / GPIO */
@@ -121,6 +122,36 @@ static void PlsrPulseDriverDirGpioInit(void)
* HAL_TIM_PWM_Stop 会清 CC1E,脚变成 AF 高阻,飞线接地的沿会耦合出极短脉冲。 * HAL_TIM_PWM_Stop 会清 CC1E,脚变成 AF 高阻,飞线接地的沿会耦合出极短脉冲。
* Forced inactive + 通道保持使能:TIM 推挽把脚主动拉低(段间空闲低)。 * Forced inactive + 通道保持使能:TIM 推挽把脚主动拉低(段间空闲低)。
*/ */
static void PlsrPulseDriverClearSegEndFallArm(TIM_HandleTypeDef *htim)
{
s_seg_end_fall_armed = 0U;
if ((htim == (TIM_HandleTypeDef *)0) || (htim->Instance == (TIM_TypeDef *)0))
{
return;
}
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
__HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC1);
}

/**
* 末拍下降沿:只切 Forced inactive 拉低,CEN/OPM/UPDATE 继续跑到周期结束。
*/
static void PlsrPulseDriverOcForceLowKeepRun(TIM_HandleTypeDef *htim)
{
uint32_t ccmr;

if ((htim == (TIM_HandleTypeDef *)0) || (htim->Instance == (TIM_TypeDef *)0))
{
return;
}

ccmr = htim->Instance->CCMR1;
ccmr &= (uint32_t)(~TIM_CCMR1_OC1M);
ccmr |= TIM_OCMODE_FORCED_INACTIVE;
htim->Instance->CCMR1 = ccmr;
htim->Instance->CCER |= TIM_CCER_CC1E;
}

static void PlsrPulseDriverOcHoldLow(TIM_HandleTypeDef *htim) static void PlsrPulseDriverOcHoldLow(TIM_HandleTypeDef *htim)
{ {
uint32_t ccmr; uint32_t ccmr;
@@ -131,6 +162,7 @@ static void PlsrPulseDriverOcHoldLow(TIM_HandleTypeDef *htim)
} }


__HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE); __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE);
PlsrPulseDriverClearSegEndFallArm(htim);
htim->Instance->CR1 &= (uint32_t)(~(TIM_CR1_CEN | TIM_CR1_OPM)); htim->Instance->CR1 &= (uint32_t)(~(TIM_CR1_CEN | TIM_CR1_OPM));


ccmr = htim->Instance->CCMR1; ccmr = htim->Instance->CCMR1;
@@ -803,7 +835,9 @@ void PlsrPulseDriverStop(void)
s_last_arr = 0xFFFFFFFFUL; s_last_arr = 0xFFFFFFFFUL;
} }


/** @brief 武装 OPM 段末停表(见 plsr_pulse_driver.h) */
/**
* @brief 武装 OPM 段末停表(见 plsr_pulse_driver.h)
*/
void PlsrPulseDriverArmOnePulseStop(void) void PlsrPulseDriverArmOnePulseStop(void)
{ {
TIM_HandleTypeDef *htim = s_active_htim; TIM_HandleTypeDef *htim = s_active_htim;
@@ -816,6 +850,38 @@ void PlsrPulseDriverArmOnePulseStop(void)
htim->Instance->CR1 |= TIM_CR1_OPM; htim->Instance->CR1 |= TIM_CR1_OPM;
} }


/**
* @brief 段末停表:OPM + 末拍 CC1 下降沿立刻拉低(见 plsr_pulse_driver.h)
*/
void PlsrPulseDriverArmSegEndStop(void)
{
TIM_HandleTypeDef *htim = s_active_htim;

if (htim == (TIM_HandleTypeDef *)0)
{
return;
}

htim->Instance->CR1 |= TIM_CR1_OPM;
s_seg_end_fall_armed = 1U;
__HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC1);
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
}

/** @brief HAL PWM 脉宽结束(CC1 匹配 ≈ 下降沿) */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
if ((s_seg_end_fall_armed == 0U) ||
(htim != s_active_htim) ||
(PlsrPulseDriverIsPulseTim(htim->Instance) == 0U))
{
return;
}

PlsrPulseDriverClearSegEndFallArm(htim);
PlsrPulseDriverOcForceLowKeepRun(htim);
}

/** @brief 取消 OPM(见 plsr_pulse_driver.h) */ /** @brief 取消 OPM(见 plsr_pulse_driver.h) */
void PlsrPulseDriverClearOnePulseStop(void) void PlsrPulseDriverClearOnePulseStop(void)
{ {
@@ -826,4 +892,17 @@ void PlsrPulseDriverClearOnePulseStop(void)
return; return;
} }
htim->Instance->CR1 &= (uint32_t)(~TIM_CR1_OPM); htim->Instance->CR1 &= (uint32_t)(~TIM_CR1_OPM);
PlsrPulseDriverClearSegEndFallArm(htim);
}

/** @brief OPM 段末 UPDATE 后立刻拉低,消除 CNT 回零 PWM1 假上升沿(见 plsr_pulse_driver.h) */
void PlsrPulseDriverHoldOutputLow(void)
{
TIM_HandleTypeDef *htim = s_active_htim;

if (htim == (TIM_HandleTypeDef *)0)
{
return;
}
PlsrPulseDriverStopHtim(htim);
} }

+ 12
- 0
plsr/pulse_driver/plsr_pulse_driver.h Zobrazit soubor

@@ -106,11 +106,23 @@ void PlsrPulseDriverStop(void);
*/ */
void PlsrPulseDriverArmOnePulseStop(void); void PlsrPulseDriverArmOnePulseStop(void);


/**
* @brief 段末停表:OPM 等周期结束 + CC1 下降沿立刻 Forced 拉低
* @note 仅非 FOLLOW-keep 段末使用;ACT 切段仍用 ArmOnePulseStop
*/
void PlsrPulseDriverArmSegEndStop(void);

/** /**
* @brief 取消单脉冲停表(后续模式同向衔接 / CutSeg keep 时) * @brief 取消单脉冲停表(后续模式同向衔接 / CutSeg keep 时)
*/ */
void PlsrPulseDriverClearOnePulseStop(void); void PlsrPulseDriverClearOnePulseStop(void);


/**
* @brief 立即将当前活动路输出强制拉低(Forced inactive),不关其它路
* @note ISR 安全;OPM 段末 UPDATE 后 CNT 回零时 PWM1 可能短暂为高,须先于收尾调用
*/
void PlsrPulseDriverHoldOutputLow(void);

/** /**
* @brief 判断 instance 是否为本模块脉冲 TIM * @brief 判断 instance 是否为本模块脉冲 TIM
* @return 1=TIM10/11/13;0=否 * @return 1=TIM10/11/13;0=否


+ 9
- 5
plsr/run_control/plsr_run_control.c Zobrazit soubor

@@ -31,8 +31,8 @@
* 减速在 remain==dec_n+1 切入;纯减速开表再预装一拍。 * 减速在 remain==dec_n+1 切入;纯减速开表再预装一拍。
* *
* 【段末停表】非 FOLLOW-keep 时开段锁 s_seg_end_opm: * 【段末停表】非 FOLLOW-keep 时开段锁 s_seg_end_opm:
* UPDATE≈上升沿;s_done 到 target 时武装 OPM,末拍整周期跑完后下一 UPDATE
* 再 AfterSegDone 且不再 ++ → 末拍完整且不多 1。FOLLOW-keep 到点立刻衔接。
* UPDATE≈上升沿;s_done 到 target 时 ArmSegEndStop(OPM+CC1 末拍下降沿拉低),
* 周期 UPDATE HoldOutputLow + AfterSegDone 且不再 ++。FOLLOW-keep 到点立刻衔接。
* *
* 【故障诊断 0x2006】(PlsrCommandSetFault,告警码 1~3 不停机;4 禁止启动) * 【故障诊断 0x2006】(PlsrCommandSetFault,告警码 1~3 不停机;4 禁止启动)
* 0x01 段结束 AfterSegDone:s_done != s_target * 0x01 段结束 AfterSegDone:s_done != s_target
@@ -1717,6 +1717,11 @@ void PlsrRunControlOnPulseIsr(void)
{ {
s_last_period_wait = 0U; s_last_period_wait = 0U;
s_act_cut_pending = 0U; s_act_cut_pending = 0U;
/*
* 末拍下降沿已在 CC1 中断拉低;本 UPDATE 为 OPM 周期结束,不再 ++。
* 再 HoldOutputLow 完整停表,交 AfterSegDone。
*/
PlsrPulseDriverHoldOutputLow();
PlsrRunControlAfterSegDone(); PlsrRunControlAfterSegDone();
return; return;
} }
@@ -1753,10 +1758,9 @@ void PlsrRunControlOnPulseIsr(void)
{ {
/* /*
* 本 UPDATE = 末拍上升沿,已计入 target。 * 本 UPDATE = 末拍上升沿,已计入 target。
* 武装 OPM:本周期完整跑完后下一 UPDATE 停表 → s_last_period_wait 收尾。
* 此处不 AfterSegDone/Stop,否则会截断末拍成尖刺。
* ArmSegEndStop:CC1 下降沿立刻拉低,OPM 等周期 UPDATE 再收尾。
*/ */
PlsrPulseDriverArmOnePulseStop();
PlsrPulseDriverArmSegEndStop();
s_last_period_wait = 1U; s_last_period_wait = 1U;
return; return;
} }


Načítá se…
Zrušit
Uložit