| @@ -138,7 +138,7 @@ void SystemClock_Config(void) | |||
| RCC_OscInitStruct.PLL.PLLM = 12; /* HSE=12MHz → VCO in = 1MHz */ | |||
| RCC_OscInitStruct.PLL.PLLN = 336; | |||
| RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; | |||
| RCC_OscInitStruct.PLL.PLLQ = 4;/*不准改成7*/ | |||
| RCC_OscInitStruct.PLL.PLLQ = 4; | |||
| if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) | |||
| { | |||
| Error_Handler(); | |||
| @@ -16,15 +16,15 @@ | |||
| * run_control 进入减速时使用局部规划副本,不会改写这里的整段规划预算。 | |||
| */ | |||
| typedef struct { | |||
| uint32_t accel_pulses; /* 入口到目标频率需要的脉冲数 */ | |||
| uint32_t const_pulses; /* 保持目标频率的脉冲数 */ | |||
| uint32_t decel_pulses; /* 目标到出口频率需要的脉冲数 */ | |||
| uint32_t start_freq_hz; /* 本段实际入口频率 */ | |||
| uint32_t target_freq_hz; /* 实际目标频率,短段可能被降低 */ | |||
| uint32_t end_freq_hz; /* 本段出口频率 */ | |||
| uint32_t accel_rate_hz_per_s; /* 升高频率时使用的变化率 */ | |||
| uint32_t decel_rate_hz_per_s; /* 降低频率时使用的变化率 */ | |||
| PlsrAccelMode_e curve_mode; /* 直线 / S / 正弦 */ | |||
| uint32_t accel_pulses; | |||
| uint32_t const_pulses; | |||
| uint32_t decel_pulses; | |||
| uint32_t start_freq_hz; | |||
| uint32_t target_freq_hz; | |||
| uint32_t end_freq_hz; | |||
| uint32_t accel_rate_hz_per_s; | |||
| uint32_t decel_rate_hz_per_s; | |||
| PlsrAccelMode_e curve_mode; | |||
| } PlsrAccelPlan_t; | |||
| /** 配置起速 → 规划入口:起速>目标用起速;否则目标与起跳比较取其一 */ | |||
| @@ -65,27 +65,26 @@ uint32_t PlsrAccelCurveFreqAtPulse(const PlsrAccelPlan_t *plan, | |||
| * S/正弦:查预计算频率表(开相 BeginAcc/BeginDec 时填好) | |||
| */ | |||
| typedef struct { | |||
| uint32_t cur_freq_hz; /* 当前输出频率 */ | |||
| uint32_t start_freq_hz; /* 当前相起点频率 */ | |||
| uint32_t end_freq_hz; /* 当前相终点频率 */ | |||
| uint32_t accel_hz_per_s; /* 当前相使用的变化率 */ | |||
| uint32_t completed_pulses; /* 当前相已经步进的脉冲数 */ | |||
| uint32_t total_pulses; /* 当前相计划步进的脉冲数 */ | |||
| uint32_t elapsed_time_us; /* 时间曲线已经经过的时间 */ | |||
| uint32_t jerk_time_us; /* S 曲线单个 jerk 阶段时间 */ | |||
| uint32_t const_accel_time_us; /* S 曲线恒加速阶段时间 */ | |||
| uint32_t ramp_time_us; /* 整个斜坡时间 */ | |||
| uint32_t table_stride; /* 每几个脉冲读取一个表项 */ | |||
| uint32_t table_length; /* 表中有效项数 */ | |||
| uint8_t freq_rising; /* 1=频率升高,0=降低 */ | |||
| uint8_t is_active; /* 1=当前相仍在运行 */ | |||
| uint8_t freq_table_id; /* 0=不用表,1=加速表,2=减速表 */ | |||
| PlsrAccelMode_e curve_mode; /* 直线 / S / 正弦 */ | |||
| uint32_t cur_freq_hz; | |||
| uint32_t start_freq_hz; | |||
| uint32_t end_freq_hz; | |||
| uint32_t accel_hz_per_s; | |||
| uint32_t completed_pulses; | |||
| uint32_t total_pulses; | |||
| uint32_t elapsed_time_us; | |||
| uint32_t jerk_time_us; | |||
| uint32_t const_accel_time_us; | |||
| uint32_t ramp_time_us; | |||
| uint32_t table_stride; | |||
| uint32_t table_length; | |||
| uint8_t freq_rising; | |||
| uint8_t is_active; | |||
| uint8_t freq_table_id; | |||
| PlsrAccelMode_e curve_mode; | |||
| } PlsrAccelRuntime_t; | |||
| /* 当前段唯一的曲线规划和逐拍状态,run_control 直接使用,不再另存副本。 */ | |||
| extern PlsrAccelPlan_t g_plsr_accel_plan; /* 本段三相规划结果 */ | |||
| extern PlsrAccelRuntime_t g_plsr_accel_runtime; /* 当前相 ISR 逐拍状态 */ | |||
| extern PlsrAccelPlan_t g_plsr_accel_plan; | |||
| extern PlsrAccelRuntime_t g_plsr_accel_runtime; | |||
| /** PlanSeg 后调用:预建 S/正弦加减速频率表(勿在 ISR) */ | |||
| void PlsrAccelPrebuildFreqTables(const PlsrAccelPlan_t *plan); | |||
| @@ -30,9 +30,9 @@ | |||
| * s_live_freq_req — 运行中写频请求标志,Poll 消费后清 0 | |||
| * s_live_freq_hz — 待应用的 new_tgt_hz | |||
| */ | |||
| static uint16_t s_fault = PLSR_ERR_NONE; /* 故障码镜像,与 0x2006 同步 */ | |||
| static volatile uint8_t s_live_freq_req; /* 1=运行中改频待 Poll 消费 */ | |||
| static volatile uint32_t s_live_freq_hz; /* 待应用的新目标频率 Hz */ | |||
| static uint16_t s_fault = PLSR_ERR_NONE; | |||
| static volatile uint8_t s_live_freq_req; | |||
| static volatile uint32_t s_live_freq_hz; | |||
| /** | |||
| * @brief 写 32 位值到相邻两个modbus保持寄存器 | |||
| @@ -57,13 +57,13 @@ static void PlsrCommandPublishMonitor(void) | |||
| if (g_plsr_busy != 0U) | |||
| { | |||
| PlsrCommandWriteDWord(PLSR_MON_FREQ_L, g_plsr_output_freq_hz); /* 0x2002/03 当前频 */ | |||
| WriteHoldReg(PLSR_MON_RUN_STATUS, 1U); /* 0x2004 运行中 */ | |||
| WriteHoldReg(PLSR_MON_CUR_SEG, (uint16_t)(g_plsr_cur_seg_idx + 1U)); /* 0x2005 1-based */ | |||
| PlsrCommandWriteDWord(PLSR_MON_FREQ_L, g_plsr_output_freq_hz); | |||
| WriteHoldReg(PLSR_MON_RUN_STATUS, 1U); | |||
| WriteHoldReg(PLSR_MON_CUR_SEG, (uint16_t)(g_plsr_cur_seg_idx + 1U)); | |||
| } | |||
| else | |||
| { | |||
| /* 空闲/停止:运行、段、频率一律清零;累计与故障码单独维护 */ | |||
| PlsrCommandWriteDWord(PLSR_MON_FREQ_L, 0U); | |||
| WriteHoldReg(PLSR_MON_RUN_STATUS, 0U); | |||
| WriteHoldReg(PLSR_MON_CUR_SEG, 0U); | |||
| @@ -107,7 +107,7 @@ void PlsrCommandInit(void) | |||
| WriteHoldReg(PLSR_CTRL_REG, 0U); | |||
| s_live_freq_req = 0U; | |||
| s_live_freq_hz = 0U; | |||
| /* 不清故障:上电由 PersistRestoreMonitor 恢复;无镜像时 s_fault 默认为 0 */ | |||
| PlsrCommandPublishMonitor(); | |||
| } | |||
| @@ -118,18 +118,18 @@ void PlsrCommandInit(void) | |||
| */ | |||
| void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity) | |||
| { | |||
| uint16_t cur_seg; /* 当前运行段(1-based) */ | |||
| uint16_t seg; /* 本次写入对应的段下标(0-based) */ | |||
| uint16_t cur_seg; | |||
| uint16_t seg; | |||
| uint16_t offset; | |||
| uint32_t freqency; | |||
| if (quantity != 2U) | |||
| { | |||
| return; /* 须为频率双字 */ | |||
| return; | |||
| } | |||
| if (g_plsr_busy == 0U) | |||
| { | |||
| return; /* 空闲改频走参数块,不走本路径 */ | |||
| return; | |||
| } | |||
| if (start_addr < PLSR_REG_SEG1_BASE) | |||
| { | |||
| @@ -139,7 +139,7 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity) | |||
| offset = (uint16_t)(start_addr - PLSR_REG_SEG1_BASE); | |||
| if ((offset % PLSR_SEG_STRIDE) != PLSR_SEG_OFF_FREQ_L) | |||
| { | |||
| return; /* 地址须对齐该段 FREQ_L */ | |||
| return; | |||
| } | |||
| seg = (uint16_t)(offset / PLSR_SEG_STRIDE); | |||
| if (seg >= PLSR_SEG_MAX) | |||
| @@ -150,22 +150,22 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity) | |||
| cur_seg = (uint16_t)(g_plsr_cur_seg_idx + 1U); | |||
| if ((cur_seg < 1U) || ((uint16_t)(cur_seg - 1U) != seg)) | |||
| { | |||
| return; /* 仅允许改当前运行段 */ | |||
| return; | |||
| } | |||
| freqency = (uint32_t)ReadHoldReg(start_addr) | | |||
| ((uint32_t)ReadHoldReg((uint16_t)(start_addr + 1U)) << 16); | |||
| if ((freqency < 1U) || (freqency > 100000U)) | |||
| { | |||
| PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); /* 非法:不改段表、不请求 */ | |||
| PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); | |||
| return; | |||
| } | |||
| g_plsr_segs[seg].freq_hz = (int32_t)freqency; /* 更新运行段表 */ | |||
| PlsrPersistSaveSegFreqToBkp(seg, freqency); /* 仅该段频率落 BKP */ | |||
| g_plsr_segs[seg].freq_hz = (int32_t)freqency; | |||
| PlsrPersistSaveSegFreqToBkp(seg, freqency); | |||
| s_live_freq_hz = freqency; | |||
| s_live_freq_req = 1U; /* 交 Poll → ChangeFreq */ | |||
| s_live_freq_req = 1U; | |||
| } | |||
| /** | |||
| @@ -181,42 +181,41 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity) | |||
| void PlsrCommandPoll(void) | |||
| { | |||
| uint16_t ctrl = ReadHoldReg(PLSR_CTRL_REG); | |||
| uint8_t skip_monitor = 0U; /* 精确等待时跳过本拍监控刷新 */ | |||
| uint8_t skip_monitor = 0U; | |||
| if (ctrl != 0U) | |||
| { | |||
| WriteHoldReg(PLSR_CTRL_REG, 0U); /* 立即清,避免重复触发 */ | |||
| WriteHoldReg(PLSR_CTRL_REG, 0U); | |||
| if ((ctrl & PLSR_CTRL_BIT_STOP) != 0U) | |||
| { | |||
| PlsrStop(); /* 急停 */ | |||
| PlsrStop(); | |||
| } | |||
| if ((ctrl & PLSR_CTRL_BIT_CLR) != 0U) | |||
| { | |||
| PlsrClearAccPulse(); /* 清累计 + 绝对原点 */ | |||
| PlsrCommandClearFault(); /* 同步清故障码 */ | |||
| PlsrClearAccPulse(); | |||
| PlsrCommandClearFault(); | |||
| } | |||
| /* START:同拍有 STOP 则不启 */ | |||
| if (((ctrl & PLSR_CTRL_BIT_START) != 0U) && | |||
| ((ctrl & PLSR_CTRL_BIT_STOP) == 0U)) | |||
| { | |||
| if (g_plsr_busy != 0U) | |||
| { | |||
| PlsrCommandSetFault(PLSR_ERR_DUP_START); /* 0x0C 重复启动 */ | |||
| PlsrCommandSetFault(PLSR_ERR_DUP_START); | |||
| } | |||
| else if (PlsrCommandIsStartBlocked() != 0U) | |||
| { | |||
| PlsrStop(); /* 0x04~0x0B:拒启,仅停 */ | |||
| PlsrStop(); | |||
| } | |||
| else | |||
| { | |||
| PlsrStop(); /* 先清残留再启 */ | |||
| PlsrStop(); | |||
| (void)PlsrStart(PlsrParamGetStartSeg()); | |||
| if (PlsrRunControlIsPreciseWait() != 0U) | |||
| { | |||
| skip_monitor = 1U; /* 换向/WAIT 精确等 TIM5 */ | |||
| skip_monitor = 1U; | |||
| } | |||
| } | |||
| } | |||
| @@ -226,11 +225,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(); /* 回写 0x2000~0x2006 */ | |||
| PlsrCommandPublishMonitor(); | |||
| } | |||
| } | |||
| @@ -28,36 +28,36 @@ | |||
| #include <stdint.h> | |||
| /* ---------- 监控保持寄存器(双字低地址存低 16 位,高地址存高 16 位) ---------- */ | |||
| #define PLSR_MON_ACC_PULSE_L 0x2000U /* 脉冲累计 SDW,有符号补码 */ | |||
| #define PLSR_MON_ACC_PULSE_L 0x2000U | |||
| #define PLSR_MON_ACC_PULSE_H 0x2001U | |||
| #define PLSR_MON_FREQ_L 0x2002U /* 当前发送频率 Hz,UDW */ | |||
| #define PLSR_MON_FREQ_L 0x2002U | |||
| #define PLSR_MON_FREQ_H 0x2003U | |||
| #define PLSR_MON_RUN_STATUS 0x2004U /* 0=空闲,1=运行中 */ | |||
| #define PLSR_MON_CUR_SEG 0x2005U /* 当前执行段号,1-based;空闲为 0 */ | |||
| #define PLSR_MON_ERR 0x2006U /* 故障码,见 PLSR_ERR_* */ | |||
| #define PLSR_MON_RUN_STATUS 0x2004U | |||
| #define PLSR_MON_CUR_SEG 0x2005U | |||
| #define PLSR_MON_ERR 0x2006U | |||
| /* ---------- 控制寄存器(读/写;从站处理后写回 0) ---------- */ | |||
| #define PLSR_CTRL_REG 0x3000U | |||
| #define PLSR_CTRL_BIT_START (1U << 0) /* 置 1:Apply 参数后启动 */ | |||
| #define PLSR_CTRL_BIT_STOP (1U << 1) /* 置 1:急停 */ | |||
| #define PLSR_CTRL_BIT_CLR (1U << 2) /* 置 1:清零累计脉冲与故障码 */ | |||
| #define PLSR_CTRL_BIT_START (1U << 0) | |||
| #define PLSR_CTRL_BIT_STOP (1U << 1) | |||
| #define PLSR_CTRL_BIT_CLR (1U << 2) | |||
| /* | |||
| * 故障码定义(写入 0x2006,须经 PlsrCommandSetFault,勿直接只写寄存器) | |||
| */ | |||
| #define PLSR_ERR_NONE 0x00U //无故障 | |||
| #define PLSR_ERR_PULSE_CNT 0x01U //实际脉冲数与段目标不一致 | |||
| #define PLSR_ERR_FREQ_UNREACH 0x02U //规划峰值达不到设定目标(三角) | |||
| #define PLSR_ERR_CURVE_MISMATCH 0x03U //加减速相内脉冲与规划预算不符 | |||
| #define PLSR_ERR_FREQ_ILLEGAL 0x04U //段频率 ∉ [1, 100000] Hz(非 0) | |||
| #define PLSR_ERR_PULSE_RANGE 0x05U //脉冲个数 ∉ int32 合法范围 | |||
| #define PLSR_ERR_SEG_COUNT 0x06U //总段数 ∉ [1, 10] | |||
| #define PLSR_ERR_START_SEG 0x07U //起始段 ∉ [1, 10] | |||
| #define PLSR_ERR_START_END_SPD 0x08U //起/止速非0且 ∉ [1, 100000] Hz | |||
| #define PLSR_ERR_PULSE_Y 0x09U //脉冲端子 ∉ {Y0,Y1,Y2} | |||
| #define PLSR_ERR_DIR_Y 0x0AU //方向端子 ≠ Y3 | |||
| #define PLSR_ERR_DEFAULT_SPD 0x0BU //默认速度 ∉ [1, 100000] Hz | |||
| #define PLSR_ERR_DUP_START 0x0CU //运行中重复 START | |||
| #define PLSR_ERR_NONE 0x00U | |||
| #define PLSR_ERR_PULSE_CNT 0x01U | |||
| #define PLSR_ERR_FREQ_UNREACH 0x02U | |||
| #define PLSR_ERR_CURVE_MISMATCH 0x03U | |||
| #define PLSR_ERR_FREQ_ILLEGAL 0x04U | |||
| #define PLSR_ERR_PULSE_RANGE 0x05U | |||
| #define PLSR_ERR_SEG_COUNT 0x06U | |||
| #define PLSR_ERR_START_SEG 0x07U | |||
| #define PLSR_ERR_START_END_SPD 0x08U | |||
| #define PLSR_ERR_PULSE_Y 0x09U | |||
| #define PLSR_ERR_DIR_Y 0x0AU | |||
| #define PLSR_ERR_DEFAULT_SPD 0x0BU | |||
| #define PLSR_ERR_DUP_START 0x0CU | |||
| /** 参数类门禁故障码下限 */ | |||
| #define PLSR_ERR_PARAM_BLOCK_MIN PLSR_ERR_FREQ_ILLEGAL | |||
| @@ -17,24 +17,24 @@ | |||
| #include "modbus_rtu.h" | |||
| #include "ucos_ii.h" | |||
| PlsrCfg_t g_plsr_config; /* 公共参数运行映像 */ | |||
| PlsrSeg_t g_plsr_segs[PLSR_SEG_MAX]; /* 段表运行映像(最多 PLSR_SEG_MAX) */ | |||
| PlsrCfg_t g_plsr_config; | |||
| PlsrSeg_t g_plsr_segs[PLSR_SEG_MAX]; | |||
| static OS_EVENT *s_param_sem; /* 分帧收齐后唤醒 ParamBlockTask */ | |||
| static volatile uint16_t s_expect_frames; /* 本批期望总帧数 = 5 + 段数 */ | |||
| static volatile uint16_t s_recv_frames; /* 已收帧计数 */ | |||
| static volatile uint8_t s_xfer_active; /* 1=正在接收一批分帧 */ | |||
| static OS_EVENT *s_param_sem; | |||
| static volatile uint16_t s_expect_frames; | |||
| static volatile uint16_t s_recv_frames; | |||
| static volatile uint8_t s_xfer_active; | |||
| /** @return 有效段数,软钳到 [0, PLSR_SEG_MAX] */ | |||
| uint16_t PlsrParamGetSegCount(void) | |||
| { | |||
| if (g_plsr_config.seg_count < 1U) | |||
| { | |||
| return 0U; /* 无有效段 */ | |||
| return 0U; | |||
| } | |||
| if (g_plsr_config.seg_count > PLSR_SEG_MAX) | |||
| { | |||
| return (uint16_t)PLSR_SEG_MAX; /* 超上限钳住 */ | |||
| return (uint16_t)PLSR_SEG_MAX; | |||
| } | |||
| return g_plsr_config.seg_count; | |||
| } | |||
| @@ -48,7 +48,7 @@ uint16_t PlsrParamGetStartSeg(void) | |||
| if (n < 1U) | |||
| { | |||
| return 1U; /* 无段时仍返回 1 */ | |||
| return 1U; | |||
| } | |||
| if (g_plsr_config.start_seg < 1U) | |||
| { | |||
| @@ -56,7 +56,7 @@ uint16_t PlsrParamGetStartSeg(void) | |||
| } | |||
| if (g_plsr_config.start_seg > n) | |||
| { | |||
| return n; /* 超出则钳到末段 */ | |||
| return n; | |||
| } | |||
| return g_plsr_config.start_seg; | |||
| } | |||
| @@ -114,7 +114,7 @@ static uint8_t PlsrParamIsSegFrameWrite(uint16_t start_addr, uint16_t quantity) | |||
| } | |||
| /*============================================================================*/ | |||
| /* 参数校验辅助 */ | |||
| /*============================================================================*/ | |||
| #define PLSR_PARAM_SPD_MIN_HZ 1U | |||
| @@ -156,7 +156,7 @@ static uint8_t PlsrParamIsSegFreqValid(int32_t freq_hz) | |||
| /** 脉冲个数 SDW:须在 int32 可安全取绝对值的范围内(排除 INT_MIN) */ | |||
| static uint8_t PlsrParamIsPulseCntValid(int32_t pulse_cnt) | |||
| { | |||
| /* INT_MIN 无法安全取反成正的目标脉冲数,报 0x05 */ | |||
| if (pulse_cnt == (int32_t)(-2147483647L - 1L)) | |||
| { | |||
| return 0U; | |||
| @@ -165,7 +165,7 @@ static uint8_t PlsrParamIsPulseCntValid(int32_t pulse_cnt) | |||
| } | |||
| /*============================================================================*/ | |||
| /* 分帧导入 / 导出 */ | |||
| /*============================================================================*/ | |||
| /** | |||
| @@ -182,41 +182,41 @@ uint8_t PlsrParamBlockApplyFromHold(void) | |||
| uint16_t base; | |||
| uint16_t fault = PLSR_ERR_NONE; | |||
| g_plsr_config.pulse_y = ReadHoldReg(PLSR_REG_PULSE_Y); /* 脉冲端子 Y0~Y2 */ | |||
| g_plsr_config.pulse_y = ReadHoldReg(PLSR_REG_PULSE_Y); | |||
| if (g_plsr_config.pulse_y > 2U) | |||
| { | |||
| fault = PLSR_ERR_PULSE_Y; /* 0x07:端子非法 */ | |||
| fault = PLSR_ERR_PULSE_Y; | |||
| } | |||
| g_plsr_config.dir_y = ReadHoldReg(PLSR_REG_DIR_Y); /* 方向端子须为 Y3 */ | |||
| g_plsr_config.dir_y = ReadHoldReg(PLSR_REG_DIR_Y); | |||
| if (g_plsr_config.dir_y != 3U) | |||
| { | |||
| fault = PLSR_ERR_DIR_Y; /* 0x08 */ | |||
| fault = PLSR_ERR_DIR_Y; | |||
| } | |||
| g_plsr_config.wait_x_sel = ReadHoldReg(PLSR_REG_WAIT_X) ? 1U : 0U; /* 0=X4,1=X5 */ | |||
| g_plsr_config.ext_x_sel = ReadHoldReg(PLSR_REG_EXT_X) ? 1U : 0U; /* 0=X4,1=X5 */ | |||
| g_plsr_config.wait_x_sel = ReadHoldReg(PLSR_REG_WAIT_X) ? 1U : 0U; | |||
| g_plsr_config.ext_x_sel = ReadHoldReg(PLSR_REG_EXT_X) ? 1U : 0U; | |||
| g_plsr_config.send_mode = (PlsrSendMode_e)(ReadHoldReg(PLSR_REG_SEND_MODE) ? 1U : 0U); | |||
| g_plsr_config.dir_delay_ms = ReadHoldReg(PLSR_REG_DIR_DELAY); /* 换向延时 ms */ | |||
| g_plsr_config.dir_delay_ms = ReadHoldReg(PLSR_REG_DIR_DELAY); | |||
| g_plsr_config.dir_logic = (ReadHoldReg(PLSR_REG_DIR_LOGIC) != 0U) ? | |||
| PLSR_DIR_LOGIC_NEG : PLSR_DIR_LOGIC_POS; /* 方向电平逻辑 */ | |||
| PLSR_DIR_LOGIC_NEG : PLSR_DIR_LOGIC_POS; | |||
| g_plsr_config.accel_mode = (PlsrAccelMode_e)ReadHoldReg(PLSR_REG_ACCEL_MODE); | |||
| g_plsr_config.run_mode = (ReadHoldReg(PLSR_REG_RUN_MODE) != 0U) ? | |||
| PLSR_POS_ABSOLUTE : PLSR_POS_RELATIVE; /* 绝对/相对 */ | |||
| PLSR_POS_ABSOLUTE : PLSR_POS_RELATIVE; | |||
| n = ReadHoldReg(PLSR_REG_SEG_COUNT); | |||
| g_plsr_config.seg_count = n; | |||
| if ((n < 1U) || (n > PLSR_SEG_MAX)) | |||
| { | |||
| fault = PLSR_ERR_SEG_COUNT; /* 0x09:段数越界 */ | |||
| fault = PLSR_ERR_SEG_COUNT; | |||
| } | |||
| g_plsr_config.start_seg = ReadHoldReg(PLSR_REG_START_SEG); /* 1-based 启动段 */ | |||
| g_plsr_config.start_seg = ReadHoldReg(PLSR_REG_START_SEG); | |||
| if ((n >= 1U) && (n <= PLSR_SEG_MAX)) | |||
| { | |||
| if ((g_plsr_config.start_seg < 1U) || (g_plsr_config.start_seg > n)) | |||
| { | |||
| fault = PLSR_ERR_START_SEG; /* 0x0A:启动段越界 */ | |||
| fault = PLSR_ERR_START_SEG; | |||
| } | |||
| } | |||
| else if (g_plsr_config.start_seg < 1U) | |||
| @@ -227,23 +227,23 @@ uint8_t PlsrParamBlockApplyFromHold(void) | |||
| g_plsr_config.default_speed = PlsrParamReadDWord(PLSR_REG_DEFAULT_SPD_L); | |||
| if (PlsrParamIsSpeedHzValid(g_plsr_config.default_speed) == 0U) | |||
| { | |||
| fault = PLSR_ERR_DEFAULT_SPD; /* 0x0B:默认速度非法 */ | |||
| fault = PLSR_ERR_DEFAULT_SPD; | |||
| } | |||
| g_plsr_config.start_speed = PlsrParamReadDWord(PLSR_REG_START_SPD_L); /* 起跳频,0 合法 */ | |||
| g_plsr_config.start_speed = PlsrParamReadDWord(PLSR_REG_START_SPD_L); | |||
| if (PlsrParamIsStartEndSpeedValid(g_plsr_config.start_speed) == 0U) | |||
| { | |||
| fault = PLSR_ERR_START_END_SPD; | |||
| } | |||
| g_plsr_config.end_speed = PlsrParamReadDWord(PLSR_REG_END_SPD_L); /* 止速,0 合法 */ | |||
| g_plsr_config.end_speed = PlsrParamReadDWord(PLSR_REG_END_SPD_L); | |||
| if (PlsrParamIsStartEndSpeedValid(g_plsr_config.end_speed) == 0U) | |||
| { | |||
| fault = PLSR_ERR_START_END_SPD; | |||
| } | |||
| g_plsr_config.accel_ms = ReadHoldReg(PLSR_REG_ACCEL_MS); /* 加速参考时间 */ | |||
| g_plsr_config.decel_ms = ReadHoldReg(PLSR_REG_DECEL_MS); /* 减速参考时间 */ | |||
| g_plsr_config.accel_ms = ReadHoldReg(PLSR_REG_ACCEL_MS); | |||
| g_plsr_config.decel_ms = ReadHoldReg(PLSR_REG_DECEL_MS); | |||
| if ((n >= 1U) && (n <= PLSR_SEG_MAX)) | |||
| { | |||
| @@ -254,32 +254,32 @@ uint8_t PlsrParamBlockApplyFromHold(void) | |||
| (int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_FREQ_L)); | |||
| if (PlsrParamIsSegFreqValid(g_plsr_segs[i].freq_hz) == 0U) | |||
| { | |||
| fault = PLSR_ERR_FREQ_ILLEGAL; /* 0x04:段频率非法 */ | |||
| fault = PLSR_ERR_FREQ_ILLEGAL; | |||
| } | |||
| g_plsr_segs[i].pulse_cnt = | |||
| (int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_PULSE_L)); | |||
| if (PlsrParamIsPulseCntValid(g_plsr_segs[i].pulse_cnt) == 0U) | |||
| { | |||
| fault = PLSR_ERR_PULSE_RANGE; /* 0x05:脉冲数 INT_MIN */ | |||
| fault = PLSR_ERR_PULSE_RANGE; | |||
| } | |||
| g_plsr_segs[i].wait_type = | |||
| (PlsrWaitType_e)ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT)); | |||
| g_plsr_segs[i].wait_ms = | |||
| ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT_MS)); /* 段后等待 ms */ | |||
| ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT_MS)); | |||
| g_plsr_segs[i].act_ms = | |||
| ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_ACT_MS)); /* ACT 定时 ms */ | |||
| ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_ACT_MS)); | |||
| g_plsr_segs[i].jump_seg = | |||
| ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP)); /* 跳转目标段 */ | |||
| ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP)); | |||
| } | |||
| } | |||
| PlsrCommandSetFault(fault); /* 写 0x2006 镜像 */ | |||
| PlsrCommandSetFault(fault); | |||
| if (fault == PLSR_ERR_NONE) | |||
| { | |||
| return 1U; /* 可落存 BKP */ | |||
| return 1U; | |||
| } | |||
| return 0U; | |||
| } | |||
| @@ -302,33 +302,33 @@ void PlsrParamBlockOnHoldWrite(uint16_t start_addr, uint16_t quantity) | |||
| if ((start_addr == PLSR_REG_COMMON_F1_BASE) && | |||
| (quantity >= PLSR_PARAM_COMMON_FRAME1_WORDS)) | |||
| { | |||
| /* 公共帧 1:开新一批,期望 5+段数 */ | |||
| uint16_t seg_n = ReadHoldReg(PLSR_REG_SEG_COUNT); | |||
| if (seg_n > PLSR_SEG_MAX) | |||
| { | |||
| seg_n = (uint16_t)PLSR_SEG_MAX; /* 计数软钳,避免 expect 溢出 */ | |||
| seg_n = (uint16_t)PLSR_SEG_MAX; | |||
| } | |||
| s_expect_frames = (uint16_t)(PLSR_PARAM_COMMON_FRAMES + seg_n); | |||
| s_recv_frames = 1U; /* 帧 1 已计入 */ | |||
| s_xfer_active = 1U; /* 开始收批 */ | |||
| s_recv_frames = 1U; | |||
| s_xfer_active = 1U; | |||
| } | |||
| else if ((s_xfer_active != 0U) && | |||
| ((PlsrParamIsCommonTailFrameWrite(start_addr, quantity) != 0U) || | |||
| (PlsrParamIsSegFrameWrite(start_addr, quantity) != 0U))) | |||
| { | |||
| s_recv_frames++; /* 公共帧 2~5 或段帧 +1 */ | |||
| s_recv_frames++; | |||
| } | |||
| else | |||
| { | |||
| return; /* 非本批帧 / 未开批 → 忽略 */ | |||
| return; | |||
| } | |||
| if ((s_xfer_active != 0U) && (s_recv_frames >= s_expect_frames)) | |||
| { | |||
| s_xfer_active = 0U; /* 收齐 */ | |||
| s_xfer_active = 0U; | |||
| if (s_param_sem != (OS_EVENT *)0) | |||
| { | |||
| (void)OSSemPost(s_param_sem); /* 唤醒 ParamBlockTask */ | |||
| (void)OSSemPost(s_param_sem); | |||
| } | |||
| } | |||
| } | |||
| @@ -364,7 +364,7 @@ void PlsrParamBlockTask(void *pArg) | |||
| if (PlsrParamBlockApplyFromHold() != 0U) | |||
| { | |||
| PlsrPersistSaveParamsFromHold(); /* 仅全部校验通过才存 BKP */ | |||
| PlsrPersistSaveParamsFromHold(); | |||
| } | |||
| } | |||
| } | |||
| @@ -41,56 +41,56 @@ | |||
| #define PLSR_SEG_MAX 10U | |||
| /* ---------- 公共参数保持寄存器(0x1000 起,共 20 字到 0x1013) ---------- */ | |||
| #define PLSR_REG_PULSE_Y 0x1000U /* 脉冲端子:0=Y0 1=Y1 2=Y2 */ | |||
| #define PLSR_REG_DIR_Y 0x1001U /* 方向端子:固件强制 3=Y3 */ | |||
| #define PLSR_REG_WAIT_X 0x1002U /* WAIT 输入选择:0=X4 1=X5 */ | |||
| #define PLSR_REG_EXT_X 0x1003U /* EXT 输入选择:0=X4 1=X5 */ | |||
| #define PLSR_REG_SEND_MODE 0x1004U /* 发送方式:0完成 1后续 */ | |||
| #define PLSR_REG_DIR_DELAY 0x1005U /* 方向建立延时 ms */ | |||
| #define PLSR_REG_DIR_LOGIC 0x1006U /* 方向逻辑:0正 1负 */ | |||
| #define PLSR_REG_ACCEL_MODE 0x1007U /* 曲线:0直线 1=S 2正弦 */ | |||
| #define PLSR_REG_RUN_MODE 0x1008U /* 定位:0相对 1绝对 */ | |||
| #define PLSR_REG_SEG_COUNT 0x1009U /* 脉冲总段数 N(决定 expect=5+N) */ | |||
| #define PLSR_REG_START_SEG 0x100AU /* 启动段号 1-based */ | |||
| #define PLSR_REG_DEFAULT_SPD_L 0x100BU /* 默认速度 Hz,双字低 */ | |||
| #define PLSR_REG_PULSE_Y 0x1000U | |||
| #define PLSR_REG_DIR_Y 0x1001U | |||
| #define PLSR_REG_WAIT_X 0x1002U | |||
| #define PLSR_REG_EXT_X 0x1003U | |||
| #define PLSR_REG_SEND_MODE 0x1004U | |||
| #define PLSR_REG_DIR_DELAY 0x1005U | |||
| #define PLSR_REG_DIR_LOGIC 0x1006U | |||
| #define PLSR_REG_ACCEL_MODE 0x1007U | |||
| #define PLSR_REG_RUN_MODE 0x1008U | |||
| #define PLSR_REG_SEG_COUNT 0x1009U | |||
| #define PLSR_REG_START_SEG 0x100AU | |||
| #define PLSR_REG_DEFAULT_SPD_L 0x100BU | |||
| #define PLSR_REG_DEFAULT_SPD_H 0x100CU | |||
| #define PLSR_REG_START_SPD_L 0x100DU /* 起速 Hz */ | |||
| #define PLSR_REG_START_SPD_L 0x100DU | |||
| #define PLSR_REG_START_SPD_H 0x100EU | |||
| /* 0x100F 保留,写帧填 0 */ | |||
| #define PLSR_REG_END_SPD_L 0x1010U /* 止速 Hz */ | |||
| #define PLSR_REG_END_SPD_L 0x1010U | |||
| #define PLSR_REG_END_SPD_H 0x1011U | |||
| #define PLSR_REG_ACCEL_MS 0x1012U /* 默认速度加速时间 ms */ | |||
| #define PLSR_REG_DECEL_MS 0x1013U /* 默认速度减速时间 ms */ | |||
| #define PLSR_REG_ACCEL_MS 0x1012U | |||
| #define PLSR_REG_DECEL_MS 0x1013U | |||
| /* ---------- 公共参数分帧(5 帧 + N 段帧) ---------- */ | |||
| #define PLSR_PARAM_COMMON_FRAMES 5U | |||
| #define PLSR_PARAM_COMMON_FRAME1_WORDS 11U /* 0x1000~0x100A */ | |||
| #define PLSR_PARAM_COMMON_DWORD_WORDS 2U /* 双字帧字数 */ | |||
| #define PLSR_PARAM_COMMON_FRAME1_WORDS 11U | |||
| #define PLSR_PARAM_COMMON_DWORD_WORDS 2U | |||
| #define PLSR_REG_COMMON_F1_BASE PLSR_REG_PULSE_Y /* 0x1000 */ | |||
| #define PLSR_REG_COMMON_F1_END PLSR_REG_START_SEG /* 0x100A */ | |||
| #define PLSR_REG_COMMON_F2_BASE PLSR_REG_DEFAULT_SPD_L /* 0x100B */ | |||
| #define PLSR_REG_COMMON_F3_BASE PLSR_REG_START_SPD_L /* 0x100D */ | |||
| #define PLSR_REG_COMMON_F4_BASE PLSR_REG_END_SPD_L /* 0x1010 */ | |||
| #define PLSR_REG_COMMON_F5_BASE PLSR_REG_ACCEL_MS /* 0x1012 */ | |||
| #define PLSR_REG_COMMON_F1_BASE PLSR_REG_PULSE_Y | |||
| #define PLSR_REG_COMMON_F1_END PLSR_REG_START_SEG | |||
| #define PLSR_REG_COMMON_F2_BASE PLSR_REG_DEFAULT_SPD_L | |||
| #define PLSR_REG_COMMON_F3_BASE PLSR_REG_START_SPD_L | |||
| #define PLSR_REG_COMMON_F4_BASE PLSR_REG_END_SPD_L | |||
| #define PLSR_REG_COMMON_F5_BASE PLSR_REG_ACCEL_MS | |||
| /* ---------- 段参数:第 i 段基址 = 0x1100 + i*0x10,每段 8 字 ---------- */ | |||
| #define PLSR_REG_SEG1_BASE 0x1100U | |||
| #define PLSR_SEG_STRIDE 0x0010U | |||
| #define PLSR_SEG_OFF_FREQ_L 0U /* 目标频率 SDW;0=用 default_speed */ | |||
| #define PLSR_SEG_OFF_FREQ_L 0U | |||
| #define PLSR_SEG_OFF_FREQ_H 1U | |||
| #define PLSR_SEG_OFF_PULSE_L 2U /* 脉冲数/绝对坐标 SDW,负=反转 */ | |||
| #define PLSR_SEG_OFF_PULSE_L 2U | |||
| #define PLSR_SEG_OFF_PULSE_H 3U | |||
| #define PLSR_SEG_OFF_WAIT 4U /* PlsrWaitType_e */ | |||
| #define PLSR_SEG_OFF_WAIT_MS 5U /* WAIT 时间 ms */ | |||
| #define PLSR_SEG_OFF_ACT_MS 6U /* ACT 时间 ms */ | |||
| #define PLSR_SEG_OFF_JUMP 7U /* 0=顺序/末段停;1~N=跳转目标段号 */ | |||
| #define PLSR_SEG_OFF_WAIT 4U | |||
| #define PLSR_SEG_OFF_WAIT_MS 5U | |||
| #define PLSR_SEG_OFF_ACT_MS 6U | |||
| #define PLSR_SEG_OFF_JUMP 7U | |||
| /** 方向逻辑:正转时方向脚电平 */ | |||
| typedef enum { | |||
| PLSR_DIR_LOGIC_POS = 0, /* 正转→方向高,反转→低 */ | |||
| PLSR_DIR_LOGIC_NEG = 1 /* 相反 */ | |||
| PLSR_DIR_LOGIC_POS = 0, | |||
| PLSR_DIR_LOGIC_NEG = 1 | |||
| } PlsrDirLogic_e; | |||
| /** | |||
| @@ -105,9 +105,9 @@ typedef enum { | |||
| /** 加减速曲线形状 */ | |||
| typedef enum { | |||
| PLSR_ACCEL_LINEAR = 0, /* f^2 = f0^2 ± 2an */ | |||
| PLSR_ACCEL_S = 1, /* 时间域七段 S:加速度梯形 1:2:1 */ | |||
| PLSR_ACCEL_SINE = 2 /* 时间域 raised-cosine */ | |||
| PLSR_ACCEL_LINEAR = 0, | |||
| PLSR_ACCEL_S = 1, | |||
| PLSR_ACCEL_SINE = 2 | |||
| } PlsrAccelMode_e; | |||
| /** | |||
| @@ -127,43 +127,43 @@ typedef enum { | |||
| * 与下一段反向时规划同其它等待(减速到止速,下一段从起速再爬) | |||
| */ | |||
| typedef enum { | |||
| PLSR_WAIT_TIME = 0, /* 发完后等 wait_ms(0 按 1ms),再跳转 */ | |||
| PLSR_WAIT_SIGNAL = 1, /* 发完后等 WAIT 口下降沿 */ | |||
| PLSR_WAIT_ACT = 2, /* 开跑后满 act_ms 从当前频切下一段;脉冲先完则等到点 */ | |||
| PLSR_WAIT_EXT = 3, /* 运行中 EXT 沿中途切段;发完后仍等 EXT */ | |||
| PLSR_WAIT_EXT_OR_DONE = 4 /* EXT 沿或脉冲发完,先到先切 */ | |||
| PLSR_WAIT_TIME = 0, | |||
| PLSR_WAIT_SIGNAL = 1, | |||
| PLSR_WAIT_ACT = 2, | |||
| PLSR_WAIT_EXT = 3, | |||
| PLSR_WAIT_EXT_OR_DONE = 4 | |||
| } PlsrWaitType_e; | |||
| /** | |||
| * 公共运行参数映像 | |||
| */ | |||
| typedef struct { | |||
| uint16_t pulse_y; /* 0=Y0/TIM10 1=Y1/TIM13 2=Y2/TIM11 */ | |||
| uint16_t dir_y; /* 固定 3=Y3 */ | |||
| uint16_t wait_x_sel; /* 0=X4 1=X5 */ | |||
| uint16_t pulse_y; | |||
| uint16_t dir_y; | |||
| uint16_t wait_x_sel; | |||
| uint16_t ext_x_sel; | |||
| PlsrSendMode_e send_mode; | |||
| uint16_t dir_delay_ms; | |||
| PlsrDirLogic_e dir_logic; | |||
| PlsrAccelMode_e accel_mode; | |||
| PlsrPosMode_e run_mode; | |||
| uint16_t seg_count; /* 有效段数 0~PLSR_SEG_MAX */ | |||
| uint16_t start_seg; /* 1-based */ | |||
| uint32_t default_speed; /* Hz;段频为 0 时作段目标;并定斜率 */ | |||
| uint32_t start_speed; /* 起速;0=运行层 ResolveStartHz 起跳 */ | |||
| uint32_t end_speed; /* 止速;0=ResolveEndHz 落地后停表 */ | |||
| uint16_t seg_count; | |||
| uint16_t start_seg; | |||
| uint32_t default_speed; | |||
| uint32_t start_speed; | |||
| uint32_t end_speed; | |||
| uint16_t accel_ms; | |||
| uint16_t decel_ms; | |||
| } PlsrCfg_t; | |||
| /** 单段运行参数 */ | |||
| typedef struct { | |||
| int32_t freq_hz; /* 0=用默认速度;解析后须在 1~100k,否则 0x04 */ | |||
| int32_t pulse_cnt; /* 可负=反向;0=本段不发 */ | |||
| int32_t freq_hz; | |||
| int32_t pulse_cnt; | |||
| PlsrWaitType_e wait_type; | |||
| uint16_t wait_ms; | |||
| uint16_t act_ms; | |||
| uint16_t jump_seg; /* 0=顺序/末段结束;1~N=跳转 */ | |||
| uint16_t jump_seg; | |||
| } PlsrSeg_t; | |||
| /* ---------- 运行参数 ---------- */ | |||
| @@ -27,16 +27,16 @@ | |||
| */ | |||
| void PlsrInit(void) | |||
| { | |||
| PlsrPersistInit(); /* 使能 BKPSRAM 写访问,否则存BKP无效 */ | |||
| PlsrPersistLoad(); /* BKPSRAM → g_hold_reg */ | |||
| (void)PlsrParamBlockApplyFromHold(); /* hold → 运行参数 + 校验 */ | |||
| PlsrPersistInit(); | |||
| PlsrPersistLoad(); | |||
| (void)PlsrParamBlockApplyFromHold(); | |||
| PlsrPulseDriverInit(); | |||
| PlsrSignalIoInit(); | |||
| PlsrRunControlInit(); | |||
| PlsrPersistRestoreRuntime(); /* hold 0x2000 累计 → run_control */ | |||
| PlsrPersistRestoreRuntime(); | |||
| PlsrCommandInit(); | |||
| PlsrPersistRestoreMonitor(); /* 恢复故障码;0x3000/运行态强制空闲 */ | |||
| PlsrPersistTickMonitor(); /* 监控区 hold+BKP 与运行态对齐 */ | |||
| PlsrPersistRestoreMonitor(); | |||
| PlsrPersistTickMonitor(); | |||
| } | |||
| /** | |||
| @@ -50,11 +50,11 @@ void PlsrInit(void) | |||
| */ | |||
| void PlsrTask(void *pArg) | |||
| { | |||
| static uint8_t s_booted = 0U; /* 1=已完成首次延迟对齐(等 Modbus 填 hold) */ | |||
| static uint8_t s_booted = 0U; | |||
| (void)pArg; | |||
| PlsrRunControlWakeInit(); /* OS 已启动,创建 WAIT/ACT 到期唤醒信号量 */ | |||
| PlsrRunControlWakeInit(); | |||
| while(1) | |||
| { | |||
| @@ -64,17 +64,17 @@ void PlsrTask(void *pArg) | |||
| */ | |||
| if (s_booted == 0U) | |||
| { | |||
| OSTimeDly(3U); /* ~30ms @ 100Hz tick;让出 CPU 给 Modbus 完成初始化 */ | |||
| OSTimeDly(3U); | |||
| PlsrCommandInit(); | |||
| PlsrPersistRestoreMonitor(); | |||
| PlsrPersistTickMonitor(); | |||
| s_booted = 1U; | |||
| } | |||
| PlsrRunControlTickMs(); /* 处理延时/外部信号输入,优先:WAIT/换向到期立刻开表 */ | |||
| PlsrSignalIoDebouncePoll(); /* OS 节拍消抖确认 */ | |||
| PlsrCommandPoll(); /* 收 START/STOP/CLR,回写 0x2000~0x2006 监控 ,决定是否开pwm输出*/ | |||
| PlsrPersistTickMonitor(); /* 监控区:运行态→hold→BKP(每 OS 节拍) */ | |||
| PlsrRunControlTickMs(); | |||
| PlsrSignalIoDebouncePoll(); | |||
| PlsrCommandPoll(); | |||
| PlsrPersistTickMonitor(); | |||
| /* | |||
| * 换向 / WAIT 时间:WakePend(0) 只等 TIM5 Post(墙钟≈设定 ms)。 | |||
| @@ -24,10 +24,9 @@ | |||
| #include <stdint.h> | |||
| /* run_control 拥有的共享运行状态;段下标从 0 开始。 */ | |||
| extern volatile uint8_t g_plsr_busy; /* 运行忙标志(上位机监控) */ | |||
| extern volatile uint16_t g_plsr_cur_seg_idx; /* 当前段下标(0-based) */ | |||
| extern volatile int32_t g_plsr_accumulated_pulses; /* 全局累计脉冲(有符号) */ | |||
| extern volatile uint8_t g_plsr_busy; | |||
| extern volatile uint16_t g_plsr_cur_seg_idx; | |||
| extern volatile int32_t g_plsr_accumulated_pulses; | |||
| #include "plsr_param.h" | |||
| /** | |||
| @@ -34,11 +34,10 @@ extern TIM_HandleTypeDef htim10; | |||
| extern TIM_HandleTypeDef htim11; | |||
| extern TIM_HandleTypeDef htim13; | |||
| /* 驱动拥有的真实输出状态,run_control 直接读取,不再保存第二份。 */ | |||
| extern volatile uint32_t g_plsr_output_freq_hz; /* 当前输出频率 Hz */ | |||
| extern volatile uint8_t g_plsr_pwm_running; /* 1=PWM 正在跑 */ | |||
| extern uint8_t g_plsr_direction_forward; /* 1=正转方向语义 */ | |||
| extern uint8_t g_plsr_direction_valid; /* 1=方向脚已有效写出 */ | |||
| 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; | |||
| /** | |||
| * @brief 初始化三路脉冲 TIM + 方向 GPIO | |||
| @@ -34,16 +34,16 @@ | |||
| /* ---------- 硬件引脚 ---------- */ | |||
| #define PLSR_X4_PORT GPIOB | |||
| #define PLSR_X4_PIN GPIO_PIN_5 /* X4:WAIT/EXT 可选 */ | |||
| #define PLSR_X4_PIN GPIO_PIN_5 | |||
| #define PLSR_X5_PORT GPIOG | |||
| #define PLSR_X5_PIN GPIO_PIN_12 /* X5:WAIT/EXT 可选 */ | |||
| #define PLSR_X5_PIN GPIO_PIN_12 | |||
| /* | |||
| * TIM5 时基:84MHz / (8399+1) = 10kHz → 100µs/格。 | |||
| * PSC=8399 落在 16 位内 | |||
| */ | |||
| #define PLSR_TIM5_PSC_100US 8399U | |||
| #define PLSR_TIM5_TICKS_PER_MS 10U /* 10×100µs = 1ms */ | |||
| #define PLSR_TIM5_TICKS_PER_MS 10U | |||
| #define PLSR_DELAY_MS_MAX 65535U | |||
| /** OS 节拍消抖窗口(ms),与 PlsrTask tick 配合 */ | |||
| @@ -51,17 +51,17 @@ | |||
| /** 单路 X 口消抖状态(pending / fell 由 ISR 与任务共享,volatile) */ | |||
| typedef struct { | |||
| volatile uint8_t pending; /* 1=EXTI 已见下降沿,待 Confirm */ | |||
| volatile uint8_t stamp_ok; /* 1=已记 arm_tick,正在计时 */ | |||
| volatile INT32U arm_tick; /* 消抖起点 OS tick */ | |||
| volatile uint8_t fell; /* 1=消抖确认的有效下降沿,Take* 消费 */ | |||
| volatile uint8_t pending; | |||
| volatile uint8_t stamp_ok; | |||
| volatile INT32U arm_tick; | |||
| volatile uint8_t fell; | |||
| GPIO_TypeDef *port; | |||
| uint16_t pin; | |||
| } PlsrEdge_t; | |||
| static PlsrEdge_t s_debounce_x4; /* X4 消抖状态 */ | |||
| static PlsrEdge_t s_debounce_x5; /* X5 消抖状态 */ | |||
| static volatile uint8_t s_delay_armed; /* 1=TIM5 单次延时正在计时 */ | |||
| static PlsrEdge_t s_debounce_x4; | |||
| static PlsrEdge_t s_debounce_x5; | |||
| static volatile uint8_t s_delay_armed; | |||
| /** 毫秒 → OS tick 数(向上取整,至少 1 tick) */ | |||
| static INT32U PlsrSignalIoMsToTicks(uint32_t ms) | |||
| @@ -164,14 +164,14 @@ static void PlsrSignalIoTim5Init(void) | |||
| { | |||
| __HAL_RCC_TIM5_CLK_ENABLE(); | |||
| TIM5->CR1 = 0U; /* 停表:向上计、关 OPM */ | |||
| TIM5->DIER = 0U; /* 关 UPDATE 中断 */ | |||
| TIM5->SR = 0U; /* 清状态标志 */ | |||
| TIM5->PSC = PLSR_TIM5_PSC_100US; /* PSC=8399 → 10kHz(100µs/格),非 1MHz */ | |||
| TIM5->ARR = 0xFFFFFFFFUL; /* 预装最大 ARR,真正延时在 Schedule 重写 */ | |||
| TIM5->CR1 = 0U; | |||
| TIM5->DIER = 0U; | |||
| TIM5->SR = 0U; | |||
| TIM5->PSC = PLSR_TIM5_PSC_100US; | |||
| TIM5->ARR = 0xFFFFFFFFUL; | |||
| TIM5->CNT = 0U; | |||
| TIM5->EGR = TIM_EGR_UG; /* UG:PSC 立刻生效(会置 UIF) */ | |||
| TIM5->SR = 0U; /* 清 UG 带来的 UIF */ | |||
| TIM5->EGR = TIM_EGR_UG; | |||
| TIM5->SR = 0U; | |||
| HAL_NVIC_SetPriority(TIM5_IRQn, 7, 0); | |||
| HAL_NVIC_EnableIRQ(TIM5_IRQn); | |||
| @@ -198,7 +198,7 @@ void PlsrSignalIoInit(void) | |||
| PlsrSignalIoGpioExtiInit(); | |||
| PlsrSignalIoTim5Init(); | |||
| /* 配完 NVIC 后再清一次,避免配置期误沿 */ | |||
| __HAL_GPIO_EXTI_CLEAR_IT(PLSR_X4_PIN); | |||
| __HAL_GPIO_EXTI_CLEAR_IT(PLSR_X5_PIN); | |||
| s_debounce_x4.fell = 0U; | |||
| @@ -229,13 +229,13 @@ void PlsrSignalIoScheduleDelayMs(uint32_t delay_ms) | |||
| TIM5->SR = 0U; | |||
| TIM5->PSC = PLSR_TIM5_PSC_100US; | |||
| TIM5->ARR = ticks - 1U; | |||
| TIM5->CR1 = TIM_CR1_URS; /* 仅溢出产生 UPDATE */ | |||
| TIM5->EGR = TIM_EGR_UG; /* PSC/ARR 立刻生效 */ | |||
| TIM5->SR = 0U; /* 清 UG 带来的 UIF */ | |||
| TIM5->CR1 = TIM_CR1_URS; | |||
| TIM5->EGR = TIM_EGR_UG; | |||
| TIM5->SR = 0U; | |||
| TIM5->CNT = 0U; | |||
| TIM5->DIER = TIM_DIER_UIE; | |||
| s_delay_armed = 1U; | |||
| TIM5->CR1 = (uint32_t)(TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS); /* 开表单次 */ | |||
| TIM5->CR1 = (uint32_t)(TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS); | |||
| } | |||
| /** @brief 取消 TIM5 延时并清武装 */ | |||
| @@ -305,7 +305,7 @@ void PlsrSignalIoClearPending(void) | |||
| /** @brief 取 WAIT 口有效下降沿(读后清) */ | |||
| uint8_t PlsrSignalIoTakeWaitFalling(void) | |||
| { | |||
| /* wait_x_sel:0=X4,1=X5 */ | |||
| if (g_plsr_config.wait_x_sel == 0U) | |||
| { | |||
| if (s_debounce_x4.fell != 0U) | |||
| @@ -325,7 +325,7 @@ uint8_t PlsrSignalIoTakeWaitFalling(void) | |||
| /** @brief 取 EXT 口有效下降沿(读后清) */ | |||
| uint8_t PlsrSignalIoTakeExtFalling(void) | |||
| { | |||
| /* ext_x_sel:0=X4,1=X5 */ | |||
| if (g_plsr_config.ext_x_sel == 0U) | |||
| { | |||
| if (s_debounce_x4.fell != 0U) | |||
| @@ -353,7 +353,7 @@ void PlsrSignalIoOnTim5Irq(void) | |||
| if (s_delay_armed != 0U) | |||
| { | |||
| s_delay_armed = 0U; | |||
| PlsrRunControlOnDelayTimer(); /* 方向/WAIT/ACT 到期 */ | |||
| PlsrRunControlOnDelayTimer(); | |||
| } | |||
| } | |||
| } | |||