Signed-off-by: hanyongwei <2043702190@qq.com>dev1
| @@ -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> | ||||
| @@ -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) | ||||
| @@ -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(); | ||||
| @@ -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); | |||||
| } | } | ||||
| @@ -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=否 | ||||
| @@ -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; | ||||
| } | } | ||||