| @@ -37,7 +37,7 @@ | |||
| /*============================================================================*/ | |||
| /* 线圈/保持寄存器最大协议地址 */ | |||
| #define MODBUS_MB_MAXIMUM 0x270FU | |||
| #define MODBUS_MB_MAXIMUM 0x3000U | |||
| /* 实际能存储的最大数据个数 */ | |||
| #define MODBUS_POINT_COUNT (MODBUS_MB_MAXIMUM + 1U) | |||
| @@ -1,6 +1,6 @@ | |||
| /** | |||
| * @file plsr_command.c | |||
| * @brief 指令接口:Modbus 命令/线圈 → 参数块 + 运行控制;状态与故障回写 | |||
| * @brief 指令接口:0x3000 控制位 → 运行控制;监控写回 0x2000~0x2006 | |||
| */ | |||
| #include "plsr_command.h" | |||
| #include "plsr_param.h" | |||
| @@ -16,16 +16,25 @@ static void PlsrCommandWriteDWord(uint16_t addr, uint32_t value) | |||
| WriteHoldReg((uint16_t)(addr + 1U), (uint16_t)((value >> 16) & 0xFFFFU)); | |||
| } | |||
| static void PlsrCommandPublishMonitor(void) | |||
| { | |||
| PlsrCommandWriteDWord(PLSR_MON_ACC_PULSE_L, (uint32_t)PlsrGetAccPulse()); | |||
| PlsrCommandWriteDWord(PLSR_MON_FREQ_L, PlsrRunControlGetCurFreq()); | |||
| WriteHoldReg(PLSR_MON_RUN_STATUS, PlsrIsBusy() ? 1U : 0U); | |||
| WriteHoldReg(PLSR_MON_CUR_SEG, PlsrRunControlGetCurSeg()); | |||
| WriteHoldReg(PLSR_MON_ERR, s_fault); | |||
| } | |||
| void PlsrCommandSetFault(uint16_t code) | |||
| { | |||
| s_fault = code; | |||
| WriteHoldReg(PLSR_CMD_REG_ERR, code); | |||
| WriteHoldReg(PLSR_MON_ERR, code); | |||
| } | |||
| void PlsrCommandClearFault(void) | |||
| { | |||
| s_fault = PLSR_ERR_NONE; | |||
| WriteHoldReg(PLSR_CMD_REG_ERR, PLSR_ERR_NONE); | |||
| WriteHoldReg(PLSR_MON_ERR, PLSR_ERR_NONE); | |||
| } | |||
| uint16_t PlsrCommandGetFault(void) | |||
| @@ -35,45 +44,41 @@ uint16_t PlsrCommandGetFault(void) | |||
| void PlsrCommandInit(void) | |||
| { | |||
| WriteHoldReg(PLSR_CMD_REG_COMMAND, PLSR_CMD_IDLE); | |||
| WriteHoldReg(PLSR_CTRL_REG, 0U); | |||
| PlsrCommandClearFault(); | |||
| PlsrCommandPublishMonitor(); | |||
| } | |||
| void PlsrCommandPoll(void) | |||
| { | |||
| uint16_t cmd = ReadHoldReg(PLSR_CMD_REG_COMMAND); | |||
| uint16_t ctrl = ReadHoldReg(PLSR_CTRL_REG); | |||
| if (ReadCoil(PLSR_CMD_COIL_CLR_ACC) != 0U) | |||
| { | |||
| WriteCoil(PLSR_CMD_COIL_CLR_ACC, 0U); | |||
| PlsrClearAccPulse(); | |||
| } | |||
| if (ReadCoil(PLSR_CMD_COIL_STOP) != 0U) | |||
| if (ctrl != 0U) | |||
| { | |||
| WriteCoil(PLSR_CMD_COIL_STOP, 0U); | |||
| PlsrStop(); | |||
| } | |||
| /* 上位机置位,从站处理后立刻清零 */ | |||
| WriteHoldReg(PLSR_CTRL_REG, 0U); | |||
| if (cmd == PLSR_CMD_STOP) | |||
| { | |||
| WriteHoldReg(PLSR_CMD_REG_COMMAND, PLSR_CMD_IDLE); | |||
| PlsrStop(); | |||
| } | |||
| else if ((cmd == PLSR_CMD_START) || (cmd == PLSR_CMD_IMPORT)) | |||
| { | |||
| WriteHoldReg(PLSR_CMD_REG_COMMAND, PLSR_CMD_IDLE); | |||
| (void)PlsrParamBlockApplyFromHold(); | |||
| if (cmd == PLSR_CMD_START) | |||
| if ((ctrl & PLSR_CTRL_BIT_STOP) != 0U) | |||
| { | |||
| PlsrStop(); | |||
| } | |||
| if ((ctrl & PLSR_CTRL_BIT_CLR) != 0U) | |||
| { | |||
| PlsrClearAccPulse(); | |||
| PlsrCommandClearFault(); | |||
| } | |||
| /* 同时有停止位时不启动 */ | |||
| if (((ctrl & PLSR_CTRL_BIT_START) != 0U) && | |||
| ((ctrl & PLSR_CTRL_BIT_STOP) == 0U)) | |||
| { | |||
| (void)PlsrParamBlockApplyFromHold(); | |||
| PlsrCommandClearFault(); | |||
| PlsrStop(); | |||
| (void)PlsrStart(PlsrParamGetStartSeg()); | |||
| } | |||
| } | |||
| WriteHoldReg(PLSR_CMD_REG_BUSY, PlsrIsBusy()); | |||
| WriteHoldReg(PLSR_CMD_REG_CUR_SEG, PlsrRunControlGetCurSeg()); | |||
| PlsrCommandWriteDWord(PLSR_CMD_REG_CUR_FREQ_L, PlsrRunControlGetCurFreq()); | |||
| PlsrCommandWriteDWord(PLSR_CMD_REG_ACC_PULSE_L, (uint32_t)PlsrGetAccPulse()); | |||
| WriteHoldReg(PLSR_CMD_REG_ERR, s_fault); | |||
| PlsrCommandPublishMonitor(); | |||
| } | |||
| @@ -2,36 +2,29 @@ | |||
| * @file plsr_command.h | |||
| * @brief 指令接口模块 | |||
| * | |||
| * 职责(与方案书 3.1 对齐;未实现项后续补充): | |||
| * 1. 接收启动 / STOP 急停等外部触发(当前经 Modbus 命令寄存器与线圈) | |||
| * 2. (待实现)重复启动防护、GOON 恢复、fault_buf | |||
| * 3. 指令分发:启动时先走参数块管理再启运行;停机直接停运动 | |||
| * 4. 状态上报:忙闲、当前段、频率、累计脉冲写回保持寄存器 | |||
| * 监控区 0x2000~0x2006:下位机刷新,上位机 0x03 读。 | |||
| * 控制寄存器 0x3000:上位机置位,下位机处理后清零。 | |||
| */ | |||
| #ifndef PLSR_COMMAND_H | |||
| #define PLSR_COMMAND_H | |||
| #include <stdint.h> | |||
| /* 指令与状态保持寄存器(地址与原协议兼容) */ | |||
| #define PLSR_CMD_REG_COMMAND 0x10F0U /* 写命令 */ | |||
| #define PLSR_CMD_REG_BUSY 0x10F1U /* 运动忙 */ | |||
| #define PLSR_CMD_REG_CUR_SEG 0x10F2U /* 当前段号 1-based */ | |||
| #define PLSR_CMD_REG_CUR_FREQ_L 0x10F3U | |||
| #define PLSR_CMD_REG_CUR_FREQ_H 0x10F4U | |||
| #define PLSR_CMD_REG_ACC_PULSE_L 0x10F5U | |||
| #define PLSR_CMD_REG_ACC_PULSE_H 0x10F6U | |||
| #define PLSR_CMD_REG_ERR 0x10F7U /* 故障码 */ | |||
| /* ---------- 监控保持寄存器(双字低地址存低字) ---------- */ | |||
| #define PLSR_MON_ACC_PULSE_L 0x2000U /* 脉冲累计,有符号补码 */ | |||
| #define PLSR_MON_ACC_PULSE_H 0x2001U | |||
| #define PLSR_MON_FREQ_L 0x2002U /* 当前发送频率 Hz */ | |||
| #define PLSR_MON_FREQ_H 0x2003U | |||
| #define PLSR_MON_RUN_STATUS 0x2004U /* 0空闲 1运行 */ | |||
| #define PLSR_MON_CUR_SEG 0x2005U /* 当前执行段 1-based */ | |||
| #define PLSR_MON_ERR 0x2006U /* 错误码 */ | |||
| #define PLSR_CMD_IDLE 0U | |||
| #define PLSR_CMD_START 1U | |||
| #define PLSR_CMD_STOP 2U | |||
| #define PLSR_CMD_IMPORT 3U | |||
| /* ---------- 控制寄存器(读/写,处理后由从站清 0) ---------- */ | |||
| #define PLSR_CTRL_REG 0x3000U | |||
| #define PLSR_CTRL_BIT_START (1U << 0) /* 启动脉冲 */ | |||
| #define PLSR_CTRL_BIT_STOP (1U << 1) /* 停止脉冲 */ | |||
| #define PLSR_CTRL_BIT_CLR (1U << 2) /* 清除状态信息 */ | |||
| #define PLSR_CMD_COIL_STOP 0x2001U | |||
| #define PLSR_CMD_COIL_CLR_ACC 0x2003U | |||
| /* 故障码(写入 0x10F7,供 Modbus 读取) */ | |||
| #define PLSR_ERR_NONE 0U | |||
| #define PLSR_ERR_SEG_FREQ 1U /* 段频率非法(非 0 且越界,或解析后不在 1~100k) */ | |||
| @@ -47,7 +47,7 @@ | |||
| #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 /* 0=结束;1~N=跳转目标段号 */ | |||
| #define PLSR_SEG_OFF_JUMP 7U /* 0=末段停 / 非末段接下一段;1~N=跳转目标段号 */ | |||
| /* 分帧传输状态(上位机可轮询) */ | |||
| #define PLSR_PARAM_XFER_RECV_REG 0x0FFCU | |||
| @@ -115,7 +115,7 @@ typedef struct { | |||
| PlsrWaitType_e wait_type; | |||
| uint16_t wait_ms; | |||
| uint16_t act_ms; | |||
| uint16_t jump_seg; /* 0=结束;1~N=跳转目标段号 */ | |||
| uint16_t jump_seg; /* 0=末段结束 / 非末段则顺序下一段;1~N=跳转目标段号 */ | |||
| } PlsrSeg_t; | |||
| /* ---------- 运行映像访问 ---------- */ | |||
| @@ -13,13 +13,17 @@ int16_t PlsrPathPlanNextSeg(uint16_t cur_seg_0based) | |||
| /* | |||
| * 跳转目标(1-based): | |||
| * 0 → 结束(含末段写 0) | |||
| * 0 → 末段:结束;非末段:顺序下一段(cur+1) | |||
| * 1..N → 跳到对应段(可顺序、回跳循环、任意段) | |||
| * 其它 → 结束 | |||
| */ | |||
| if (jump == 0U) | |||
| { | |||
| (void)cur_seg_0based; | |||
| /* 非末段写 0:视为顺序下一档,不是停机 */ | |||
| if ((n >= 1U) && (cur_seg_0based + 1U < n)) | |||
| { | |||
| return (int16_t)(cur_seg_0based + 1U); | |||
| } | |||
| return -1; | |||
| } | |||
| if ((jump >= 1U) && (jump <= n)) | |||
| @@ -14,7 +14,8 @@ | |||
| * @brief 解析下一段索引 | |||
| * @param cur_seg_0based 当前段 0-based | |||
| * @return 下一段 0-based;无下一段或非法跳转返回 -1 | |||
| * @note jump=0 结束;jump=1~N 跳到对应段(可循环) | |||
| * @note jump=0:末段→结束;非末段→顺序下一段 | |||
| * jump=1~N:跳到对应段(可循环) | |||
| */ | |||
| int16_t PlsrPathPlanNextSeg(uint16_t cur_seg_0based); | |||