| @@ -474,6 +474,7 @@ | |||
| <file>$PROJ_DIR$\Debug\Obj\stm32f4xx_hal_sdram.xcl</file> | |||
| <file>$PROJ_DIR$\Debug\Obj\startup_stm32f407xx.o</file> | |||
| <file>$PROJ_DIR$\Debug\Obj\os_cpu_c.xcl</file> | |||
| <file>$PROJ_DIR$\..\..\..\Desktop\plsr\app\main.c</file> | |||
| </outputs> | |||
| <file> | |||
| <name>[ROOT_NODE]</name> | |||
| @@ -39,41 +39,41 @@ static volatile uint8_t s_xfer_active; /* 1=正在接收一批分帧 */ | |||
| * @brief 出厂默认参数(见 plsr_param.h) | |||
| * @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) */ | |||
| PlsrCfg_t *PlsrParamGetCfg(void) | |||
| @@ -29,7 +29,7 @@ | |||
| */ | |||
| void PlsrInit(void) | |||
| { | |||
| PlsrParamInitDefault(); | |||
| //PlsrParamInitDefault(); | |||
| PlsrPersistLoad(); /* BKPSRAM 稀疏映像 → g_hold_reg */ | |||
| (void)PlsrParamBlockApplyFromHold(); | |||
| PlsrPulseDriverInit(); | |||
| @@ -55,6 +55,7 @@ static volatile uint8_t s_req_pending; | |||
| * 1=DIR_WAIT 已装载寄存器且 CEN 关:到期 Commit 前必须 CNT=0 再开 PWM。 | |||
| */ | |||
| static uint8_t s_regs_prepared; | |||
| static volatile uint8_t s_seg_end_fall_armed; /* 1=末拍 CC1 下降沿后强制拉低 */ | |||
| /*============================================================================*/ | |||
| /* 路选择 / 时钟 / GPIO */ | |||
| @@ -121,6 +122,36 @@ static void PlsrPulseDriverDirGpioInit(void) | |||
| * HAL_TIM_PWM_Stop 会清 CC1E,脚变成 AF 高阻,飞线接地的沿会耦合出极短脉冲。 | |||
| * 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) | |||
| { | |||
| uint32_t ccmr; | |||
| @@ -131,6 +162,7 @@ static void PlsrPulseDriverOcHoldLow(TIM_HandleTypeDef *htim) | |||
| } | |||
| __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE); | |||
| PlsrPulseDriverClearSegEndFallArm(htim); | |||
| htim->Instance->CR1 &= (uint32_t)(~(TIM_CR1_CEN | TIM_CR1_OPM)); | |||
| ccmr = htim->Instance->CCMR1; | |||
| @@ -803,7 +835,9 @@ void PlsrPulseDriverStop(void) | |||
| s_last_arr = 0xFFFFFFFFUL; | |||
| } | |||
| /** @brief 武装 OPM 段末停表(见 plsr_pulse_driver.h) */ | |||
| /** | |||
| * @brief 武装 OPM 段末停表(见 plsr_pulse_driver.h) | |||
| */ | |||
| void PlsrPulseDriverArmOnePulseStop(void) | |||
| { | |||
| TIM_HandleTypeDef *htim = s_active_htim; | |||
| @@ -816,6 +850,38 @@ void PlsrPulseDriverArmOnePulseStop(void) | |||
| 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) */ | |||
| void PlsrPulseDriverClearOnePulseStop(void) | |||
| { | |||
| @@ -826,4 +892,17 @@ void PlsrPulseDriverClearOnePulseStop(void) | |||
| return; | |||
| } | |||
| 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); | |||
| /** | |||
| * @brief 段末停表:OPM 等周期结束 + CC1 下降沿立刻 Forced 拉低 | |||
| * @note 仅非 FOLLOW-keep 段末使用;ACT 切段仍用 ArmOnePulseStop | |||
| */ | |||
| void PlsrPulseDriverArmSegEndStop(void); | |||
| /** | |||
| * @brief 取消单脉冲停表(后续模式同向衔接 / CutSeg keep 时) | |||
| */ | |||
| void PlsrPulseDriverClearOnePulseStop(void); | |||
| /** | |||
| * @brief 立即将当前活动路输出强制拉低(Forced inactive),不关其它路 | |||
| * @note ISR 安全;OPM 段末 UPDATE 后 CNT 回零时 PWM1 可能短暂为高,须先于收尾调用 | |||
| */ | |||
| void PlsrPulseDriverHoldOutputLow(void); | |||
| /** | |||
| * @brief 判断 instance 是否为本模块脉冲 TIM | |||
| * @return 1=TIM10/11/13;0=否 | |||
| @@ -31,8 +31,8 @@ | |||
| * 减速在 remain==dec_n+1 切入;纯减速开表再预装一拍。 | |||
| * | |||
| * 【段末停表】非 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 禁止启动) | |||
| * 0x01 段结束 AfterSegDone:s_done != s_target | |||
| @@ -1717,6 +1717,11 @@ void PlsrRunControlOnPulseIsr(void) | |||
| { | |||
| s_last_period_wait = 0U; | |||
| s_act_cut_pending = 0U; | |||
| /* | |||
| * 末拍下降沿已在 CC1 中断拉低;本 UPDATE 为 OPM 周期结束,不再 ++。 | |||
| * 再 HoldOutputLow 完整停表,交 AfterSegDone。 | |||
| */ | |||
| PlsrPulseDriverHoldOutputLow(); | |||
| PlsrRunControlAfterSegDone(); | |||
| return; | |||
| } | |||
| @@ -1753,10 +1758,9 @@ void PlsrRunControlOnPulseIsr(void) | |||
| { | |||
| /* | |||
| * 本 UPDATE = 末拍上升沿,已计入 target。 | |||
| * 武装 OPM:本周期完整跑完后下一 UPDATE 停表 → s_last_period_wait 收尾。 | |||
| * 此处不 AfterSegDone/Stop,否则会截断末拍成尖刺。 | |||
| * ArmSegEndStop:CC1 下降沿立刻拉低,OPM 等周期 UPDATE 再收尾。 | |||
| */ | |||
| PlsrPulseDriverArmOnePulseStop(); | |||
| PlsrPulseDriverArmSegEndStop(); | |||
| s_last_period_wait = 1U; | |||
| return; | |||
| } | |||