From 4c3793fa8af53fb2a1c28a45b1332ccb22d55ddd Mon Sep 17 00:00:00 2001 From: ywh <2227158009@qq.com> Date: Wed, 5 Aug 2026 12:51:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E9=9C=80=E6=B1=82?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PLSR_document/PLSR_Modbus通信协议.md | 657 ------------------ .../PLSR信捷对标追踪矩阵.md | 7 +- .../PLSR_document/PLSR需求确认清单.md | 524 -------------- ...计.md => PLSR需求规格统计_V1.3.md} | 404 +++++++++-- Document/PLSR_document/~$需求规格书.docx | Bin 0 -> 162 bytes Document/PLSR_document/需求规格书.docx | Bin 32324 -> 46363 bytes 6 files changed, 332 insertions(+), 1260 deletions(-) delete mode 100644 Document/PLSR_document/PLSR_Modbus通信协议.md delete mode 100644 Document/PLSR_document/PLSR需求确认清单.md rename Document/PLSR_document/{PLSR需求规格统计.md => PLSR需求规格统计_V1.3.md} (67%) create mode 100644 Document/PLSR_document/~$需求规格书.docx diff --git a/Document/PLSR_document/PLSR_Modbus通信协议.md b/Document/PLSR_document/PLSR_Modbus通信协议.md deleted file mode 100644 index d5142c1..0000000 --- a/Document/PLSR_document/PLSR_Modbus通信协议.md +++ /dev/null @@ -1,657 +0,0 @@ -# PLSR Modbus通信协议 - -> 协议版本:V1.0 -> 地址表修订:R5 -> 目标平台:XDM-60T4-E -> 对标依据:[信捷XD/XL系列PLC定位控制手册](./信捷XD_XL系列PLC定位控制手册_PD02_20260510_V1.3.pdf) -> 对应需求:[PLSR需求规格统计.md](./PLSR需求规格统计.md) -> -> R5变更:取消Modbus通信历史区;S0、S1改为在1000~9199数据池中运行时指定首地址 -> 的动态数据块;其余PLSR参数和状态固定映射到Modbus保持寄存器。取消固定S0槽和 -> 每轴内嵌S1数据。 -> R4变更:已定义固定字段的PLSR地址标记为已占用;仅未定义字段的扩展区保持保留。 -> R3变更:区分工程已占用地址和PLSR推荐预留地址。 -> R2变更:区分可选操作数、固定相对布局和信捷固定软元件地址;增加Y0~Y3公共参数、 -> K0~K4参数组及运行状态地址与本项目Modbus字段的逐项对应表。 - -## 1. 地址和数据约定 - -### 1.1 地址表示 - -本文所有地址均为Modbus PDU中的**零基地址**。例如: - -| 本文地址 | 传统4xxxx写法 | -|---:|---:| -| 200 | 40201 | -| 5160 | 45161 | - -上位机如果使用“地址从1开始”显示,应在本文地址基础上加1。代码、报文和测试用例 -统一使用本文零基地址,禁止直接把`40201`作为PDU地址发送。 - -### 1.2 字节序和字序 - -- 单个16位寄存器使用Modbus大端字节序。 -- 32位数据占两个寄存器,高16位在前、低16位在后。 -- 64位数据占四个寄存器,从最高16位到最低16位依次排列。 -- 有符号数采用二进制补码。 -- 写入32位或64位命令参数时必须使用功能码`0x10`一次写完,禁止拆成多个`0x06`后立即触发。 - -示例:32位数`0x12345678`从地址A开始保存为: - -```text -A+0 = 0x1234 -A+1 = 0x5678 -``` - -### 1.3 访问权限 - -| 标记 | 含义 | -|---|---| -| RO | 只读,主站写入应返回非法数据地址或非法数据值 | -| RW-S | 影子参数可读写,COMMIT成功后才进入运行配置 | -| RW-L | 运行时可读写,按字段定义立即或在控制周期内生效 | -| WO-T | 只写触发字段;写入后产生一次命令处理 | -| RES | 保留,读回0,写入拒绝 | - -当前工程的通用Modbus数组尚未实施字段级读写权限。接入PLSR时必须增加地址权限校验, -不能仅依赖文档约束上位机。 - -### 1.4 原子提交规则 - -1. 每轴保存S0、S1动态数据块首地址;S2、D和公共参数使用固定地址影子区。 -2. 主站写完某轴配置后,发送`COMMIT_AXIS`命令。 -3. 从站完整检查段数、输出冲突、频率、跳转、限位和参数范围。 -4. 校验成功后原子复制到该轴运行配置,并更新`ACTIVE_GENERATION`。 -5. 校验失败时运行配置保持不变,返回错误码和错误数据块号。 -6. 已启动任务不受后续影子参数写入影响;运行中调频使用`SET_TARGET_FREQUENCY`命令。 -7. COMMIT成功后轴使用S0、S1、S2和D的私有不可变运行快照;修改原动态数据块不得 - 影响已经提交或已经启动的任务。 - -### 1.5 信捷地址与本项目地址的关系 - -本协议区分三类地址,不得混为一谈: - -1. **可选操作数地址**:信捷PLSR的S0、S1由用户在指令中指定。本项目用每轴固定的 - `S0_BASE_ADDRESS`和`S1_BASE_ADDRESS`保存其运行时首地址;S0、S1数据本身不固定。 - D在本项目中选择Q输出点,S2通过`SELECTED_S2`选择K0~K4。 -2. **固定相对偏移**:S0头部、每段10字、S1两个双字以及S2套组内部字段的相对 - 布局固定。本项目保持这些功能布局。 -3. **固定绝对软元件地址**:信捷为Y0~Y3固定分配SFD、HSD、SD和SM地址。本项目不把 - 这些编号直接作为Modbus PDU地址,而是在第4章提供确定的一一对应关系。 - -因此,“对标信捷固定地址”表示每个信捷字段都能唯一映射到本项目字段并保持等效语义, -不表示主站可以把`SFD900`直接当作Modbus地址900访问。若后续需要兼容信捷软元件编号, -应增加独立的地址转换层;已经实施并冻结的Modbus PDU地址不得直接改义。 - -## 2. 现有占用和推荐预留方案 - -工程标准Modbus保持寄存器范围为0~9999。下表中的数值全部是**本项目Modbus PDU -零基地址**,不是信捷SFD、HSD或SD软元件编号。信捷不同类型的软元件拥有彼此独立的 -编号空间,例如SFD和SD可以出现相同编号,不能直接合并到一个Modbus保持寄存器空间。 - -当前占用情况及推荐预留方案如下: - -| Modbus保持寄存器范围 | 数量 | 当前状态 | 推荐用途 | 信捷PLSR对应关系 | 所有者/建议使用者 | -|---:|---:|---|---|---|---| -| 0~199 | 79 | 保留 | 无 | 无 | 待定 | -| 200~255 | 56 | 保留 | PLSR全局信息、命令和应答 | 指令调用与诊断增强;信捷无同地址区 | PLSR | -| 256~895 | 640 | 已占用 | 四轴S0/S1基址、D、S2和实时状态 | S0/S1为动态操作数;其余对应Y0~Y3固定参数和状态,详见4.1~4.4 | PLSR | -| 896~999 | 104 | 保留 | 推荐作为PLSR动态数据块描述符或近期扩展区 | 无固定信捷地址 | 待定 | -| 1000~9199 | 8200 | 已占用 | S0/S1动态数据池,运行时指定各数据块首地址 | 对应信捷可动态指定首地址的S0和S1数据块 | PLSR | -| 9200~9999 | 800 | 保留 | 推荐用于PLSR后续扩展或事件历史,也可在地址冻结前另行分配 | 无 | 待定 | - -标为“已占用”的范围已经确定具体字段或数据结构,其他模块不得覆盖,即使对应代码尚未 -全部实现,也应视为地址协议已经占位。标为“保留”的范围没有确定字段,推荐用途不构成 -占用;正式分配前仍可调整,但必须更新本地址表修订号并完成全工程冲突检查。 - -本表规定“已确定的数据放在本项目哪个Modbus地址”;第4章解决“该字段对应信捷哪个固定 -软元件地址”。两张表必须结合使用。V1.0不提供把`SFD900`直接解释为PDU地址900的 -物理地址兼容模式。 - -## 3. 全局信息、命令和应答:200~255 - -| 地址 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| 200 | PROTOCOL_MAGIC_0 | U16 | RO | 固定`0x504C`,ASCII `PL` | -| 201 | PROTOCOL_MAGIC_1 | U16 | RO | 固定`0x5352`,ASCII `SR` | -| 202 | PROTOCOL_VERSION_MAJOR | U16 | RO | 主版本,V1为1 | -| 203 | PROTOCOL_VERSION_MINOR | U16 | RO | 次版本 | -| 204 | ADDRESS_MAP_REVISION | U16 | RO | 地址表修订R5为5 | -| 205 | AXIS_COUNT | U16 | RO | 固定4 | -| 206 | MAX_SEGMENTS | U16 | RO | 固定100 | -| 207 | CAPABILITY_FLAGS | U16 | RO | 能力标志,见3.1 | -| 208~209 | GUARANTEED_MAX_HZ | U32 | RO | 100000 | -| 210~211 | EXTENDED_MAX_HZ | U32 | RO | 200000,非保证扩展区 | -| 212 | REFRESH_CAPABILITIES | U16 | RO | bit0=1 ms,bit1=0.1 ms | -| 213 | GLOBAL_STATUS | U16 | RO | 全局状态标志 | -| 214~215 | RESERVED | - | RES | 保留 | -| 216 | CMD_CODE | U16 | RW-L | 命令码,见3.2 | -| 217 | CMD_AXIS | U16 | RW-L | 0~3;`0xFFFF`表示允许的全轴命令 | -| 218 | CMD_FLAGS | U16 | RW-L | 命令选项 | -| 219 | CMD_RESERVED | - | RES | 保留 | -| 220~223 | CMD_ARG0 | U64/I64 | RW-L | 命令参数0 | -| 224~227 | CMD_ARG1 | U64/I64 | RW-L | 命令参数1 | -| 228~229 | CMD_ARG2 | U32/I32 | RW-L | 命令参数2 | -| 230 | CMD_PAYLOAD_GENERATION | U16 | RW-L | 期望使用的影子参数代号 | -| 231 | CMD_SEQUENCE | U16 | WO-T | **最后写入**;新序号触发一次命令 | -| 232 | ACK_SEQUENCE | U16 | RO | 最近处理完成的命令序号 | -| 233 | CMD_RESULT | U16 | RO | 处理结果,见3.3 | -| 234 | CMD_ERROR_CODE | U16 | RO | 错误码 | -| 235 | CMD_ERROR_DETAIL | U16 | RO | 错误字段或数据块号 | -| 236~239 | ACK_DATA | U64 | RO | 命令返回数据 | -| 240 | GLOBAL_SHADOW_GENERATION | U16 | RO | 最近收到的全局影子代号 | -| 241 | GLOBAL_ACTIVE_GENERATION | U16 | RO | 已生效的全局配置代号 | -| 242 | LAST_EVENT_SEQUENCE | U16 | RO | 全局最近事件序号 | -| 243 | LAST_EVENT_AXIS | U16 | RO | 最近事件轴号 | -| 244 | LAST_EVENT_SEGMENT | U16 | RO | 最近事件段号,1~100 | -| 245 | LAST_EVENT_REASON | U16 | RO | 最近事件原因 | -| 246 | SELF_TEST_STATUS | U16 | RO | 自测状态 | -| 247 | SELF_TEST_ERROR | U16 | RO | 自测错误 | -| 248~255 | RESERVED | - | RES | 保留 | - -### 3.1 CAPABILITY_FLAGS - -| 位 | 含义 | -|---:|---| -| 0 | PULSE/DIR | -| 1 | AB相x4计数 | -| 2 | 四轴独立运行 | -| 3 | 100段路径 | -| 4 | 相对定位 | -| 5 | 绝对定位 | -| 6 | 软限位 | -| 7 | 齿隙补偿 | -| 8 | FOLLOW参数 | -| 9 | 工程单位换算 | -| 10 | 0.1 ms刷新 | -| 11 | Backup SRAM检查点 | -| 12 | 命令序号防重 | -| 13~15 | 保留 | - -### 3.2 CMD_CODE - -| 值 | 命令 | CMD_ARG0 | 说明 | -|---:|---|---|---| -| 0 | NOP | - | 不执行 | -| 1 | COMMIT_AXIS | - | 校验指定轴的S0/S1动态块及S2/D固定参数,并创建运行快照 | -| 2 | START | - | 异步启动指定轴 | -| 3 | STOP_DECEL | - | 指定轴减速停止;轴`0xFFFF`表示全部轴 | -| 4 | STOP_IMMEDIATE | - | 指定轴立即停止;轴`0xFFFF`表示全部轴 | -| 5 | PAUSE | - | 减速暂停 | -| 6 | RESUME | - | 继续暂停任务 | -| 7 | SET_POSITION | I64位置 | 设置逻辑当前位置并置`position_valid` | -| 8 | CLEAR_POSITION | - | 当前位置清零并置有效 | -| 9 | CLEAR_TOTAL | - | 清零累计输出脉冲 | -| 10 | SAVE_CONFIG | - | 固定配置保存到Flash | -| 11 | LOAD_CONFIG | - | 加载已保存固定配置,不自动启动 | -| 12 | RESET_ERROR | - | 清除可恢复错误 | -| 13 | SELF_TEST | 测试掩码 | 执行内部自测 | -| 14 | SET_TARGET_FREQUENCY | U32频率 | 运行中调频,在S2刷新周期内开始生效 | -| 15 | CLEAR_EVENT | - | 确认并清除最近事件锁存 | - -### 3.3 CMD_RESULT - -| 值 | 名称 | 含义 | -|---:|---|---| -| 0 | IDLE | 尚未处理命令 | -| 1 | ACCEPTED | 已接受,异步执行中 | -| 2 | SUCCESS | 执行成功 | -| 3 | REJECTED | 命令被拒绝,查看错误码 | -| 4 | DUPLICATE | 相同序号,未重复执行并返回上次结果 | - -`CMD_SEQUENCE`为16位循环序号。主站发送新命令时递增,通信重试必须保持原序号。 -从站缓存最近序号及完整结果;相同序号不得再次产生运动。 - -## 4. 每轴固定块:256~895 - -每轴占160个保持寄存器: - -```text -AXIS_BASE(axis) = 256 + axis × 160,axis取0~3 -``` - -| 轴 | AXIS_BASE | 范围 | -|---:|---:|---:| -| 0 | 256 | 256~415 | -| 1 | 416 | 416~575 | -| 2 | 576 | 576~735 | -| 3 | 736 | 736~895 | - -### 4.1 信捷固定地址逐轴对应 - -下表给出信捷Y0~Y3固定软元件区与本项目轴块的唯一对应关系。信捷使用Y点名称, -本项目板级输出使用Q点名称;表中的Y0~Y3表示信捷对标轴序号,不等于本项目Q点编码。 - -| 本项目轴 | 信捷脉冲轴D | 本项目轴块 | 信捷公共参数 | 信捷K0动态参数 | 信捷K1 | 信捷K2 | 信捷K3 | 信捷K4 | -|---:|---|---:|---|---|---|---|---|---| -| 0 | Y0 | 256~415 | SFD900~943 | HSD460~479 | SFD950~969 | SFD970~989 | SFD990~1009 | SFD1010~1029 | -| 1 | Y1 | 416~575 | SFD1030~1073 | HSD480~499 | SFD1080~1099 | SFD1100~1119 | SFD1120~1139 | SFD1140~1159 | -| 2 | Y2 | 576~735 | SFD1160~1203 | HSD500~519 | SFD1210~1229 | SFD1230~1249 | SFD1250~1269 | SFD1270~1289 | -| 3 | Y3 | 736~895 | SFD1290~1333 | HSD520~539 | SFD1340~1359 | SFD1360~1379 | SFD1380~1399 | SFD1400~1419 | - -信捷固定运行状态地址与本项目实时状态区对应如下: - -| 本项目轴 | 信捷运行标志 | 信捷方向标志 | 信捷实时SD区 | 信捷累计脉冲 | 本项目实时状态区 | -|---:|---|---|---|---|---:| -| 0 | SM1000 | SM1001 | SD1000~1011 | HSD0~1 | 384~415 | -| 1 | SM1020 | SM1021 | SD1020~1031 | HSD4~5 | 544~575 | -| 2 | SM1040 | SM1041 | SD1040~1051 | HSD8~9 | 704~735 | -| 3 | SM1060 | SM1061 | SD1060~1071 | HSD12~13 | 864~895 | - -信捷段事件中断号固定为Y0对应`I6000~I6099`、Y1对应`I6100~I6199`、Y2对应 -`I6200~I6299`、Y3对应`I6300~I6399`。本项目不复用PLC中断号,而通过 -`SEGMENT_EVENT_SEQUENCE`、`SEGMENT_EVENT_NUMBER`和`SEGMENT_EVENT_REASON`发布等效事件。 - -常用起始地址速查: - -| 轴 | S0/S1动态基址配置 | D/公共参数 | S2-K0 | 实时状态 | -|---:|---:|---:|---:|---:| -| 0 | 256 | 272 | 304 | 384 | -| 1 | 416 | 432 | 464 | 544 | -| 2 | 576 | 592 | 624 | 704 | -| 3 | 736 | 752 | 784 | 864 | - -### 4.2 S0/S1动态基址和选择信息:AXIS_BASE+0~15 - -| 偏移 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| +0 | S0_BASE_ADDRESS | U16 | RW-S | S0数据块在1000~9199动态池中的零基首地址 | -| +1 | S0_WORD_COUNT | U16 | RW-S | S0实际占用字数,必须等于`10+段数×10` | -| +2 | S1_BASE_ADDRESS | U16 | RW-S | S1数据块在1000~9199动态池中的零基首地址 | -| +3 | SELECTED_S2 | U16 | RW-S | 选择固定参数套组K0~K4,取值0~4 | -| +4 | AXIS_SHADOW_GENERATION | U16 | RW-S | 主站写完S0、S1和轴参数后最后递增 | -| +5 | AXIS_ACTIVE_GENERATION | U16 | RO | 最近成功COMMIT的代号 | -| +6 | AXIS_CONFIG_STATUS | U16 | RO | bit0影子完整,bit1活动配置有效,bit2影子已修改 | -| +7 | EXPECTED_S0_CRC16 | U16 | RW-S | COMMIT时核对S0数据块CRC16,防止写入中途启动 | -| +8 | EXPECTED_S1_CRC16 | U16 | RW-S | COMMIT时核对S1的4个字 | -| +9 | OPERAND_FLAGS | U16 | RW-S | 当前必须为0,保留动态数据块属性扩展 | -| +10 | ACTIVE_S0_BASE_ADDRESS | U16 | RO | 最近成功COMMIT快照的S0来源首地址 | -| +11 | ACTIVE_S1_BASE_ADDRESS | U16 | RO | 最近成功COMMIT快照的S1来源首地址 | -| +12~+15 | RESERVED | - | RES | 保留 | - -`AXIS_BASE+0~15`只保存操作数地址、固定参数组选择和原子提交信息,不保存S0、S1 -数据本体。S0和S1可以被不同轴共享;COMMIT后各轴使用私有快照,后续改写动态数据池 -不会改变已提交任务。S0和S1数据块不得重叠,活动写入也不得破坏其他轴正在提交的数据。 - -### 4.3 D及脉冲公共参数:AXIS_BASE+16~47 - -| 偏移 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| +16 | D_PULSE_A_POINT | U16 | RW-S | PULSE点或AB的A点,点编码见4.6 | -| +17 | D_DIR_B_POINT | U16 | RW-S | DIR点或AB的B点 | -| +18 | D_OUTPUT_MODE | U16 | RW-S | 0=PULSE/DIR,1=AB相 | -| +19 | PULSE_OUTPUT_POLARITY | U16 | RW-S | 0正常,1反相 | -| +20 | DIRECTION_POLARITY | U16 | RW-S | 0正逻辑,1负逻辑 | -| +21 | COUNT_EDGE | U16 | RO | PULSE/DIR固定0=物理上升沿;AB固定4=x4 | -| +22 | DIRECTION_DELAY_MS | U16 | RW-S | 默认10 ms | -| +23 | PULSE_UNIT | U16 | RW-S | 单位编码见4.5 | -| +24~+25 | PULSES_PER_REV | U32 | RW-S | 每转指令脉冲数,必须非0 | -| +26~+27 | MOVE_UNITS_PER_REV | U32 | RW-S | 每转移动量,单位为所选工程单位,必须非0 | -| +28 | SEGMENT_SEND_MODE | U16 | RW-S | 0完成方式,1后续方式 | -| +29 | SOFT_LIMIT_ENABLE | U16 | RW-S | 0关闭,1启用 | -| +30 | POS_LIMIT_INPUT | U16 | RW-S | 正限位输入点编码,`0xFFFF`无输入 | -| +31 | NEG_LIMIT_INPUT | U16 | RW-S | 负限位输入点编码,`0xFFFF`无输入 | -| +32 | LIMIT_INPUT_POLARITY | U16 | RW-S | bit0正限位、bit1负限位;0常开,1常闭 | -| +33 | COMMON_FLAGS | U16 | RW-S | 保留扩展标志,当前必须写0 | -| +34~+35 | SOFT_POSITIVE_LIMIT | I32 | RW-S | 正软限位逻辑坐标 | -| +36~+37 | SOFT_NEGATIVE_LIMIT | I32 | RW-S | 负软限位逻辑坐标 | -| +38~+39 | BACKLASH_POSITIVE | U32 | RW-S | 正向齿隙补偿量 | -| +40~+41 | BACKLASH_NEGATIVE | U32 | RW-S | 反向齿隙补偿量 | -| +42~+43 | ELECTRICAL_ORIGIN | I32 | RW-S | 电气原点位置 | -| +44 | AB_COUNT_MODE | U16 | RO | 固定4,表示x4边沿计数 | -| +45 | OUTPUT_RESOURCE_FLAGS | U16 | RO | 输出能力和占用状态 | -| +46~+47 | RESERVED | - | RES | 保留 | - -信捷公共参数地址设为`B`:Y0/Y1/Y2/Y3的`B`分别为SFD900/SFD1030/SFD1160/SFD1290。 -本项目公共字段按下表与信捷固定地址对应;无直接对应项属于本项目增强字段。 - -| 本项目偏移 | 本项目字段 | 信捷固定地址/字段 | -|---:|---|---| -| +16 | D_PULSE_A_POINT | PLSR的D操作数(Y0~Y3),不是SFD参数 | -| +17 | D_DIR_B_POINT | B+6,脉冲方向端子 | -| +18 | D_OUTPUT_MODE | B+0中的脉冲输出类型/AB相配置 | -| +19 | PULSE_OUTPUT_POLARITY | B+0中的脉冲输出逻辑 | -| +20 | DIRECTION_POLARITY | B+0中的方向逻辑 | -| +21、+44 | COUNT_EDGE、AB_COUNT_MODE | 本项目固定语义,信捷无独立参数地址 | -| +22 | DIRECTION_DELAY_MS | B+7 | -| +23 | PULSE_UNIT | B+0中的脉冲单位字段 | -| +24~+25 | PULSES_PER_REV | B+2~B+3 | -| +26~+27 | MOVE_UNITS_PER_REV | B+4~B+5 | -| +28 | SEGMENT_SEND_MODE | B+1 | -| +29 | SOFT_LIMIT_ENABLE | B+0中的软限位使能位 | -| +30~+31 | POS/NEG_LIMIT_INPUT | B+15的高、低字节 | -| +32 | LIMIT_INPUT_POLARITY | B+12中的限位端子极性位 | -| +34~+35 | SOFT_POSITIVE_LIMIT | B+20~B+21 | -| +36~+37 | SOFT_NEGATIVE_LIMIT | B+22~B+23 | -| +38~+39 | BACKLASH_POSITIVE | B+8 | -| +40~+41 | BACKLASH_NEGATIVE | B+9 | -| +42~+43 | ELECTRICAL_ORIGIN | B+10~B+11 | -| +45 | OUTPUT_RESOURCE_FLAGS | 本项目资源冲突检查增强字段 | - -### 4.4 S2参数套组:AXIS_BASE+48~127 - -每轴有5套S2,每套16个寄存器: - -```text -S2_BASE(axis, set) = AXIS_BASE(axis) + 48 + set × 16 -set取0~4 -``` - -| 相对S2偏移 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| +0~+1 | DEFAULT_FREQUENCY_HZ | U32 | RW-S | 段频率为0时使用,同时定义加减速斜率基准 | -| +2 | ACCEL_TIME_MS | U16 | RW-S | 默认速度对应的加速时间,0表示无加速 | -| +3 | DECEL_TIME_MS | U16 | RW-S | 默认速度对应的减速时间,0表示无减速 | -| +4 | BACKLASH_TIME_MS | U16 | RW-S | 齿隙补偿加减速时间 | -| +5 | CURVE_MODE | U16 | RW-S | 0直线,1=S形,2=正弦,3保留 | -| +6~+7 | MAX_FREQUENCY_HZ | U32 | RW-S | 最高速度限制 | -| +8~+9 | START_FREQUENCY_HZ | U32 | RW-S | 任务起始速度 | -| +10~+11 | END_FREQUENCY_HZ | U32 | RW-S | 任务终止速度 | -| +12 | FOLLOW_PERFORMANCE | U16 | RW-S | 1~100 | -| +13 | FOLLOW_FEEDFORWARD | U16 | RW-S | 0~100% | -| +14 | REFRESH_PERIOD | U16 | RW-S | 0=1 ms,1=0.1 ms | -| +15 | RESERVED | - | RES | 保留 | - -S2第0套保存在Backup SRAM动态区,第1~4套属于固定配置并由`SAVE_CONFIG`保存到Flash。 - -信捷每套S2参数也采用20个软元件的固定步长,其中PLSR字段使用`P+0~P+14`, -`P+15`保留,`P+16~P+19`为ZRN参数。本项目只映射PLSR所需的前16个寄存器: - -| 本项目S2偏移 | 信捷参数组偏移 | 含义 | -|---:|---:|---| -| +0~+1 | P+0~P+1 | 默认速度/频率 | -| +2 | P+2 | 加速时间 | -| +3 | P+3 | 减速时间 | -| +4 | P+4 | 补间/补偿加减速时间 | -| +5 | P+5 | 脉冲加减速模式 | -| +6~+7 | P+6~P+7 | 最高速度 | -| +8~+9 | P+8~P+9 | 起始速度 | -| +10~+11 | P+10~P+11 | 终止速度 | -| +12 | P+12 | FOLLOW性能参数 | -| +13 | P+13 | FOLLOW前馈补偿参数 | -| +14 | P+14 | 脉冲频率刷新时间 | -| +15 | P+15 | 保留 | - -### 4.5 PULSE_UNIT编码 - -编码与信捷配置语义对应: - -| 值 | 单位 | -|---:|---| -| 0 | 脉冲个数/Hz | -| 1 | 1 μm | -| 3 | 0.01 mm | -| 5 | 0.1 mm | -| 7 | 1 mm | - -### 4.6 Q点和I点编码 - -PLC点名采用八进制风格编号,寄存器中使用连续逻辑ID,避免把Q10误解成十进制第10点: - -| ID | 输出点 | MCU | ID | 输出点 | MCU | -|---:|---|---|---:|---|---| -| 0 | Q0 | PF6 | 9 | Q11 | PG6 | -| 1 | Q1 | PF8 | 10 | Q12 | PH9 | -| 2 | Q2 | PF7 | 11 | Q13 | PH8 | -| 3 | Q3 | PF9 | 12 | Q14 | PH7 | -| 4 | Q4 | PI8 | 13 | Q15 | PH6 | -| 5 | Q5 | PE6 | 14 | Q16 | PF11 | -| 6 | Q6 | PE5 | 15 | Q17 | PB0 | -| 7 | Q7 | PE4 | 16 | Q20 | PH5 | -| 8 | Q10 | PG7 | 65535 | 无输出点 | - | - -输入点采用相同连续ID规则:I0~I7对应0~7,I10~I17对应8~15,I20对应16, -`0xFFFF`表示无输入点。具体MCU引脚由板型适配表定义。 - -### 4.7 实时状态:AXIS_BASE+128~159 - -状态读取应采用快照:从站更新所有多字字段后最后递增`SNAPSHOT_SEQUENCE`;主站读取前后 -两次序号一致时,才能认为本次状态一致。 - -| 偏移 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| +128 | AXIS_STATE | U16 | RO | 状态枚举见4.8 | -| +129 | AXIS_STATUS_FLAGS | U16 | RO | 方向、输出和限位等标志 | -| +130 | ERROR_CODE | U16 | RO | 当前锁存错误 | -| +131 | ERROR_DATA_BLOCK | U16 | RO | 出错字段或段号 | -| +132 | CURRENT_SEGMENT | U16 | RO | 当前段号1~100,空闲为0 | -| +133 | TOTAL_SEGMENTS | U16 | RO | 当前任务总段数 | -| +134 | ACTIVE_S2 | U16 | RO | 当前S2套组0~4 | -| +135 | LAST_STOP_REASON | U16 | RO | 完成、STOP、限位、急停或错误 | -| +136~+137 | CURRENT_FREQUENCY_HZ | U32 | RO | 当前实际指令频率 | -| +138~+139 | TARGET_FREQUENCY_HZ | U32 | RO | 当前目标频率 | -| +140~+141 | SEGMENT_EMITTED | U32 | RO | 本段已发指令脉冲/AB计数边沿 | -| +142~+143 | SEGMENT_REMAINING | U32 | RO | 本段剩余数量 | -| +144~+147 | LOGICAL_POSITION | I64 | RO | 当前逻辑位置 | -| +148~+151 | TOTAL_PULSE_COUNT | U64 | RO | 总累计输出量 | -| +152~+155 | TASK_EMITTED | U64 | RO | 本次任务累计输出量 | -| +156 | SEGMENT_EVENT_SEQUENCE | U16 | RO | 每次段事件递增 | -| +157 | SEGMENT_EVENT_NUMBER | U16 | RO | 最近事件段号 | -| +158 | SEGMENT_EVENT_REASON | U16 | RO | 完成、ACT、EXT、STOP等 | -| +159 | SNAPSHOT_SEQUENCE | U16 | RO | 状态快照序号,最后更新 | - -### 4.8 AXIS_STATE - -| 值 | 状态 | -|---:|---| -| 0 | UNINITIALIZED | -| 1 | IDLE | -| 2 | ACCEL | -| 3 | RUN | -| 4 | DECEL | -| 5 | WAIT | -| 6 | PAUSED | -| 7 | COMPLETED | -| 8 | STOPPED | -| 9 | ERROR | - -### 4.9 AXIS_STATUS_FLAGS - -| 位 | 含义 | -|---:|---| -| 0 | 指令活动,包括运动、等待和暂停 | -| 1 | 物理脉冲正在输出 | -| 2 | 正方向 | -| 3 | AB模式 | -| 4 | 位置有效 | -| 5 | 正硬限位有效 | -| 6 | 负硬限位有效 | -| 7 | 正软限位到达 | -| 8 | 负软限位到达 | -| 9 | 急停锁存 | -| 10 | 影子配置已修改但未提交 | -| 11 | 活动配置有效 | -| 12~15 | 保留 | - -### 4.10 段事件和停止原因 - -| 值 | 原因 | -|---:|---| -| 0 | NONE | -| 1 | PULSE_COMPLETE | -| 2 | WAIT_TIME_COMPLETE | -| 3 | WAIT_SIGNAL_ACTIVE | -| 4 | ACT_TIME | -| 5 | EXT_SIGNAL | -| 6 | EXT_OR_COMPLETE_BY_EXT | -| 7 | EXT_OR_COMPLETE_BY_PULSE | -| 8 | STOP_DECEL | -| 9 | STOP_IMMEDIATE | -| 10 | POS_LIMIT | -| 11 | NEG_LIMIT | -| 12 | EMERGENCY_STOP | -| 13 | ERROR | -| 14 | NORMAL_TASK_COMPLETE | - -## 5. S0/S1动态数据池:1000~9199 - -S0和S1不设置固定数据块地址。主站在1000~9199范围内自行选择不重叠的连续区域, -写入数据后,把首地址分别写入目标轴的`S0_BASE_ADDRESS`和`S1_BASE_ADDRESS`。 - -动态数据池共8200个保持寄存器,可容纳至少4个满100段的S0数据块、4个S1数据块, -并保留余量。数据池地址已经由PLSR占用,其他模块不得用于通信历史或其他功能。 - -分配必须满足: - -1. S0首地址和S1首地址均位于1000~9199。 -2. S1固定占4个寄存器;S0占用`10+段数×10`个寄存器,范围不得越过9199。 -3. 任意两个同时存在的数据块不得重叠;允许多个轴只读共享同一个完整数据块。 -4. 主站写完数据后计算CRC16,再写入轴基址、字数和期望CRC,最后递增 - `AXIS_SHADOW_GENERATION`并发送`COMMIT_AXIS`。 -5. COMMIT重新检查范围、长度、CRC和字段内容,成功后复制私有快照;CRC不一致时拒绝 - 启动并返回“动态数据块正在变化”。 - -### 5.1 S1数据块 - -S1首地址记为`S1_BASE`,由`S1_BASE_ADDRESS`指定: - -| S1偏移 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| +0~+1 | S1_POSITION_MODE | U32 | RW | 0相对,1绝对 | -| +2~+3 | S1_START_SEGMENT | U32 | RW | 0或1从第1段开始,2~100从指定段开始 | - -S1只包含上述两个双字字段。异步调用、命令序号、轴选择、S2选择以及S0/S1基址均不属于S1。 - -### 5.2 S0头部 - -| S0偏移 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| +0~+1 | SEGMENT_COUNT | U32 | RW-S | 1~100 | -| +2~+9 | RESERVED | - | RES | 对标信捷保留8个寄存器 | - -### 5.3 每段10寄存器布局 - -段号`N`取1~100: - -```text -SEGMENT_BASE(N) = S0_BASE_ADDRESS + N × 10 -``` - -| 段内偏移 | 名称 | 类型 | 权限 | 说明 | -|---:|---|---|---|---| -| +0~+1 | SEGMENT_FREQUENCY | U32 | RW-S | 0表示使用所选S2默认速度 | -| +2~+3 | SEGMENT_PULSE_COUNT | I32 | RW-S | 完整INT32范围,负数表示反向 | -| +4 | WAIT_CONFIG | U16 | RW-S | 高8位等待条件,低8位参数来源类型 | -| +5~+6 | WAIT_VALUE_OR_REFERENCE | U32 | RW-S | 常数值或变量/点编号 | -| +7 | JUMP_SOURCE_TYPE | U16 | RW-S | 低8位有效,高8位必须为0 | -| +8~+9 | JUMP_VALUE_OR_REFERENCE | U32 | RW-S | 常数段号或变量编号 | - -段1位于`S0+10`,段100位于`S0+1000`,最后占用到`S0+1009`。 - -### 5.4 WAIT_CONFIG高8位 - -| 值 | 条件 | 行为 | -|---:|---|---| -| 0 | PULSE_COMPLETE | 本段数量完成后跳转 | -| 1 | WAIT_TIME | 完成后等待指定毫秒数,0按1 ms | -| 2 | WAIT_SIGNAL | 完成后等待位信号有效 | -| 3 | ACT_TIME | 从段开始计时,到时放弃剩余脉冲并跳转 | -| 4 | EXT_SIGNAL | 输入上升沿到来时跳转;若脉冲先完成则等待边沿 | -| 5 | EXT_OR_COMPLETE | EXT边沿或脉冲完成先到者触发跳转 | - -### 5.5 WAIT_CONFIG低8位 - -| 值 | 来源 | WAIT_VALUE_OR_REFERENCE含义 | -|---:|---|---| -| 0 | CONSTANT | 直接常数 | -| 1 | HOLDING_VOLATILE | 普通保持寄存器零基地址 | -| 2 | HOLDING_BACKUP | Backup SRAM保持变量编号/地址 | -| 3 | HOLDING_FLASH | Flash固定参数编号/地址 | -| 4 | INPUT_POINT | I点逻辑ID | -| 5 | INTERNAL_COIL | 普通内部线圈零基地址 | -| 6 | RETAINED_COIL | 掉电保持内部线圈编号 | - -对于WAIT_TIME和ACT_TIME,动态数值为无符号毫秒数;对于WAIT_SIGNAL、EXT_SIGNAL和 -EXT_OR_COMPLETE,动态数值表示位或输入点。EXT条件只允许有效的外部输入来源。 - -### 5.6 JUMP_SOURCE_TYPE - -| 值 | 来源 | -|---:|---| -| 0 | CONSTANT | -| 1 | HOLDING_VOLATILE | -| 2 | HOLDING_BACKUP | -| 3 | HOLDING_FLASH | - -跳转值范围0~100: - -- 0:顺序进入下一段;最后一段为0时任务结束。 -- 1~100:跳转到指定段。 -- 等于当前段:允许有意无限循环。 - -动态跳转变量在发生段转换时读取。超出范围应进入ERROR,不得越界访问S0。 - -## 6. 线圈映射:100~163 - -为对标信捷“正在发脉冲标志”等位状态,每轴分配16个只读线圈: - -该线圈范围已经定义固定状态字段,属于PLSR已占用的线圈地址。其他模块不得覆盖;代码 -接入前仍须扫描现有线圈使用情况,若发现历史冲突,必须升级地址表修订号后整体调整。 -线圈只是兼容性只读镜像,权威状态全部位于每轴保持寄存器实时状态区;不读取线圈也能 -取得完整PLSR状态。 - -```text -AXIS_COIL_BASE(axis) = 100 + axis × 16 -``` - -| 偏移 | 名称 | 权限 | 说明 | -|---:|---|---|---| -| +0 | INSTRUCTION_ACTIVE | RO | 指令仍处于运行/等待/暂停状态 | -| +1 | PULSE_ACTIVE | RO | 当前物理脉冲正在输出 | -| +2 | COMPLETED | RO | 最近任务正常完成 | -| +3 | ERROR | RO | 轴处于错误状态 | -| +4 | WAITING | RO | 正在等待段条件 | -| +5 | PAUSED | RO | 已暂停 | -| +6 | POSITION_VALID | RO | 逻辑位置有效 | -| +7 | CONFIG_VALID | RO | 活动配置有效 | -| +8 | POS_HARD_LIMIT | RO | 正硬限位有效 | -| +9 | NEG_HARD_LIMIT | RO | 负硬限位有效 | -| +10 | POS_SOFT_LIMIT | RO | 正软限位到达 | -| +11 | NEG_SOFT_LIMIT | RO | 负软限位到达 | -| +12 | EMERGENCY_STOP | RO | 软件急停锁存 | -| +13 | SEGMENT_EVENT_TOGGLE | RO | 每次段事件翻转,便于PLC/HMI边沿检测 | -| +14 | AB_MODE_ACTIVE | RO | 当前使用AB模式 | -| +15 | RESERVED | RO | 固定0 | - -轴0线圈范围100~115,轴1为116~131,轴2为132~147,轴3为148~163。 -这些线圈必须在协议处理层拒绝功能码`0x05`和`0x0F`写入。 - -## 7. 对标信捷与本项目增强的边界 - -### 7.1 保持信捷语义 - -- S0头部、每段10寄存器布局、等待类型编码和跳转编码与信捷功能一致。 -- S1仅包含相对/绝对和起始段。 -- S0、S1由调用方在动态数据池中指定首地址,不绑定轴,也不设置固定数据块地址。 -- S2选择0~4套参数,并保留信捷速度、曲线、补偿、FOLLOW和刷新参数。 -- 段频率为0时使用S2默认速度。 -- 运行中修改目标频率在刷新周期内生效,且不改变剩余脉冲数。 - -### 7.2 地址编码边界 - -- 不把HD、HSD、SFD、SM编号直接复刻为Modbus PDU地址,但必须维持第4.1、4.3和4.4节 - 规定的一一对应关系。 -- 不复制XDPPro配置界面。 -- D通过本项目连续逻辑ID保存Q点,并通过轴号、板型映射和资源冲突检查对应信捷Y轴语义。 - -### 7.3 本项目增强 - -- 四轴独立影子参数和原子COMMIT。 -- 命令序号防止Modbus重试造成重复运动。 -- 64位逻辑位置、累计量和任务计数。 -- 独立`INSTRUCTION_ACTIVE`与`PULSE_ACTIVE`,可区分运动和等待。 -- 快照序号保证多字状态一致。 -- AB相x4计数、两轴AB以及混合输出资源检查。 - -## 8. 实现前检查 - -- [ ] 在`modbus_rtu_slave.h`中增加本地址表常量。 -- [ ] 协议处理层实施RO、RW-S、RW-L、WO-T权限。 -- [ ] 功能码`0x10`写多字数据时保持原子性。 -- [ ] CMD_SEQUENCE写入时对命令参数做一致性快照。 -- [ ] COMMIT校验四轴Q点、定时器和AB点对冲突。 -- [ ] 状态发布最后更新SNAPSHOT_SEQUENCE。 -- [ ] 测试地址边界895/896、999/1000、9199/9200和9999。 -- [ ] 测试S0/S1动态块的边界、重叠、共享、长度和CRC校验。 -- [ ] 使用四轴各100段执行读写和并发运行压力测试。 -- [ ] 按第4.1、4.3和4.4节逐项验证信捷固定地址对应关系,无遗漏、无一对多歧义。 diff --git a/Document/PLSR_document/PLSR信捷对标追踪矩阵.md b/Document/PLSR_document/PLSR信捷对标追踪矩阵.md index 6275268..ccf6e8c 100644 --- a/Document/PLSR_document/PLSR信捷对标追踪矩阵.md +++ b/Document/PLSR_document/PLSR信捷对标追踪矩阵.md @@ -2,7 +2,6 @@ > 矩阵版本:V1.0 Rev.B > 基准资料:[信捷XD/XL系列PLC定位控制手册](./信捷XD_XL系列PLC定位控制手册_PD02_20260510_V1.3.pdf) -> 对应规格:[PLSR需求规格统计.md](./PLSR需求规格统计.md) > 对标原则:信捷PLSR已有功能全部纳入,本项目增强功能允许保留;Y0~Y3的PLSR固定软元件 > 地址按[PLSR地址映射](./PLSR地址映射.md)一比一对应。 @@ -35,7 +34,7 @@ | 负数表示反向 | 49 | 有符号脉冲数量决定方向 | 已纳入 | | 频率增减与方向无关 | 49 | 速度规划与方向符号分离 | 已纳入 | | 段频率0使用默认速度 | 56 | 使用当前S2默认速度 | 已纳入 | -| 段脉冲数0的行为 | 56 | 实机确认连续/终止语义后冻结 | 待实机确认 | +| 段脉冲数0的行为 | 56 | 项目冻结为跳过当前段且不输出脉冲;最后一段则完成任务 | 已冻结差异 | | 相对定位 | 17、69等 | 支持相对模式 | 已纳入 | | 绝对定位 | 17、69等 | 支持绝对模式 | 已纳入 | | 绝对目标等于累计位置时不输出 | 50 | 零脉冲直接完成 | 已纳入 | @@ -85,7 +84,7 @@ | 方向输出点 | 31、60等 | 从有效未占用Q点配置 | 等效实现 | | 方向延时 | 31、41 | 默认10 ms,单位ms可配置 | 已纳入 | | PULSE/DIR | 29、49 | 最多四轴 | 已纳入 | -| AB相输出 | 29、70等 | 最多两轴,x4边沿计数 | 增强 | +| AB相输出 | 29、70等 | 最多两轴,一个完整正交周期计1个指令脉冲 | 增强 | | 脉冲单位 | 28~29 | 支持脉冲模式 | 已纳入 | | 1 μm、0.01/0.1/1 mm当量 | 28 | 内核直接换算并保存余数 | 增强 | | 每转脉冲数和每转移动量 | 28、60等 | 公共参数 | 已纳入 | @@ -107,7 +106,7 @@ | Modbus状态监控 | 原子状态快照 | 增强 | | 参数原子提交 | 影子参数加COMMIT | 增强 | | 命令防重 | 命令序号保证只执行一次 | 增强 | -| 四轴资源检查 | PULSE/DIR轴数 + 2×AB轴数不超过4 | 增强 | +| 四轴资源检查 | PULSE/DIR轴数 + 2×AB轴数 + 2×CW/CCW轴数不超过4 | 增强 | | 自测和错误数据块号 | 参数、状态机、计数、跳转、定时器和冲突诊断 | 增强 | ## 7. 关闭准则 diff --git a/Document/PLSR_document/PLSR需求确认清单.md b/Document/PLSR_document/PLSR需求确认清单.md deleted file mode 100644 index 5eaaacc..0000000 --- a/Document/PLSR_document/PLSR需求确认清单.md +++ /dev/null @@ -1,524 +0,0 @@ -# PLSR 需求确认清单 - -> 清单版本:V1.0 Rev.B(S0/S1动态地址及固定参数映射确认) -> 创建日期:2026-08-04 -> 对应需求文档:[PLSR需求规格统计.md](./PLSR需求规格统计.md) - -## 填写说明 - -1. 在选中的选项前将 `[ ]` 修改为 `[x]`。 -2. 标有“单选”的项目只能选择一项。 -3. 标有“多选”的项目可以选择多项。 -4. 不清楚的硬件参数可以选择“待上板实测”。 -5. 如果没有填写,需求评审时默认采用标有“建议”的选项。 -6. 补充内容直接填写在横线或“备注”后。 - -确认人:_虞文昊___________________ -确认日期:_________2026/8/4_________ -计划开始日期:_________2026/8/4_____ -计划验收日期:_______2026/8/25_______ - ---- - -## 1. 开发板范围 - -### 1.1 首版验收平台(单选) - -- [ ] 只验收 XDM-60T4-E,T10-E 仅保留兼容设计(建议) -- [ ] 同时验收 XDM-60T4-E 和 XDM-60T10-E -- [ ] 只验收 XDM-60T10-E -- [x] 只验收 XDM-60T4-E - -补充型号或要求:____________________________________________ - -### 1.2 MCU 和时钟 - -- [x] 确认使用 STM32F407,外部晶振 12 MHz,CPU 168 MHz(建议) -- [ ] 参数需要修改 - -修改内容:____________________________________________________ - -## 2. 轴数和输出点 - -### 2.1 V1.0 轴数(单选) - -- [ ] 单轴(建议) -- [ ] 双轴 -- [x] 四轴(V1.0 的 PULSE/DIR 最多四轴,AB 相最多两轴) -- [ ] 其他:________轴 - -### 2.2 四轴输出点 - -脉冲输出点:Q0、Q1、Q2、Q3 -脉冲 MCU 引脚:Q0/PF6、Q1/PF8、Q2/PF7、Q3/PF9 -脉冲定时器/通道:Q0/PF6/TIM10_CH1、Q1/PF8/TIM13_CH1、Q2/PF7/TIM11_CH1、Q3/PF9/TIM14_CH1 - -AB 相输出点对:AB轴0使用 Q0(A)/Q1(B),AB轴1使用 Q2(A)/Q3(B)。 -每个 PULSE/DIR 轴占用一个高速输出点,每个 AB 轴占用两个高速输出点,且满足 -`PULSE/DIR轴数 + 2 × AB轴数 ≤ 4`。 - -方向点允许从 XDM-60T4-E 的有效输出点 `Q0~Q7、Q10~Q17、Q20` 中运行时配置; -不得与任何正在使用的脉冲点或其它已占用输出点冲突。四轴全部启用时,方向点白名单为: - -| 方向输出点 | MCU 引脚 | 方向输出点 | MCU 引脚 | -|---|---|---|---| -| Q4 | PI8 | Q5 | PE6 | -| Q6 | PE5 | Q7 | PE4 | -| Q10 | PG7 | Q11 | PG6 | -| Q12 | PH9 | Q13 | PH8 | -| Q14 | PH7 | Q15 | PH6 | -| Q16 | PF11 | Q17 | PB0 | -| Q20 | PH5 | | | - -- [x] 上述映射已经原理图确认 -- [ ] 上述映射已经上板实测 -- [ ] 映射尚未确认,开发前需要核对(建议在第 1 周第一天完成) - -### 2.3 输出点配置方式(单选) - -- [ ] 编译时固定脉冲点和方向点 -- [x] 运行时从支持列表中配置(建议) -- [ ] 任意 Q 点均可配置 - -## 3. 伺服脉冲接口 - -### 3.1 输出形式(单选) - -- [ ] PULSE/DIR(建议) -- [ ] CW/CCW -- [ ] PULSE/DIR 和 CW/CCW 都支持 -- [x] PULSE/DIR 和 AB 都支持 -### 3.2 有效边沿(单选) - -- [x] 上升沿(建议) -- [ ] 下降沿 -- [ ] 参数可配置 - -### 3.3 输出极性(单选) - -- [ ] 高电平有效 -- [ ] 低电平有效 -- [x] 参数可配置(建议) -- [ ] 待上板实测 - -### 3.4 伺服驱动器电气参数 - -伺服品牌及型号:______________________________________________ -最大接收频率:________________ Hz -最小高电平时间:______________ us -最小低电平时间:______________ us -最小方向建立时间:____________ us -最小方向保持时间:____________ us - -- [ ] 参数来自伺服驱动器手册 -- [ ] 参数已经示波器实测 -- [x] 暂时未知,按保守值实现并在联调时确认 - -### 3.5 AB 相计数定义 - -- [x] 采用 x4 边沿计数:A 或 B 每次有效跳变计 1 个指令脉冲 -- [x] AB 模式的目标频率表示每秒有效计数边沿数 -- [x] 一个完整 AB 正交周期对应 4 个指令脉冲 -- [x] 停止时允许保持在任一合法正交状态,下一次运动从该状态继续 - -## 4. 频率和脉冲数量 - -### 4.1 V1.0 保证频率范围(单选) - -- [x] 1 Hz~100 kHz(建议) -- [ ] 1 Hz~200 kHz -- [ ] 其他:________ Hz~________ Hz -- [ ] 先按 100 kHz 实现,最高值由上板测试决定 - -### 4.2 频率误差(单选) - -- [ ] 不超过 ±0.1%(建议) -- [ ] 不超过 ±0.5% -- [x] 只要求使用最佳定时器分频值,不设固定百分比 -- [ ] 其他:________________ - -### 4.3 单段脉冲数量(单选) - -- [x] 完整有符号32位,范围 -2,147,483,648~2,147,483,647,对标信捷 -- [ ] 无符号 32 位,方向单独设置 -- [ ] 64 位脉冲数量 -- [ ] 其他:________________ - -### 4.4 正常完成脉冲误差(单选) - -- [x] 必须为 0 个脉冲(建议) -- [ ] 允许误差:±________个脉冲 - -## 5. 定位模式 - -### 5.1 支持模式(多选) - -- [x] 相对定位(必须,建议勾选) -- [x] 绝对定位(必须,建议勾选) -- [x] 设置当前位置 -- [x] 当前逻辑位置清零 - -### 5.2 绝对位置无效时的处理(单选) - -- [x] 禁止绝对定位,必须先设置或清零当前位置(建议) -- [ ] 自动将当前位置视为 0 -- [ ] 自动读取保存值,即使上次异常掉电 -- [ ] 其他:________________________________________________ - -### 5.3 位置单位(单选) - -- [ ] PLSR 内核只使用脉冲和 Hz,工程单位由上位机换算(建议) -- [ ] PLSR 直接支持 mm、mm/s -- [ ] PLSR 直接支持角度、rpm -- [x] 同时支持脉冲单位和工程单位,对标信捷 - -如需工程单位,请填写: - -``` -脉冲、1 mm、0.1 mm、0.01 mm、1 μm -``` - -每圈指令脉冲数:____________ -电子齿轮比:________________ -机械减速比:________________ -丝杠螺距:________________mm - -## 6. 多段路径 - -### 6.1 最大段数(单选) - -- [x] 100 段,对标信捷(建议) -- [ ] 32 段 -- [ ] 16 段 -- [ ] 其他:________段 - -### 6.2 每段参数(多选) - -- [x] 有符号脉冲数量(必须) -- [x] 目标频率(必须) -- [ ] 段起始频率 -- [ ] 段结束频率 -- [x] 等待类型 -- [x] 等待参数 -- [x] 下一段编号 -- [ ] 本段加速时间 -- [ ] 本段减速时间 -- [ ] 本段曲线类型 - -### 6.3 段起止频率配置方式(单选) - -- [ ] 每段显式配置起始频率和结束频率 -- [x] 只配置每段目标频率,由 S2 和相邻段自动推导(建议) -- [ ] 两种方式都支持;显式值优先,未配置时自动推导 - -### 6.4 段间条件(多选) - -- [x] 当前段脉冲发送完成(必须) -- [x] 等待指定时间(建议) -- [x] 等待指定输入点(建议) -- [x] 输入有效或本段完成 -- [x] 指定下一段(建议) -- [ ] 有限循环(建议) -- [x] 从指定段号开始(建议) -- [ ] 上述功能 V1.0 全部实现 -- [x] ACT 指定时间后跳段 -- [x] EXT 外部输入立即跳段 -- [x] 跳转值为 0:顺序执行 -- [x] 最后一段跳转值为 0:结束 -- [x] 跳转到自身:无限循环 -- [x] “有限循环”没有独立循环次数字段,需要通过寄存器、计数器和动态下一段编号实现。 -- [ ] V1.0 只实现顺序执行,其余放到 V1.1 - -### 6.5 多段衔接方式(多选) - -- [x] 完成方式(建议) -- [x] 后续方式(建议) -- [x] 两种方式均作为 V1.0 强制验收项 -- [ ] V1.0 只实现完成方式 - -## 7. 加减速曲线 - -### 7.1 V1.0 曲线(多选) - -- [x] 无加减速(建议)将加速度时间设为0 -- [x] 直线/梯形加减速(必须,建议勾选) -- [x] S 形加减速(必须,建议勾选) -- [x] 正弦曲线加减速 -- [ ] 正弦曲线作为 V1.1 加分项 - -### 7.2 参数方式(单选) - -- [x] S2 保存默认速度和默认加减速时间,按斜率计算(对标信捷) -- [ ] 直接为每次任务设置总加速时间和总减速时间(建议,接口更直观) -- [ ] 两种方式均支持 - -### 7.3 短距离处理(单选) - -- [x] 自动压缩为三角或短距离曲线(建议) -- [ ] 无法完成完整曲线时拒绝启动 -- [ ] 其他:________________________________________________ - -## 8. 调用方式和运行控制 - -### 8.1 调用方式(多选) - -- [ ] 同步等待(建议) -- [x] 异步返回(建议) -- [ ] 两种方式均作为 V1.0 强制功能 - -### 8.2 运行中控制(多选) - -- [x] 动态修改当前段目标频率(必须) -- [x] 频率刷新周期可选 `1 ms` 或 `0.1 ms` -- [x] 刷新周期保存在 S2 中,调频应在所配置的 `1 ms` 或 `0.1 ms` 内开始生效 -- [x] uC/OS-II Tick 保持 `1 ms`;`0.1 ms` PLSR刷新由独立硬件定时器触发 -- [x] 减速停止(必须) -- [x] 立即停止(必须) -- [x] 暂停(建议) -- [x] 继续(建议) -- [ ] 暂停和继续放到 V1.1 - -### 8.3 重复 START(单选) - -- [ ] 运行中拒绝并返回 BUSY,不影响当前任务(建议) -- [ ] 中止当前任务并启动新任务 -- [ ] 将新任务加入队列 -- [x] 运行中拒绝并且不用返回 BUSY,不影响当前任务(建议) - -### 8.4 通信断开时的运动行为(单选) - -- [ ] 已启动任务继续运行,记录通信断开状态(建议) -- [ ] 通信超时后减速停止 -- [ ] 通信超时后立即停止 -- [x] 已启动任务继续运行,不用记录通信断开状态 -- [ ] 参数可配置 - -## 9. 累计数据和掉电保存 - -### 9.1 必须保存的数据(多选) - -- [x] 输出点和输出极性 -- [x] S2 参数套组 -- [x] 默认运行和衔接模式 -- [x] 总累计脉冲数 -- [ ] 正向、反向累计脉冲数 -- [x] 当前逻辑位置及独立有效标志 -- [ ] 当前逻辑位置有累计位置,但无独立有效标志 -- [ ] 未完成任务及剩余路径 - -### 9.2 参数保存方式(单选) - -- [ ] 内部 Flash 双备份、版本号和 CRC(建议) -- [ ] 只使用 Backup SRAM -- [ ] 外部 EEPROM/FRAM,型号:________________ -- [x] 其他:___固定参数使用 Flash;动态参数使用 Backup SRAM,例如累计位置和第 0 套动态参数_____________________________________________ - -### 9.3 运行中突然掉电的恢复等级(单选) - -- [ ] 只保证已完成任务和检查点;上电不续跑,位置可能无效(建议) -- [x] 有 VBAT,恢复 Backup SRAM 最近检查点;上电不续跑 -- [ ] 要求累计位置零脉冲误差恢复,需要增加 FRAM 或掉电检测 -- [ ] 要求自动继续未完成运动(不建议,需单独安全评审) - -板卡是否安装并有效连接 VBAT: - -- [x] 是 -- [ ] 否 -- [ ] 未确认 - -允许异常掉电丢失的最大累计数据:____________________________ - -- [x] 异常掉电后恢复最近检查点供诊断,但将独立 `position_valid` 标志清零 -- [x] 重新清零、设置位置或完成回零前,禁止绝对定位 - -## 10. 安全输入和伺服状态 - -### 10.1 V1.0 输入信号(多选) - -- [x] 急停;V1.0 无外部硬件切断回路,由软件立即停止脉冲输出 - -信捷明确指出“脉冲发送完成”不等于“伺服到位”,In-position 必须读取伺服反馈信号。 - -- [x] 正限位 -- [x] 负限位 -- [ ] 伺服 Ready -- [ ] 伺服 Alarm -- [ ] 伺服 In-position -- [ ] V1.0 不接入上述硬件信号,只预留软件接口(建议按任务书最小范围) - -### 10.2 限位触发后的行为(单选) - -- [x] 减速停止,禁止继续向限位方向运动(建议) -- [ ] 立即停止,禁止继续向限位方向运动 -- [ ] 可按每个输入单独配置 -- [ ] V1.0 不适用 - -### 10.3 急停行为(单选) - -- [ ] 硬件切断脉冲输出,同时软件记录状态(建议用于正式设备) -- [x] 软件立即停止 -- [ ] 软件减速停止 -- [ ] V1.0 不适用 - -## 11. Modbus 接口 - -### 11.1 接口功能(多选) - -- [x] 读取配置和实时状态(必须) -- [x] 写入单段和多段参数(必须) -- [x] 启动、停止和清零(必须) -- [x] 暂停和继续 -- [x] 保存和加载参数(必须) -- [x] 自测和错误复位(必须) - -### 11.2 参数提交方式(单选) - -- [x] 影子参数写入完成后,通过提交命令原子生效(建议) -- [ ] 每写一个寄存器立即生效 -- [ ] 其他:________________________________________________ - -### 11.3 多字数据寄存器顺序(单选) - -- [x] 高字在前、低字在后(建议) -- [ ] 低字在前、高字在后 - -### 11.4 命令防重(单选) - -- [x] 使用命令序号;相同序号只执行一次(建议)普通参数读写不需要 -- [ ] 不使用命令序号 -- [ ] 其他:________________________________________________ - -## 12. 自测和诊断 - -### 12.1 V1.0 自测项目(多选) - -- [ ] 参数版本和 CRC(本项目增强项,不作为信捷对标前提) -- [x] 输出点冲突 -- [x] 定时器时钟和分频 -- [x] 频率、段数和脉冲数量范围 -- [x] 路径跳转和循环(包括跳转目标及死循环) -- [x] 计数溢出 -- [x] 状态机非法转换 -- [ ] 外部输入回接脉冲输出 - -- [x] 频率、参数块、段数据范围检查 -- [x] 当前段和当前输出频率监控 -- [x] 累计脉冲溢出标志 -- [x] 正负限位停止错误 -- [x] PLSR 每段中断 -- [x] 脉冲错误码和错误数据块号 - - -### 12.2 测试设备(多选) - -- [ ] 示波器 -- [x] 逻辑分析仪 -- [ ] 伺服驱动器和电机 -- [ ] 外部脉冲计数器 -- [x] PC Modbus 测试工具 - -现有设备型号:________________________________________________ - -## 13. 性能和资源预算 - -### 13.1 是否接受当前建议指标 - -- [ ] 频率误差不超过 ±0.1% -- [ ] 正常完成脉冲误差为 0 -- [x] 调频在 S2 配置的 1 ms 或 0.1 ms 内开始生效 -- [ ] PLSR 平均 CPU 占用率不超过 20% -- [ ] PLSR 静态 RAM 不超过 8 KiB -- [ ] 脉冲级中断最坏时间不超过 100 kHz 周期的 25% -- [ ] 运行阶段禁止动态内存分配 -- [ ] 连续运行 24 小时无异常 -- [x] 最大额定频率:100 kHz -- [x] 频率刷新周期:1 ms 或 0.1 ms -- [x] 定位数值范围:32 位有符号数 -- [x] 正常完成按指定脉冲数量停止 -需要修改的指标:________________________________________________ - -## 14. 交付范围 - -### 14.1 必须交付(多选) - -- [ ] PLSR 源代码和头文件 -- [ ] 定时器、GPIO 和板型适配代码 -- [ ] Modbus 通信协议 -- [ ] 参数保存模块 -- [ ] 需求规格书 -- [ ] 软件设计说明书 -- [ ] 测试方案 -- [ ] 测试记录和测试报告 -- [ ] 上位机测试工具 -- [ ] 示例程序和使用说明 - -### 14.2 四周周期(单选) - -- [ ] 接受当前四周开发计划(建议) -- [ ] 周期调整为:________周 -- [ ] 硬件和需求冻结后再确定周期 - -## 15. 后续版本和排除项 - -### 15.1 后续版本或加分项(多选) - -- [ ] AB 相正交脉冲输出(已纳入 V1.0) -- [ ] 外部输入脉冲回读诊断 -- [ ] 多轴输出(四轴独立输出已纳入 V1.0) -- [ ] 超过 100 kHz 输出 -- [x] 完整机械回零(ZRN独立指令,仍为后续项) -- [ ] 齿隙补偿(已纳入V1.0 PLSR) -- [ ] FOLLOW 前馈控制(已纳入V1.0 PLSR) -- [ ] 编码器实际位置监控 - -### 15.2 确认 V1.0 不包含(多选) - -- [x] 编码器闭环位置控制 -- [x] 多轴插补 -- [x] 电子凸轮和龙门同步 -- [ ] 信捷专用软元件地址兼容(已改为V1.0必须一比一对应,不再属于排除项) -- [x] XDPPro 参数界面兼容 -- [x] 完整复制信捷全部运动指令语法 - -## 16. 最终确认 - -### 16.1 需求处理结果(单选) - -- [ ] 清单尚未填写完成 -- [ ] 已填写,但仍有项目需要硬件实测 -- [x] 已填写,同意据此更新 V1.0 需求规格书 -- [ ] 已填写并确认,可以开始软件设计和实现 - -仍需讨论的问题: - -1. CW/CCW 双脉冲不纳入 V1.0;V1.0 实现 PULSE/DIR 与 AB 相输出。 -2. 急停无外部硬件切断,由软件立即停止脉冲输出。 -3. AB 相最多同时运行两轴,采用 x4 边沿计数;点对为 Q0/Q1 和 Q2/Q3,定时器/DMA方案仍需上板验证。 - -确认人签字:____________________ -确认日期:______________________ - -## 17. 信捷 PLSR 功能超集补充确认 - -- [x] 信捷PLSR已有功能全部作为V1.0最低基线,本项目增强功能继续保留 -- [x] Y0~Y3的PLSR固定HSD、SFD、SD、SM和I地址按信捷手册一比一对应 -- [x] S1只保存相对/绝对模式和起始执行段;异步调用不占用S1字段 -- [x] S0和S1在Modbus动态数据池中指定首地址,不设置固定数据块地址,不永久绑定到轴 -- [x] COMMIT时创建轴运行快照,提交后修改原S0/S1动态数据块不影响已提交或已运行任务 -- [x] 除S0和S1外,S2、D、公共参数、命令和状态全部映射到固定保持寄存器地址 -- [x] 取消16条Modbus通信历史,其原地址空间释放给S0/S1动态数据池 -- [x] 段频率为0时使用S2默认速度 -- [x] 脉冲数0的确切语义在实现冻结前通过信捷实机或厂家资料确认 -- [x] Wait时间、Wait信号、ACT、EXT、EXT或完成按信捷触发时序实现 -- [x] Wait时间范围1~2,147,483,647 ms,0按1 ms处理 -- [x] 跳转目标支持常数和运行时变量,0为顺序/结束,自身为无限循环 -- [x] 每段产生包含轴号、段号和结束原因的段事件 -- [x] 支持脉冲、1 μm、0.01 mm、0.1 mm和1 mm单位 -- [x] 支持每转脉冲数、每转移动量及累计余数换算 -- [x] 支持软限位、方向逻辑、方向延时和限位输入极性 -- [x] 方向延时默认10 ms,单位ms并可配置 -- [x] 支持正反向齿隙补偿及补偿加减速时间 -- [x] S2支持FOLLOW性能参数和FOLLOW前馈补偿参数 -- [x] 绝对目标等于当前位置时零脉冲完成 -- [x] START接受后锁存运行,触发条件消失不终止任务 -- [x] 100 kHz以上至200 kHz属于非保证扩展区,通过板级测试后开放 diff --git a/Document/PLSR_document/PLSR需求规格统计.md b/Document/PLSR_document/PLSR需求规格统计_V1.3.md similarity index 67% rename from Document/PLSR_document/PLSR需求规格统计.md rename to Document/PLSR_document/PLSR需求规格统计_V1.3.md index f4f97aa..e010382 100644 --- a/Document/PLSR_document/PLSR需求规格统计.md +++ b/Document/PLSR_document/PLSR需求规格统计_V1.3.md @@ -1,18 +1,48 @@ # PLSR 需求规格书 -> 文档版本:V1.0 Rev.B(S0/S1动态地址及固定参数映射基线) -> 更新日期:2026-08-04 +> 文档版本:V1.3 Rev.A(需求冲突统一冻结版) +> 更新日期:2026-08-05 > 目标平台:XDM-60T4-E > 软件平台:STM32F407 + uC/OS-II +## 目录 + +- [1 概述](#1-概述) + - [1.1 项目背景](#11-项目背景) + - [1.2 定义](#12-定义) +- [2 功能需求](#2-功能需求) + - [2.1 系统与硬件功能](#21-系统与硬件功能) + - [2.2 脉冲输出功能](#22-脉冲输出功能) + - [2.3 定位功能](#23-定位功能) + - [2.4 S0、S1、S2、D 功能模型](#24-s0s1s2d-功能模型) + - [2.5 单段与多段路径](#25-单段与多段路径) + - [2.6 加减速与段内变频](#26-加减速与段内变频) + - [2.7 调用与多段衔接模式](#27-调用与多段衔接模式) + - [2.8 运行控制](#28-运行控制) + - [2.9 状态机与状态监控](#29-状态机与状态监控) + - [2.10 Modbus 通信](#210-modbus-通信) + - [2.11 参数与累计数据保存](#211-参数与累计数据保存) + - [2.12 自测与诊断](#212-自测与诊断) + - [2.13 安全与异常处理](#213-安全与异常处理) +- [3 性能需求](#3-性能需求) + - [3.1 脉冲性能](#31-脉冲性能) + - [3.2 实时性能](#32-实时性能) + - [3.3 可靠性](#33-可靠性) + - [3.4 工程单位与换算边界](#34-工程单位与换算边界) +- [4 其它需求](#4-其它需求) + - [4.1 验收要求](#41-验收要求) + - [4.2 交付物](#42-交付物) + - [4.3 后续版本或加分项](#43-后续版本或加分项) + - [4.4 不在当前范围内](#44-不在当前范围内) + - [4.5 实施验证事项](#45-实施验证事项) +- [5 参考资料](#5-参考资料) -[TOC] ## 1 概述 ### 1.1 项目背景 -本项目计划在新一代 XDM 系列 PLC 中实现一个高性能定位脉冲输出模块, -通过 PLC 指令或 Modbus 命令驱动伺服驱动器,完成四轴独立位置控制。 +本项目计划在新一代 XDM 系列 PLC 中实现一个高性能定位脉冲输出模块, 通过 +PLC 指令或 Modbus 命令驱动伺服驱动器,完成四轴独立位置控制。 项目当前已有以下基础: @@ -25,11 +55,12 @@ 本项目以信捷 PLC 的 PLSR 功能作为最低功能基线:信捷 PLSR 已有的功能和 可观察运行语义均应具备;本项目已有的四轴资源管理、Modbus原子提交、命令防重、 -64位累计、诊断和Backup SRAM等增强功能继续保留。Y0~Y3的PLSR操作数、公共参数、 -K0~K4参数组和固定状态地址必须与信捷手册一比一对应;不复制XDPPro参数配置界面。 +64位累计、诊断和Backup +SRAM等增强功能继续保留。Y0~Y3的PLSR固定配置参数和固定状态地址必须与信捷手册 +一比一对应;S0、S1保持动态首地址语义,S2、D保持指令操作数语义;不复制XDPPro参数配置界面。 逐项对应关系见[PLSR信捷对标追踪矩阵](./PLSR信捷对标追踪矩阵.md)。矩阵中未关闭的 -差异不得宣称为“严格功能对标完成”。 +差异不得宣称为"严格功能对标完成"。 V1.0 的目标范围如下: @@ -51,7 +82,7 @@ V1.0 的目标范围如下: ### 1.2 定义 | 名称 | 定义 | -|---|---| +| --- | --- | | PLSR | 本项目的定位脉冲输出模块,支持单段及多段位置控制 | | PULSE/DIR | 脉冲加方向的伺服控制接口,PULSE 表示位置增量,DIR 表示方向 | | AB 相输出 | A、B 两路相差 90° 的正交脉冲接口,通过相位先后表示方向 | @@ -62,7 +93,7 @@ V1.0 的目标范围如下: | 完成方式 | 上一段脉冲发送完后,才开始向下一段频率加减速 | | 后续方式 | 在上一段内提前变频,使段结束时已经达到下一段频率 | | S0 | 路径数据块,保存段数、频率、脉冲数、等待和跳转参数 | -| S1 | 用户执行参数,保存定位模式、起始段和调用方式 | +| S1 | 用户执行参数,仅保存定位模式和起始段 | | S2 | K0~K4运动参数套组,保存速度限制、起止频率、加减速、补偿、FOLLOW和刷新周期 | | D | 输出轴或脉冲输出点 | | 控制周期 | PLSR 更新状态和速度规划的周期,由 S2 配置为 1 ms 或 0.1 ms | @@ -74,7 +105,7 @@ V1.0 的目标范围如下: ### 2.1 系统与硬件功能 | 编号 | 需求 | 优先级 | -|---|---|---| +| --- | --- | --- | | FR-SYS-01 | 系统应运行在 STM32F407 和 uC/OS-II 平台上 | 必须 | | FR-SYS-02 | 系统应使用 12 MHz 外部晶振并运行于 168 MHz 主频 | 必须 | | FR-SYS-03 | 首版应在 XDM-60T4-E(STM32F407IG)上完成验收 | 必须 | @@ -86,7 +117,7 @@ V1.0 的目标范围如下: 已知主要输出点如下: | PLC 点 | MCU 引脚 | -|---|---| +| --- | --- | | Q0 | PF6 | | Q1 | PF8 | | Q2 | PF7 | @@ -116,8 +147,8 @@ Q2/PF7/TIM11_CH1、Q3/PF9/TIM14_CH1,仍应通过上板波形测试确认。 ### 2.2 脉冲输出功能 | 编号 | 需求 | V1.0 指标 | -|---|---|---| -| FR-PUL-01 | 输出形式 | PULSE/DIR、AB 相;不支持 CW/CCW 双脉冲 | +| --- | --- | --- | +| FR-PUL-01 | 输出形式 | PULSE/DIR、AB 相、CW/CCW 双脉冲 | | FR-PUL-02 | PULSE/DIR 有效计数边沿 | 固定为物理上升沿 | | FR-PUL-03 | 脉冲占空比 | 50% | | FR-PUL-04 | 输出频率范围 | 1~100,000 Hz | @@ -128,20 +159,64 @@ Q2/PF7/TIM11_CH1、Q3/PF9/TIM14_CH1,仍应通过上板波形测试确认。 | FR-PUL-09 | 输出点 | 脉冲点和方向点可配置且不得重复 | | FR-PUL-10 | 运行调频 | 修改目标频率后不改变剩余脉冲数量 | | FR-PUL-11 | 四轴运行 | 四轴可独立启动、停止、调频和查询状态 | -| FR-PUL-12 | AB 相方向和计数 | 通过A、B相位先后控制方向;采用x4计数,A或B每次有效跳变计1个指令脉冲 | -| FR-PUL-13 | AB 相轴数 | 最多同时运行两轴;AB轴0使用 Q0(A)/Q1(B),AB轴1使用 Q2(A)/Q3(B) | -| FR-PUL-14 | 高速点资源 | PULSE/DIR轴数 + 2 × AB轴数不得超过4,启动前必须检查资源冲突 | -| FR-PUL-15 | AB 相频率 | 目标频率表示每秒有效计数边沿数,一个完整AB周期对应4个指令脉冲 | +| FR-PUL-12 | AB 相方向和计数 | 通过A、B相位先后控制方向;一个完整A/B正交周期计1个指令脉冲 | +| FR-PUL-13 | AB 相轴数 | 最多同时运行两轴;物理点对固定为 Q0(A)/Q1(B)、Q2(A)/Q3(B),逻辑轴可动态申请空闲点对 | +| FR-PUL-14 | 高速点资源 | PULSE/DIR轴数 + 2 × AB轴数 + 2 × CW/CCW轴数不得超过4,启动前必须检查资源冲突 | +| FR-PUL-15 | AB 相频率 | 目标频率表示每秒完整AB周期数;每周期含4次相位跳变,但只计1个指令脉冲 | | FR-PUL-16 | 默认速度 | 段频率为0时使用当前S2套组的脉冲默认速度 | | FR-PUL-17 | 扩展频率 | 100,001~200,000 Hz作为非保证扩展区,仅在板级测试通过后开放并报告警告 | -手册对“段脉冲个数为0”同时描述了使用默认速度,但没有明确连续输出或零距离的 -终止语义。V1.0实现冻结前必须使用信捷实机或厂家确认该行为,并将结果写入追踪矩阵; -不得自行把0定义为普通非法参数后仍宣称严格对标。 +系统支持三种输出模式: + +| 模式编号 | 输出模式 | 说明 | +| --- | --- | --- | +| 0 | PULSE/DIR | 脉冲+方向输出 | +| 1 | AB 相 | 正交脉冲输出 | +| 2 | CW/CCW | 双脉冲方向输出 | + +要求: + +- 三种模式均应支持正反方向控制; +- 输出模式运行前不可修改; +- 输出点必须支持资源冲突检查; +- 不同轴之间高速输出资源不得重复占用。 + +高速输出资源按以下规则统一: + +- 物理高速资源固定为Q0~Q3,不改变其MCU引脚和定时器映射; +- 逻辑运动轴不永久绑定高速资源,START时申请、任务终止时释放; +- PULSE/DIR占用1个高速资源;AB相和CW/CCW各占用2个高速资源; +- AB相及CW/CCW只能使用Q0/Q1或Q2/Q3有效点对; +- 正常完成、STOP或ERROR退出后必须释放本任务占用的高速资源; +- 运行期间输出模式、高速点绑定和定时器资源保持锁定。 + +CW/CCW模式下,正向只允许CW端输出脉冲,反向只允许CCW端输出脉冲;另一端和停止 +状态均保持无效电平,任何时刻禁止CW、CCW同时输出。 + +- **FR-PUL-20:** PLSR任务正常完成、STOP停止或ERROR退出后必须释放高速输出资源。 +- **FR-PUL-21:** CW/CCW必须遵守上述互斥输出和停止安全电平规则。 +- **FR-PUL-22:** 单段脉冲数量为0时跳过当前段,不输出脉冲并进入下一段;若为最后一段则完成任务。 + +AB模式的段脉冲数量按完整正交周期累计。每完成`00→相邻相位→相邻相位→相邻相位→00` +的一轮四相位状态转换,段剩余脉冲数减1;四次相位跳变不得分别扣减脉冲数量。正反方向 +通过相位先后顺序区分。 最小有效脉宽、输出极性及最高可靠频率还应满足 PLC 输出电路和伺服驱动器 的电气要求。100 kHz 是 V1.0 建议保证值,更高频率需通过硬件测试后开放。 +当段目标频率为0时: + +使用当前 S2 默认速度。 + +如果: + + 默认速度 <= 0 + +则: + +- 禁止启动; +- 返回 DEFAULT_SPEED_INVALID。 + ### 2.3 定位功能 #### 2.3.1 相对定位 @@ -171,7 +246,7 @@ Q2/PF7/TIM11_CH1、Q3/PF9/TIM14_CH1,仍应通过上板波形测试确认。 #### 2.3.3 位置与累计计数 -系统应维护以下 64 位数据: +系统内部应维护以下64位增强数据: - 当前逻辑位置。 - 本次任务累计脉冲数。 @@ -179,12 +254,17 @@ Q2/PF7/TIM11_CH1、Q3/PF9/TIM14_CH1,仍应通过上板波形测试确认。 上位机应能够读取并清零累计数据。运行期间禁止清零或设置当前位置。 +信捷兼容的固定累计状态`HSD0~15`仍按每个值两个16位寄存器组成32位数据;内部64位 +累计不得改变该固定地址布局。将内部值发布到信捷兼容状态前必须进行范围检查,超出32位 +范围时报告累计溢出,不得静默截断。 + ### 2.4 S0、S1、S2、D 功能模型 -项目采用与信捷 PLSR 相似的逻辑模型,但不要求使用相同的物理寄存器地址。 +项目采用信捷PLSR的S0、S1、S2、D逻辑模型。Y0~Y3固定配置和状态地址必须按 +[PLSR地址映射](./PLSR地址映射.md)一比一对应;S0、S1保持动态首地址语义。 | 参数 | 功能 | 主要内容 | -|---|---|---| +| --- | --- | --- | | S0 | 路径数据块 | 总段数、每段频率、脉冲数、等待及跳转 | | S1 | 用户执行参数 | 仅包含相对/绝对模式和起始执行段;异步调用属于指令接口而非S1字段 | | S2 | 运动参数套组 | K0~K4,包含默认频率、最高频率、起止频率、加减速、曲线、补偿、FOLLOW和刷新周期 | @@ -196,11 +276,13 @@ Q2/PF7/TIM11_CH1、Q3/PF9/TIM14_CH1,仍应通过上板波形测试确认。 PLSR_Start(S0路径, S1执行参数, S2参数套组, D输出轴) ``` -Modbus实现应为S0和S1提供动态数据池。调用方在池内选择不重叠的连续区域,并把 -S0、S1首地址传给目标轴;数据块不永久绑定到轴,多个轴允许只读共享同一数据块。 -COMMIT成功时为目标轴创建不可变运行快照,随后修改原动态数据块不得影响已经启动 -或已经提交的轴任务。除S0和S1数据块首地址动态指定外,S2、D、公共参数、命令和 -运行状态均使用固定的Modbus保持寄存器地址。 +S0和S1由调用方在未占用数据区选择不重叠的连续首地址;数据块不永久绑定到轴,多个轴 +允许只读共享同一数据块。COMMIT成功时为目标轴创建不可变运行快照,随后修改原动态 +数据块不得影响已经启动或已经提交的轴任务。K0~K4固定配置和固定运行状态使用 +[PLSR地址映射](./PLSR地址映射.md)规定的信捷原地址;D只指定输出资源,不自拟固定参数地址。 + +**FR-CMD-04:** PLSR指令必须支持`S0、S1、S2、D`四个操作数语义,分别表示路径数据、 +用户执行参数、K0~K4系统运动参数组和输出资源配置。 每个输出轴必须提供第0~4套S2参数: @@ -220,8 +302,8 @@ COMMIT成功时为目标轴创建不可变运行快照,随后修改原动态 S2 的控制刷新周期只允许配置为 `1 ms` 或 `0.1 ms`。系统OS Tick保持1 ms; 0.1 ms运动控制刷新应由独立硬件定时器触发,不得通过提高全局OS Tick实现。 -运行中修改目标频率后, -系统应在当前 S2 所配置的刷新周期内开始应用新目标;该指标表示调频响应时间, +运行中修改目标频率后, 系统应在当前 S2 +所配置的刷新周期内开始应用新目标;该指标表示调频响应时间, 不表示脉冲输出周期。 ### 2.5 单段与多段路径 @@ -236,11 +318,12 @@ S2 的控制刷新周期只允许配置为 `1 ms` 或 `0.1 ms`。系统OS Tick 下一段编号 ``` -S0应提供与信捷每段数据等效的字段和动态引用能力,但不要求复刻HD寄存器地址: +S0应提供与信捷每段数据一致的相对布局和动态引用能力;S0首地址由调用方动态指定: - 等待条件和等待参数均可表达常数或受支持的数据/位变量引用。 - 跳转目标可为常数或运行时数据变量引用,范围0~100。 -- Wait时间范围1~2,147,483,647 ms,配置0时按1 ms处理;计时从本段脉冲完成后开始。 +- Wait时间范围1~2,147,483,647 ms,配置0时按1 + ms处理;计时从本段脉冲完成后开始。 - Wait信号在本段完成后判断;若信号已有效则立即跳段,否则保持WAIT直至有效。 - ACT从本段开始输出时计时;时间到时放弃本段剩余脉冲并跳段;若脉冲先完成则等待ACT到时。 - EXT采用输入上升沿;运动中触发立即放弃剩余脉冲并跳段,脉冲先完成则等待后续EXT边沿。 @@ -250,7 +333,7 @@ S0应提供与信捷每段数据等效的字段和动态引用能力,但不要 多段路径应满足: | 编号 | 需求 | 优先级 | -|---|---|---| +| --- | --- | --- | | FR-SEG-01 | 每段可独立设置有符号脉冲数量 | 必须 | | FR-SEG-02 | 每段可独立设置目标频率 | 必须 | | FR-SEG-03 | 段起止频率由S2和相邻段目标频率自动推导,不要求每段显式配置 | 必须 | @@ -264,10 +347,33 @@ S0应提供与信捷每段数据等效的字段和动态引用能力,但不要 | FR-SEG-11 | 支持从指定段号开始;跳转到自身表示有意无限循环 | 必须 | | FR-SEG-12 | 每个实际完成或被条件切换的段均产生带轴号、段号和原因的段事件 | 必须 | | FR-SEG-13 | 最后一段使用等待类条件时保持WAIT/运行状态,直到条件成立或STOP,不得静默结束 | 必须 | +| FR-SEG-14 | 最大路径段数固定为100;超过限制时拒绝执行并返回SEGMENT_OVERFLOW | 必须 | 运行期间除当前目标频率外,其余路径参数修改不得影响当前任务。新参数应在 下一次成功提交并启动时生效。 +每段数据增加以下逻辑字段: + +| 字段 | 说明 | +| --- | --- | +| PulseCount | 有符号脉冲数量 | +| TargetFrequency | 目标频率 | +| WaitType | 等待类型 | +| WaitSourceType | 等待数据来源 | +| WaitAddress | 等待变量地址 | +| WaitParameter | 等待参数 | +| JumpType | 跳转来源 | +| JumpAddress | 跳转变量地址 | +| NextSegment | 下一段编号 | + +支持: + +- 常量等待; +- 输入等待; +- 数据变量等待; +- 动态跳转; +- 条件循环。 + ### 2.6 加减速与段内变频 系统应支持: @@ -305,10 +411,25 @@ S0应提供与信捷每段数据等效的字段和动态引用能力,但不要 ### 2.8 运行控制 +#### 2.8.1 PLSR启动触发规则 + +PLSR启动采用上升沿触发方式。 + +| 编号 | 需求 | 优先级 | +| --- | --- | --- | +| FR-CMD-01 | PLSR启动必须检测启动信号上升沿 | 必须 | +| FR-CMD-02 | 启动成功后,解除启动条件不会影响当前任务 | 必须 | +| FR-CMD-03 | 已经接受的任务必须锁存执行参数,不受原参数区修改影响 | 必须 | + +禁止: + +- 启动信号持续有效导致重复启动; +- 通信结束或调用返回导致运动停止。 + 系统至少应支持以下命令: | 命令 | 行为 | 优先级 | -|---|---|---| +| --- | --- | --- | | START | 校验并启动任务 | 必须 | | STOP_DECEL | 按减速曲线停止 | 必须 | | STOP_IMMEDIATE | 完成本次有效脉冲后关闭输出 | 必须 | @@ -325,13 +446,69 @@ S0应提供与信捷每段数据等效的字段和动态引用能力,但不要 命令边界行为: - IDLE 状态收到 START 时,校验通过后接受。 -- 运行、减速、等待或暂停状态再次收到 START 时拒绝执行,不重启任务,也不要求返回BUSY。 +- 运行、减速、等待或暂停状态再次收到 START + 时拒绝执行,不重启任务,也不要求返回BUSY。 - ERROR 状态收到 START 时,应拒绝执行,必须先清除错误。 - 相同命令序号重复到达时,应返回上次结果,不得重复执行运动。 - 多次 STOP_IMMEDIATE 应按幂等命令处理。 - CLEAR_POSITION、SET_POSITION 和 CLEAR_TOTAL 在运行期间应被拒绝。 - 发生数值溢出时应报告错误,不得依赖整数回绕。 +#### 2.8.2 参数修改生效规则 + +运行过程中参数修改规则: + +| 参数 | 运行中修改 | +| --- | --- | +| 目标频率 | 允许,立即生效 | +| STOP命令 | 允许 | +| PAUSE命令 | 允许 | +| 方向 | 禁止 | +| 脉冲数量 | 禁止 | +| 路径段数据 | 禁止 | +| 输出模式 | 禁止 | +| 输出点配置 | 禁止 | +| 加减速参数 | 下一次启动生效 | + +启动时必须生成不可变运行快照。 + +**FR-PUL-23:** 运行过程中禁止直接修改方向;必须终止当前任务后重新提交并启动。 + +#### 2.8.3 PAUSE、RESUME、STOP语义 + +##### PAUSE + +暂停要求: + +1. 按当前减速曲线降低速度; +2. 输出频率降为0; +3. 保存当前段号; +4. 保存剩余脉冲数量; +5. 等待RESUME。 + +##### RESUME + +恢复: + +- 从暂停位置继续执行; +- 不重新加载路径; +- 不重新计算已完成段。 + +##### STOP_DECEL + +减速停止: + +- 按当前减速曲线停止; +- 当前任务结束。 + +##### STOP_IMMEDIATE + +立即停止: + +- 完成本次有效脉冲输出后关闭; +- 锁存停止原因; +- 不自动恢复。 + ### 2.9 状态机与状态监控 PLSR 至少应包含以下状态: @@ -364,7 +541,29 @@ ERROR 错误 - 当前段已发送脉冲数,以及最近一次段事件的轴号、段号和结束原因。 绝对模式目标等于当前累计位置时不得输出脉冲;完成状态不得依赖必须出现一次 -“运行标志下降沿”,应直接返回零位移完成结果。 +"运行标志下降沿",应直接返回零位移完成结果。 + +增加 PLC 用户可观察状态: + +| 状态 | 说明 | +| --- | --- | +| BUSY | 当前轴存在已接受但尚未终止的任务,包括运动、WAIT和PAUSED | +| PULSE_ACTIVE | 当前物理脉冲正在输出;WAIT和PAUSED期间为0 | +| DONE | 当前任务正常完成并锁存 | +| WAIT | 当前任务正在等待段条件 | +| ERROR | 当前任务异常结束并锁存错误 | + +#### 2.9.1 DONE定义 + +采用方案A: + +- 运动正常完成后 DONE 置1; +- DONE保持有效; +- 下一次 START 成功接受后清零; +- DONE 不依赖 BUSY 下降沿。 +- STOP_DECEL、STOP_IMMEDIATE和ERROR结束不得置DONE。 + +**FR-STA-01:** DONE只表示正常完成,并按上述方案A产生、保持和清零。 ### 2.10 Modbus 通信 @@ -392,9 +591,9 @@ ERROR 错误 8. 协议应包含版本号,新增字段时不得改变既有寄存器语义。 PLSR内存地址、数据类型和固定占用规则见 -[PLSR地址映射](./PLSR地址映射.md);Modbus报文、访问权限和提交规则另见 -[PLSR Modbus通信协议](./PLSR_Modbus通信协议.md)。地址分配必须避开现有演示、 -Backup SRAM保持区。原Modbus通信历史功能不纳入PLSR版本,原历史寄存器区域释放给 +[PLSR地址映射](./PLSR地址映射.md)。地址分配必须避开现有演示、 +Backup +SRAM保持区。原Modbus通信历史功能不纳入PLSR版本,原历史寄存器区域释放给 S0/S1动态数据池使用。 ### 2.11 参数与累计数据保存 @@ -411,20 +610,22 @@ S0/S1动态数据池使用。 保存规则如下: 1. 固定配置参数使用内部 Flash 保存。 -2. 动态参数、累计位置和第0套动态S2参数使用有VBAT维持的 Backup SRAM 保存。 +2. 动态参数、累计位置和第0套动态S2参数使用有VBAT维持的 Backup SRAM + 保存。 3. 不得每个脉冲写 Flash。 4. 正常完成、正常停止、清零和设置位置后,应保存一致累计值。 5. SAVE_CONFIG 返回成功后,重新上电必须完整恢复固定配置。 6. 重新上电不得自动继续未完成运动。 -7. 异常掉电或异常复位后可恢复最近检查点供诊断,但必须清除 `position_valid`。 +7. 异常掉电或异常复位后可恢复最近检查点供诊断,但必须清除 + `position_valid`。 8. 重新清零、设置当前位置或完成回零前,禁止绝对定位。 9. 任意掉电瞬间零脉冲误差恢复需要额外硬件,Backup SRAM单独不能保证。 -测试报告应记录板卡是否安装 VBAT 以及最终采用的数据恢复等级。 -XDM-60T4-E 已确认安装有效 VBAT,Backup SRAM 可用于保持动态检查点; +测试报告应记录板卡是否安装 VBAT 以及最终采用的数据恢复等级。 XDM-60T4-E +已确认安装有效 VBAT,Backup SRAM 可用于保持动态检查点; 当前逻辑位置必须具有独立的 `position_valid` 标志。 -### 2.11.1 信捷等效脉冲公共参数 +#### 2.11.1 信捷等效脉冲公共参数 每个轴必须提供以下与PLSR直接相关的公共参数,字段地址严格采用 [PLSR地址映射](./PLSR地址映射.md)中的信捷原地址,不得采用自定义轴块偏移: @@ -463,11 +664,30 @@ XDM-60T4-E 已确认安装有效 VBAT,Backup SRAM 可用于保持动态检查 外部诊断和测试至少包括: - 使用示波器或逻辑分析仪测量输出频率。 + - 统计实际脉冲边沿数量。 + - 检查占空比和方向建立时间。 + - 检查梯形、S 形和正弦曲线。 + - 进行连续运行和频繁启停压力测试。 +| 诊断项 | 要求 | +| --- | --- | +| 软件累计脉冲 | 记录实际发送数量 | +| 硬件边沿计数 | 记录输出实际边沿 | +| 差值诊断 | 判断输出异常 | +| 频率记录 | 保存当前和最高频率 | +| 段事件记录 | 记录结束原因 | + +用于定位: + +- 参数错误; +- 状态机错误; +- 定时器异常; +- 输出资源异常。 + ### 2.13 安全与异常处理 - 上电、复位、HardFault 和看门狗复位时,脉冲输出必须保持无效。 @@ -476,7 +696,8 @@ XDM-60T4-E 已确认安装有效 VBAT,Backup SRAM 可用于保持动态检查 - 清除错误不得自动重新启动未完成运动。 - 配置限位输入后,限位有效时应禁止向该方向启动,但允许反向离开限位。 - 运动中限位触发默认执行减速停止。 -- V1.0 急停没有外部硬件切断回路;急停输入由软件立即禁止脉冲输出并锁存状态。 +- V1.0 + 急停没有外部硬件切断回路;急停输入由软件立即禁止脉冲输出并锁存状态。 - 软件急停不具备独立硬件安全回路的故障容错能力,不得宣称为安全认证急停。 至少应定义以下错误: @@ -500,12 +721,44 @@ Flash数据无效或保存失败 内部计数异常 ``` +运动控制事件优先级: + + 急停 + > + 硬限位 + > + STOP_IMMEDIATE + > + STOP_DECEL + > + PAUSE + > + 正常运行 + +要求: + +- 高优先级事件不能被低优先级命令覆盖; +- 错误清除后禁止自动恢复运动。 + +### 2.13.1 错误码补充 + +新增: + +| 错误码 | 说明 | +| --- | --- | +| DEFAULT_SPEED_INVALID | 默认速度非法 | +| SEGMENT_OVERFLOW | 路径段数超过100 | +| OUTPUT_MODE_INVALID | 输出模式非法 | +| RESOURCE_CONFLICT | 输出资源冲突 | +| PARAMETER_LOCKED | 运行参数禁止修改 | +| DONE_STATE_ERROR | 完成状态异常 | + ## 3 性能需求 ### 3.1 脉冲性能 | 编号 | 性能项 | 验收指标 | -|---|---|---| +| --- | --- | --- | | PR-01 | 保证频率范围 | 1 Hz~100 kHz | | PR-02 | 固定频率误差 | 使用可实现的最佳定时器分频值,记录目标值、实际值及误差,不设统一百分比限值 | | PR-03 | 正常完成脉冲误差 | 0 个脉冲 | @@ -520,7 +773,7 @@ Flash数据无效或保存失败 设计评审并记录原因: | 编号 | 性能项 | 初始指标 | -|---|---|---| +| --- | --- | --- | | PR-RT-01 | 控制更新周期 | S2 可配置为 1 ms 或 0.1 ms | | PR-RT-02 | 脉冲产生 | 由硬件定时器维持,不受 OS 调度影响 | | PR-RT-03 | 脉冲级中断最坏执行时间 | 实测并记录,不得导致脉冲数量错误 | @@ -532,7 +785,7 @@ Flash数据无效或保存失败 ### 3.3 可靠性 | 编号 | 性能项 | 验收指标 | -|---|---|---| +| --- | --- | --- | | PR-REL-01 | 连续运行 | 测试时长由测试方案确定,运行期间不得出现计数错误或任务失联 | | PR-REL-02 | 频繁启停 | 不产生额外脉冲和非法状态转换 | | PR-REL-03 | 异常参数 | 拒绝执行且不影响当前合法任务 | @@ -542,7 +795,8 @@ Flash数据无效或保存失败 ### 3.4 工程单位与换算边界 -- PLSR内核同时支持脉冲模式和当量模式,当量单位为1 μm、0.01 mm、0.1 mm或1 mm。 +- PLSR内核同时支持脉冲模式和当量模式,当量单位为1 μm、0.01 mm、0.1 + mm或1 mm。 - 当量模式根据每转指令脉冲数和每转移动量换算频率与脉冲数量。 - 换算层必须定义舍入方式并保存累计余数,连续多段运动不得持续产生单向舍入漂移。 - 上位机仍可提前换算,但不得成为使用工程单位的唯一途径。 @@ -553,7 +807,7 @@ Flash数据无效或保存失败 ### 4.1 验收要求 | 编号 | 验收项 | 合格标准 | -|---|---|---| +| --- | --- | --- | | AT-01 | 固定频率 | 1 Hz~100 kHz 使用最佳定时器分频值,并记录实际误差 | | AT-02 | 固定脉冲数 | 正常完成误差为 0 个 | | AT-03 | 正反转 | 方向电平和脉冲数量正确 | @@ -568,13 +822,27 @@ Flash数据无效或保存失败 | AT-12 | 重复命令 | 相同命令序号不产生重复运动 | | AT-13 | 掉电恢复 | 不自动运动,位置有效性符合恢复等级 | | AT-14 | 上电安全 | 上电和复位期间无意外脉冲 | -| AT-17 | 四轴独立运行 | 四轴可独立启动、停止、调频,状态和累计数据互不串扰 | -| AT-18 | AB 相输出 | 两个AB轴可独立运行;采用x4计数,完整周期4个计数边沿,方向、频率和数量正确 | +| AT-17 | 四轴独立运行 | 四轴同时以100 kHz运行时无丢脉冲、重复脉冲和异常周期,且状态和累计数据互不串扰 | +| AT-18 | AB 相输出 | 两个AB轴可独立运行;一个完整正交周期计1个指令脉冲,周期频率、相位方向和数量正确 | | AT-19 | S0等待与跳转 | 六种等待条件、动态参数来源、提前/延后触发和0/指定/自身跳转语义与信捷一致 | | AT-20 | 公共参数 | 单位换算、软限位、方向延时、齿隙补偿和FOLLOW参数均通过测试 | -| AT-21 | 零值及边界 | INT32最小值、频率0、脉冲数0和绝对零位移行为完成对标测试 | +| AT-21 | 零值及边界 | INT32最小值、频率0、脉冲数0跳段和绝对零位移行为符合本规格 | | AT-22 | 段事件和监控 | 每段事件、运行标志、当前段计数和累计计数可被稳定读取 | +新增测试: + +- FR-TEST-01四轴100 kHz并发测试; +- PLSR启动上升沿测试; +- BUSY/DONE状态测试; +- DONE保持及清零测试; +- PULSE/DIR测试; +- AB相测试; +- CW/CCW测试; +- PAUSE/RESUME测试; +- STOP优先级测试; +- 参数运行修改测试; +- 输出诊断一致性测试。 + 正式测试应使用开发板、逻辑分析仪和PC Modbus测试工具,并记录测试固件、 参数、接线、测量设备、原始波形和测试结论。 @@ -591,33 +859,19 @@ Flash数据无效或保存失败 - 上位机调试或测试工具。 - 示例程序和使用说明。 -### 4.3 开发周期 - -项目周期按任务书要求控制为 4 周: - -| 周期 | 主要工作 | 周交付物 | -|---|---|---| -| 第 1 周 | 确认定时器映射;完成单段频率、计数和方向 | 定时器驱动、单段演示、基础波形 | -| 第 2 周 | 完成定位、状态机、梯形曲线、调用模式和调频 | PLSR 核心模块、单轴测试记录 | -| 第 3 周 | 完成多段、衔接模式、等待跳转、S 形、Modbus 和保存 | 多段演示、协议草案、恢复测试 | -| 第 4 周 | 完成正弦曲线、诊断、压力测试、修复和文档 | 交付固件、设计书、测试报告 | - -如果硬件映射、伺服接口或验收条件在第 1 周结束前仍未确认,应从关键条件 -冻结之日重新评估四周周期。 - -### 4.4 后续版本或加分项 +### 4.3 后续版本或加分项 - 完整机械回零。 -### 4.5 不在当前范围内 +### 4.4 不在当前范围内 - 编码器闭环控制和位置误差修正。 - 多轴直线或圆弧插补。 - 电子凸轮和龙门同步。 - 完整复制信捷 PLSR、PLSF、DRVI、DRVA、ZRN、STOP 和 GOON 语法。 -- 兼容信捷专用软元件地址和 XDPPro 界面。 +- XDPPro参数配置界面兼容。 -### 4.6 实施验证事项 +### 4.5 实施验证事项 以下事项不改变V1.0需求范围,属于设计、实现和上板验收阶段需要验证的内容: @@ -626,7 +880,7 @@ Flash数据无效或保存失败 3. 两个 AB 轴的定时器/DMA同步方案及上板波形验证。 4. 四轴100 kHz并发及0.1 ms控制刷新时的CPU和中断资源实测结果。 5. Backup SRAM检查点的具体更新时机和诊断数据允许损失量。 -6. 信捷PLSR段脉冲数为0时的确切输出与终止语义。 +6. 段脉冲数为0时无脉冲输出、跳过当前段并正确进入下一段或完成任务。 ## 5 参考资料 @@ -634,7 +888,7 @@ Flash数据无效或保存失败 2. [实现 PLSR 指令](./实现PLSR指令.pdf) 3. [信捷 XD/XL 系列 PLC 定位控制手册](./信捷XD_XL系列PLC定位控制手册_PD02_20260510_V1.3.pdf) 4. [C 语言规范](../c语言规范.pdf) -5. 当前工程 `Core`、`Modbus`、`Middlewares`、`EWARM` 和 `HostComputer` 目录 +5. 当前工程 `Core`、`Modbus`、`Middlewares`、`EWARM` 和 `HostComputer` + 目录 6. [PLSR地址映射](./PLSR地址映射.md) -7. [PLSR Modbus通信协议](./PLSR_Modbus通信协议.md) 7. [PLSR信捷对标追踪矩阵](./PLSR信捷对标追踪矩阵.md) diff --git a/Document/PLSR_document/~$需求规格书.docx b/Document/PLSR_document/~$需求规格书.docx new file mode 100644 index 0000000000000000000000000000000000000000..992507346f4a35f3847f5b4fd187feddabc155eb GIT binary patch literal 162 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%0AVWDTr|tQ8eOavikXAcoS}Dc%P=Nv zOXXMLRY|WJe=QSOCu$>`*^2H|9BB;cw zUm{HYj2Am6`SC}-=CNBl5x}mD{JKdD0=)wN7M^qTc;IVnch3#+BRn^gIr{)BPXBN> zEigvl%bl>tbr!E5OgEWu6k1hsHu%vMS6%s(wq3E!%~8SkgoGUw8OS`+dB<~0+N$hD z5i@o~bF3Ry*D7x_r1kmoed(Ht%GAi3x7*uIbx{_b_CR}g=*eK0Cx5MIDRqKjH}lRX zACc{jM{C2Mi(4Y4ctvxD9a7Xo6-|V8VabU`I%zX2FvpQxPnEO?xP-p|Z8j=|e@R*+ zK2cMBY-Zo8-d;@n9t)*DE$t#5yRLv^-$1~Hp@;8tb+n+`)4nXz842=?O6^AN*RU@a z4Anl;;s8=tj@w-Cc=gAiGXwW-k&$ArP1ZX3|KTJ@^40aBUgZ5jrp1WGwgI7-PQq8@ zd1E>mhEA`*i8@j07h6p#RIeT#QEGP!>E$i<-CtgB)GVa$_07z27>rekGUqYxF6tMe zlS55d6R#QHP=(;FlbIQvGKeUuKSXp^Q<Ph*CzkVB`+(^n1K5a>Zo7VsetaA`%{&vy+LrFifD(|kf$S3+hpGH%b2zy5I9~8LE;PR)Hho12T${q~g z?Brj^AmGydd#;!@UxQOVP9M_SPjNS5~nnd1CXMRA^h-FpaFMiNGB_jmyHNb`Xa2mu3#& z{4%f!{>CSB>E(AGKVkQI(t#AiHBc{UBEW67PF0pP^N9$3qWPO7saKz>dU*zP@^;GO z4MfK5OAX=!M~W`88y|bPbsUT3^W=?*l6oA@oy_$N1k;tXIh594o_>Ef$xxi*JxP}j z=eR@S6W+};%7aA2?Mi7gado)3ljvJOY>9NGFGrEiV#FXap5Y4a_e z;jyp6-kgMfJs$pMhui@KXBjkc^e%aVM9UmU1*(rT27c6E&RPTk_AqiN8?sV&W9c+>jm!=?Du6D5~1817$>nV91yS=d^K{uoJ4@GE4>PJ%O7Vkb~{sZy;}3XFDaI$CW}mNx^sQbPfd%>^3_@wV>0ufJx^DU zXFQoI_k5a`a#O$vEzZCG-TQp)XbS(AbZcOkOmJH3xfg!LHS9a`Y};Pc=#u6XMWMF{ z1xN<;n9&YXMA6rf)TlS^mDq83mXT zqhMB4yuLSJ$aVt!M1U|F*a-MN*Bq^`tMw?U)3NG%{^2i68cY~QY(^y z80~Rqlbqt$~Kr0^_o!W z?1>r;=4btdswe3G-54k|07auqhvE+rBJO&KDmP(Al_9A`{*5d9UBDy)^dFQNsvwv_ z;@=pp-vtnl{wwe|V(W(#>wjTPzvPM{QRomJ)?Z-}5Qq>R`E7AaMa_mN63Z2!AfbG$ z|DACCYWS@XbvKlU_3!%+;pE8^PTRi^0R3}RekeEV|9;d64XA&K6Sg2Fs869vbT=^| zkb{T)-<=oxInYss!SqJ|z6O4md|v*$=f7PMKPG_xj2coxsvii%Kv*qFK_JYlAAA1? D4j!2_ delta 24481 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