Преглед на файлове

完成了初版需求规格书与方案书

deepseek
ywh преди 1 месец
родител
ревизия
e35595aae1
променени са 31 файла, в които са добавени 750 реда и са изтрити 149 реда
  1. +0
    -2
      Core/Src/main.c
  2. +19
    -0
      Document/PLSR_document/PLSR方案设计书_V1.0.md
  3. Двоични данни
      Document/PLSR_document/图片/PLSR单轴完整执行流程图.png
  4. Двоични данни
      Document/PLSR_document/图片/PLSR单轴状态机与命令优先级图.png
  5. +216
    -0
      Document/PLSR_document/图片/PLSR单轴状态机与命令优先级图.svg
  6. Двоични данни
      Document/PLSR_document/图片/PLSR单轴状态机图.png
  7. +170
    -0
      Document/PLSR_document/图片/PLSR单轴状态机图.svg
  8. Двоични данни
      Document/PLSR_document/图片/PLSR数据流关系图.png
  9. +179
    -0
      Document/PLSR_document/图片/PLSR数据流关系图.svg
  10. +0
    -0
      Document/PLSR_document/图片/PLSR系统结构图.png
  11. +0
    -0
      Document/PLSR_document/图片/PLSR系统结构图.svg
  12. Двоични данни
      Document/PLSR_document/图片/PLSR高速脉冲与硬件计数架构图.png
  13. +166
    -0
      Document/PLSR_document/图片/PLSR高速脉冲与硬件计数架构图.svg
  14. +0
    -0
      Document/PLSR_document/图片/任务要求.png
  15. Двоични данни
      Document/PLSR_document/框图/PLSR运动控制流程图 - 副本.vsdx
  16. Двоични данни
      Document/PLSR_document/框图/PLSR运动控制流程图 - 副本_修改前备份.vsdx
  17. Двоични данни
      Document/PLSR_document/框图/PLSR运动控制流程图.vsdx
  18. Двоични данни
      Document/PLSR_document/框图/PLSR运动控制流程图_完整版.vsdx
  19. Двоични данни
      Document/PLSR_document/框图/PLSR运动控制流程图_完整预览.png
  20. Двоични данни
      Document/PLSR_document/框图/PLSR运动控制流程图_当前预览.png
  21. Двоични данни
      Document/PLSR_document/框图/PLSR高速脉冲与硬件计数架构图.vsdx
  22. Двоични данни
      Document/PLSR_document/框图/~$$PLSR运动控制流程图 - 副本.~vsdx
  23. Двоични данни
      Document/PLSR_document/框图/状态机图解.vsdx
  24. Двоични данни
      Document/PLSR_document/虞文昊_PLSR_2026.8.6.zip
  25. Двоични данни
      Document/PLSR_document/虞文昊_PLSR_2026.8.6/设计方案书.docx
  26. Двоични данни
      Document/PLSR_document/虞文昊_PLSR_2026.8.6/需求规格书.docx
  27. Двоични данни
      Document/PLSR_document/设计方案书.docx
  28. Двоични данни
      Document/PLSR_document/设计方案书2.docx
  29. Двоични данни
      Document/PLSR_document/需求规格书.docx
  30. +0
    -12
      Modbus/Inc/modbus_rtu_slave.h
  31. +0
    -135
      Modbus/Src/modbus_rtu_slave.c

+ 0
- 2
Core/Src/main.c Целия файл

@@ -100,8 +100,6 @@ static void AppTaskStart(void *pArg)
// (void)ModbusSlaveSetHoldingRegister( // 非法数据值计数
// D6, (uint16_t)ModbusSlaveStatistics.illegalValueCount);

// HistorySaveToRegisters();

/*
* 每1ms轮询一次,
*/


+ 19
- 0
Document/PLSR_document/PLSR方案设计书_V1.0.md Целия файл

@@ -270,6 +270,10 @@ void Plsr_IsrPost(uint8_t axis, uint32_t event_mask);

#### 3.1.3 流程图

![PLSR单轴完整执行流程图](./PLSR单轴完整执行流程图.png)

**图 3-1 PLSR单轴完整执行流程图**

```text
系统启动
-> 输出置安全状态
@@ -476,6 +480,10 @@ void PlsrProfile_SetTarget(PlsrProfile *profile, uint32_t target_hz);

高速输出模块使用硬件定时器维持脉冲边沿,OS不参与逐脉冲翻转。

![PLSR高速脉冲与硬件计数架构图](./PLSR高速脉冲与硬件计数架构图.svg)

**图 3-2 PLSR高速脉冲与硬件计数架构图**

| 逻辑点 | MCU引脚 | 定时器通道 | 定时器时钟 |
| --- | --- | --- | ---: |
| Q0/Y0 | PF6 | TIM10_CH1 | 168 MHz |
@@ -655,6 +663,10 @@ UNINITIALIZED、IDLE、ACCEL、RUN、DECEL、WAIT、PAUSED、
COMPLETED、STOPPED、ERROR
```

![PLSR单轴状态机与命令优先级图](./PLSR单轴状态机与命令优先级图.svg)

**图 3-3 PLSR单轴状态机与命令优先级图**

主要合法转换如下:

| 当前状态 | 事件 | 下一状态 |
@@ -1128,6 +1140,13 @@ typedef struct {

#### 4.2.1 数据流关系

![PLSR数据流关系图](./PLSR数据流关系图.svg)

**图 4-1 PLSR数据流关系图**

图中蓝色表示配置和运动数据,橙色表示硬实时数据及中断事件,绿色表示持久化数据,紫色表示命令与
状态接口。为方便纯文本环境阅读,保留如下简化关系。

```text
S0/S1/S2/D逻辑软元件
|


Двоични данни
Document/PLSR_document/图片/PLSR单轴完整执行流程图.png Целия файл

Преди След
Ширина: 2400  |  Височина: 1950  |  Големина: 606 KiB

Двоични данни
Document/PLSR_document/图片/PLSR单轴状态机与命令优先级图.png Целия файл

Преди След
Ширина: 1800  |  Височина: 1100  |  Големина: 230 KiB

+ 216
- 0
Document/PLSR_document/图片/PLSR单轴状态机与命令优先级图.svg Целия файл

@@ -0,0 +1,216 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1800" height="1100" viewBox="0 0 1800 1100" role="img" aria-labelledby="title desc">
<title id="title">PLSR单轴状态机与命令优先级图</title>
<desc id="desc">展示单轴从初始化、空闲、运动、等待、暂停到正常完成、停止和错误的状态转换,以及软件急停到正常运行的命令事件优先级。</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#F8FBFF"/>
<stop offset="1" stop-color="#EEF3F9"/>
</linearGradient>
<filter id="shadow" x="-15%" y="-15%" width="130%" height="140%">
<feDropShadow dx="0" dy="5" stdDeviation="7" flood-color="#183A61" flood-opacity="0.14"/>
</filter>
<marker id="blueArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#3478B9"/>
</marker>
<marker id="orangeArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#D96F1E"/>
</marker>
<marker id="redArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#C64545"/>
</marker>
<marker id="greenArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#398760"/>
</marker>
<style>
.title { font: 700 34px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.subtitle { font: 400 16px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #5E7187; }
.layer { font: 700 21px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.state-title { font: 700 19px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.state-text { font: 400 14px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #485E75; }
.white-title { font: 700 19px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #FFFFFF; }
.white-text { font: 400 14px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #F4F8FD; }
.label { font: 600 13px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #405A74; }
.small { font: 400 13px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #5A6E83; }
.blue { fill: none; stroke: #3478B9; stroke-width: 3; marker-end: url(#blueArrow); }
.orange { fill: none; stroke: #D96F1E; stroke-width: 3; marker-end: url(#orangeArrow); }
.red { fill: none; stroke: #C64545; stroke-width: 3; marker-end: url(#redArrow); }
.green { fill: none; stroke: #398760; stroke-width: 3; marker-end: url(#greenArrow); }
.dash { stroke-dasharray: 8 7; }
</style>
</defs>

<rect width="1800" height="1100" fill="url(#bg)"/>
<text x="900" y="50" text-anchor="middle" class="title">PLSR 单轴状态机与命令优先级图</text>
<text x="900" y="78" text-anchor="middle" class="subtitle">每轴独立状态 · 唯一转换入口 · 高优先级事件不可被低优先级命令覆盖</text>

<!-- 状态机区域 -->
<g filter="url(#shadow)">
<rect x="65" y="105" width="1270" height="900" rx="22" fill="#FFFFFF" stroke="#A8C4E0" stroke-width="2"/>
</g>
<text x="100" y="143" class="layer">单轴状态转换</text>

<!-- 状态节点 -->
<g filter="url(#shadow)">
<rect x="115" y="180" width="240" height="95" rx="18" fill="#E9EEF4" stroke="#9AABBC" stroke-width="2"/>
<rect x="470" y="180" width="240" height="95" rx="18" fill="#EAF4FE" stroke="#78A8D6" stroke-width="2"/>
<rect x="205" y="385" width="240" height="105" rx="18" fill="#2F78B7"/>
<rect x="555" y="385" width="240" height="105" rx="18" fill="#2F78B7"/>
<rect x="905" y="385" width="240" height="105" rx="18" fill="#2F78B7"/>
<rect x="205" y="595" width="240" height="105" rx="18" fill="#FFF4E8" stroke="#DFA06D" stroke-width="2"/>
<rect x="555" y="595" width="240" height="105" rx="18" fill="#FFF4E8" stroke="#DFA06D" stroke-width="2"/>
<rect x="130" y="825" width="250" height="105" rx="18" fill="#EAF8F0" stroke="#73B18F" stroke-width="2"/>
<rect x="490" y="825" width="250" height="105" rx="18" fill="#F5F1EB" stroke="#B0A18C" stroke-width="2"/>
<rect x="850" y="825" width="250" height="105" rx="18" fill="#FDEDED" stroke="#D68181" stroke-width="2"/>
</g>

<text x="235" y="216" text-anchor="middle" class="state-title">UNINITIALIZED</text>
<text x="235" y="245" text-anchor="middle" class="state-text">输出安全 · 模块未就绪</text>

<text x="590" y="216" text-anchor="middle" class="state-title">IDLE</text>
<text x="590" y="245" text-anchor="middle" class="state-text">BUSY=0 · PULSE_ACTIVE=0</text>

<text x="325" y="424" text-anchor="middle" class="white-title">ACCEL</text>
<text x="325" y="453" text-anchor="middle" class="white-text">加速输出</text>
<text x="325" y="476" text-anchor="middle" class="white-text">BUSY=1 · PULSE_ACTIVE=1</text>

<text x="675" y="424" text-anchor="middle" class="white-title">RUN</text>
<text x="675" y="453" text-anchor="middle" class="white-text">目标频率运行/段内调频</text>
<text x="675" y="476" text-anchor="middle" class="white-text">BUSY=1 · PULSE_ACTIVE=1</text>

<text x="1025" y="424" text-anchor="middle" class="white-title">DECEL</text>
<text x="1025" y="453" text-anchor="middle" class="white-text">减速或反向前停车</text>
<text x="1025" y="476" text-anchor="middle" class="white-text">BUSY=1 · PULSE_ACTIVE=1</text>

<text x="325" y="635" text-anchor="middle" class="state-title">WAIT</text>
<text x="325" y="664" text-anchor="middle" class="state-text">等待时间/信号/EXT</text>
<text x="325" y="687" text-anchor="middle" class="state-text">BUSY=1 · PULSE_ACTIVE=0</text>

<text x="675" y="635" text-anchor="middle" class="state-title">PAUSED</text>
<text x="675" y="664" text-anchor="middle" class="state-text">保留快照、段号和剩余量</text>
<text x="675" y="687" text-anchor="middle" class="state-text">BUSY=1 · PULSE_ACTIVE=0</text>

<text x="255" y="864" text-anchor="middle" class="state-title">COMPLETED</text>
<text x="255" y="893" text-anchor="middle" class="state-text">正常结束 · DONE=1并锁存</text>
<text x="255" y="916" text-anchor="middle" class="state-text">BUSY=0 · PULSE_ACTIVE=0</text>

<text x="615" y="864" text-anchor="middle" class="state-title">STOPPED</text>
<text x="615" y="893" text-anchor="middle" class="state-text">命令/限位停止 · DONE=0</text>
<text x="615" y="916" text-anchor="middle" class="state-text">停止原因锁存</text>

<text x="975" y="864" text-anchor="middle" class="state-title">ERROR</text>
<text x="975" y="893" text-anchor="middle" class="state-text">不可恢复运行错误 · DONE=0</text>
<text x="975" y="916" text-anchor="middle" class="state-text">禁止新脉冲并锁存错误</text>

<!-- 主运行链:线条只穿过状态框之间的留白区 -->
<path d="M355 227 L462 227" class="blue"/>
<text x="408" y="215" text-anchor="middle" class="label">初始化成功</text>

<path d="M590 275 L590 320 L325 320 L325 377" class="blue"/>
<text x="455" y="309" text-anchor="middle" class="label">START成功并建立运行快照</text>

<path d="M445 437 L547 437" class="blue"/>
<text x="496" y="425" text-anchor="middle" class="label">达到运行频率</text>

<path d="M795 437 L897 437" class="blue"/>
<text x="846" y="425" text-anchor="middle" class="label">需减速或反向</text>

<path d="M1025 385 L1025 348 L675 348 L675 377" class="blue dash"/>
<text x="850" y="338" text-anchor="middle" class="label">下一同向段或继续运行</text>

<!-- WAIT:进入与退出使用状态框两侧的独立通道 -->
<path d="M555 465 L500 465 L500 647 L453 647" class="orange"/>
<text x="492" y="526" text-anchor="end" class="label">段完成且条件未满足</text>

<path d="M325 595 L325 498" class="orange dash"/>
<text x="310" y="554" text-anchor="end" class="label">条件满足,进入下一段</text>

<!-- PAUSE / RESUME -->
<path d="M1025 490 L1025 550 L675 550 L675 587" class="orange"/>
<text x="850" y="539" text-anchor="middle" class="label">PAUSE:减速到0</text>

<path d="M555 647 L520 647 L520 565 L420 565 L420 498" class="orange dash"/>
<text x="472" y="581" text-anchor="middle" class="label">RESUME</text>

<!-- 正常完成 -->
<path d="M325 700 L325 770 L255 770 L255 817" class="green"/>
<text x="255" y="758" text-anchor="middle" class="label">等待后正常结束</text>

<path d="M605 490 L605 520 L540 520 L540 720 L180 720 L180 817" class="green"/>
<text x="190" y="710" class="label">最后一段正常完成</text>

<!-- 零位移可直接正常完成,不要求先进入脉冲活动态 -->
<path d="M520 275 L520 290 L72 290 L72 790 L180 790 L180 817" class="green dash"/>
<text x="82" y="282" class="label">零位移/零脉冲末段</text>

<!-- 抢占与异常采用汇总入口,避免把每个活动态重复连线 -->
<rect x="410" y="752" width="410" height="54" rx="12" fill="#FFF3E7" stroke="#D8843F"/>
<text x="615" y="775" text-anchor="middle" class="label">任意BUSY状态:STOP_DECEL减速到0</text>
<text x="615" y="797" text-anchor="middle" class="label">STOP_IMMEDIATE完成当前有效脉冲后关闭</text>
<path d="M615 806 L615 817" class="orange"/>

<rect x="850" y="752" width="390" height="54" rx="12" fill="#FDEDEE" stroke="#C64545"/>
<text x="1045" y="775" text-anchor="middle" class="label">任意状态:初始化、参数、定时器</text>
<text x="1045" y="797" text-anchor="middle" class="label">或硬件计数发生不可恢复错误</text>
<path d="M975 806 L975 817" class="red"/>

<path d="M1100 877 L1280 877 L1280 145 L710 145 L710 227" class="red dash"/>
<text x="995" y="134" text-anchor="middle" class="label">RESET_ERROR成功:仅回IDLE,不自动续跑</text>

<!-- 终态后的下一次启动规则用注记表达,避免回路线穿越状态图 -->
<rect x="130" y="955" width="610" height="43" rx="11" fill="#EEF5FC" stroke="#7FA9CF"/>
<text x="435" y="982" text-anchor="middle" class="label">COMPLETED / STOPPED收到合法START:清DONE,建立新快照后重新运行</text>

<!-- 优先级区域 -->
<g filter="url(#shadow)">
<rect x="1370" y="105" width="365" height="900" rx="22" fill="#FFFFFF" stroke="#D4B0A0" stroke-width="2"/>
</g>
<text x="1552" y="143" text-anchor="middle" class="layer">命令与事件优先级</text>
<text x="1552" y="174" text-anchor="middle" class="small">越靠上优先级越高</text>

<rect x="1415" y="215" width="275" height="80" rx="15" fill="#A92F38"/>
<text x="1552" y="248" text-anchor="middle" class="white-title">1 软件急停</text>
<text x="1552" y="274" text-anchor="middle" class="white-text">立即禁止新脉冲并锁存</text>

<rect x="1415" y="315" width="275" height="80" rx="15" fill="#C3463F"/>
<text x="1552" y="348" text-anchor="middle" class="white-title">2 硬限位</text>
<text x="1552" y="374" text-anchor="middle" class="white-text">禁止越界方向,默认减速停止</text>

<rect x="1415" y="415" width="275" height="80" rx="15" fill="#D6653F"/>
<text x="1552" y="448" text-anchor="middle" class="white-title">3 STOP_IMMEDIATE</text>
<text x="1552" y="474" text-anchor="middle" class="white-text">完成当前有效脉冲后关闭</text>

<rect x="1415" y="515" width="275" height="80" rx="15" fill="#E28B45"/>
<text x="1552" y="548" text-anchor="middle" class="white-title">4 STOP_DECEL</text>
<text x="1552" y="574" text-anchor="middle" class="white-text">按当前减速曲线停止</text>

<rect x="1415" y="615" width="275" height="80" rx="15" fill="#E5AE57"/>
<text x="1552" y="648" text-anchor="middle" class="white-title">5 PAUSE</text>
<text x="1552" y="674" text-anchor="middle" class="white-text">减速到0并保留运行快照</text>

<rect x="1415" y="715" width="275" height="80" rx="15" fill="#6E9EC8"/>
<text x="1552" y="748" text-anchor="middle" class="white-title">6 正常运行事件</text>
<text x="1552" y="774" text-anchor="middle" class="white-text">段完成、等待、跳转、调频</text>

<path d="M1552 295 L1552 307" class="red"/>
<path d="M1552 395 L1552 407" class="red"/>
<path d="M1552 495 L1552 507" class="orange"/>
<path d="M1552 595 L1552 607" class="orange"/>
<path d="M1552 695 L1552 707" class="blue"/>

<rect x="1415" y="835" width="275" height="115" rx="15" fill="#F5F7FA" stroke="#B7C2CE"/>
<text x="1552" y="866" text-anchor="middle" class="state-title">锁存规则</text>
<text x="1552" y="895" text-anchor="middle" class="state-text">高优先级原因一旦锁存</text>
<text x="1552" y="919" text-anchor="middle" class="state-text">低优先级命令不得覆盖</text>
<text x="1552" y="943" text-anchor="middle" class="state-text">重复立即停止按幂等处理</text>

<!-- 图例 -->
<circle cx="95" cy="1065" r="6" fill="#2F78B7"/>
<text x="110" y="1070" class="small">脉冲活动状态</text>
<circle cx="260" cy="1065" r="6" fill="#E0A064"/>
<text x="275" y="1070" class="small">BUSY但不发脉冲</text>
<circle cx="455" cy="1065" r="6" fill="#398760"/>
<text x="470" y="1070" class="small">正常完成</text>
<circle cx="585" cy="1065" r="6" fill="#C64545"/>
<text x="600" y="1070" class="small">异常/抢占转换</text>
</svg>

Двоични данни
Document/PLSR_document/图片/PLSR单轴状态机图.png Целия файл

Преди След
Ширина: 2000  |  Височина: 1250  |  Големина: 223 KiB

+ 170
- 0
Document/PLSR_document/图片/PLSR单轴状态机图.svg Целия файл

@@ -0,0 +1,170 @@
<svg xmlns="http://www.w3.org/2000/svg" width="2000" height="1250" viewBox="0 0 2000 1250">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="150%">
<feDropShadow dx="0" dy="7" stdDeviation="7" flood-color="#24445F" flood-opacity="0.16"/>
</filter>
<marker id="arrowBlue" markerWidth="13" markerHeight="13" refX="11" refY="6.5" orient="auto">
<path d="M0,0 L13,6.5 L0,13 Z" fill="#2F78B7"/>
</marker>
<marker id="arrowOrange" markerWidth="13" markerHeight="13" refX="11" refY="6.5" orient="auto">
<path d="M0,0 L13,6.5 L0,13 Z" fill="#D97925"/>
</marker>
<marker id="arrowGreen" markerWidth="13" markerHeight="13" refX="11" refY="6.5" orient="auto">
<path d="M0,0 L13,6.5 L0,13 Z" fill="#31845E"/>
</marker>
<marker id="arrowRed" markerWidth="13" markerHeight="13" refX="11" refY="6.5" orient="auto">
<path d="M0,0 L13,6.5 L0,13 Z" fill="#C64545"/>
</marker>
<style>
text { font-family: "Microsoft YaHei", "Noto Sans CJK SC", Arial, sans-serif; fill: #123A60; }
.title { font-size: 42px; font-weight: 700; fill: #123A60; }
.subtitle { font-size: 20px; fill: #61778C; }
.lane { font-size: 20px; font-weight: 700; fill: #50708D; letter-spacing: 1px; }
.state-title { font-size: 29px; font-weight: 700; }
.state-desc { font-size: 19px; }
.flag { font-size: 17px; fill: #345B7D; }
.label { font-size: 18px; font-weight: 600; paint-order: stroke; stroke: #FFFFFF; stroke-width: 7px; stroke-linejoin: round; }
.note-title { font-size: 18px; font-weight: 700; }
.note-text { font-size: 17px; }
.blue { fill: none; stroke: #2F78B7; stroke-width: 4; marker-end: url(#arrowBlue); }
.orange { fill: none; stroke: #D97925; stroke-width: 4; marker-end: url(#arrowOrange); }
.green { fill: none; stroke: #31845E; stroke-width: 4; marker-end: url(#arrowGreen); }
.red { fill: none; stroke: #C64545; stroke-width: 4; marker-end: url(#arrowRed); }
.dash { stroke-dasharray: 11 9; }
</style>
</defs>

<rect width="2000" height="1250" fill="#F4F8FC"/>
<text x="1000" y="62" text-anchor="middle" class="title">PLSR 单轴状态机</text>
<text x="1000" y="94" text-anchor="middle" class="subtitle">每轴独立运行 · 唯一状态入口 · 硬件脉冲发生与状态控制解耦</text>

<rect x="65" y="125" width="1870" height="1050" rx="25" fill="#FFFFFF" stroke="#A7C8E5" stroke-width="2.5" filter="url(#shadow)"/>

<!-- 分层背景 -->
<rect x="95" y="155" width="1810" height="185" rx="18" fill="#F4F7FA"/>
<rect x="95" y="365" width="1810" height="245" rx="18" fill="#F0F6FC"/>
<rect x="95" y="635" width="1810" height="210" rx="18" fill="#FFF8F0"/>
<rect x="95" y="870" width="1810" height="245" rx="18" fill="#F6FAF7"/>
<text x="115" y="184" class="lane">准备状态</text>
<text x="115" y="394" class="lane">脉冲活动状态</text>
<text x="115" y="664" class="lane">保持状态</text>
<text x="115" y="899" class="lane">终止状态</text>

<!-- 准备状态 -->
<g filter="url(#shadow)">
<rect x="190" y="205" width="330" height="105" rx="20" fill="#E8EDF3" stroke="#93A9BD" stroke-width="2.5"/>
<rect x="700" y="205" width="330" height="105" rx="20" fill="#EAF4FD" stroke="#66A4DC" stroke-width="2.5"/>
</g>
<text x="355" y="246" text-anchor="middle" class="state-title">UNINITIALIZED</text>
<text x="355" y="278" text-anchor="middle" class="state-desc">输出安全,模块尚未就绪</text>
<text x="865" y="246" text-anchor="middle" class="state-title">IDLE</text>
<text x="865" y="278" text-anchor="middle" class="flag">BUSY=0 · PULSE_ACTIVE=0</text>

<!-- 活动状态 -->
<g filter="url(#shadow)">
<rect x="190" y="430" width="330" height="120" rx="20" fill="#347FBD"/>
<rect x="700" y="430" width="330" height="120" rx="20" fill="#2876B5"/>
<rect x="1210" y="430" width="330" height="120" rx="20" fill="#347FBD"/>
</g>
<text x="355" y="474" text-anchor="middle" class="state-title" fill="#FFFFFF" style="fill:#FFFFFF">ACCEL</text>
<text x="355" y="504" text-anchor="middle" class="state-desc" fill="#FFFFFF" style="fill:#FFFFFF">按加速参数提升频率</text>
<text x="355" y="532" text-anchor="middle" class="flag" fill="#FFFFFF" style="fill:#FFFFFF">BUSY=1 · PULSE_ACTIVE=1</text>
<text x="865" y="474" text-anchor="middle" class="state-title" fill="#FFFFFF" style="fill:#FFFFFF">RUN</text>
<text x="865" y="504" text-anchor="middle" class="state-desc" fill="#FFFFFF" style="fill:#FFFFFF">恒频或段内动态调频</text>
<text x="865" y="532" text-anchor="middle" class="flag" fill="#FFFFFF" style="fill:#FFFFFF">BUSY=1 · PULSE_ACTIVE=1</text>
<text x="1375" y="474" text-anchor="middle" class="state-title" fill="#FFFFFF" style="fill:#FFFFFF">DECEL</text>
<text x="1375" y="504" text-anchor="middle" class="state-desc" fill="#FFFFFF" style="fill:#FFFFFF">减速、反向或受控停止</text>
<text x="1375" y="532" text-anchor="middle" class="flag" fill="#FFFFFF" style="fill:#FFFFFF">BUSY=1 · PULSE_ACTIVE=1</text>

<!-- 保持状态 -->
<g filter="url(#shadow)">
<rect x="190" y="690" width="330" height="115" rx="20" fill="#FFF3E7" stroke="#EA9B55" stroke-width="2.5"/>
<rect x="700" y="690" width="330" height="115" rx="20" fill="#FFF3E7" stroke="#EA9B55" stroke-width="2.5"/>
</g>
<text x="355" y="734" text-anchor="middle" class="state-title">WAIT</text>
<text x="355" y="765" text-anchor="middle" class="state-desc">等待时间、信号或EXT条件</text>
<text x="355" y="791" text-anchor="middle" class="flag">BUSY=1 · PULSE_ACTIVE=0</text>
<text x="865" y="734" text-anchor="middle" class="state-title">PAUSED</text>
<text x="865" y="765" text-anchor="middle" class="state-desc">保留快照、段号与剩余量</text>
<text x="865" y="791" text-anchor="middle" class="flag">BUSY=1 · PULSE_ACTIVE=0</text>

<!-- 终止状态 -->
<g filter="url(#shadow)">
<rect x="175" y="950" width="350" height="120" rx="20" fill="#ECF8F1" stroke="#56A67D" stroke-width="2.5"/>
<rect x="690" y="950" width="350" height="120" rx="20" fill="#F5F2ED" stroke="#AF9A7C" stroke-width="2.5"/>
<rect x="1205" y="950" width="350" height="120" rx="20" fill="#FDEEEF" stroke="#E06469" stroke-width="2.5"/>
</g>
<text x="350" y="994" text-anchor="middle" class="state-title">COMPLETED</text>
<text x="350" y="1025" text-anchor="middle" class="state-desc">正常结束,DONE=1并锁存</text>
<text x="350" y="1053" text-anchor="middle" class="flag">BUSY=0 · PULSE_ACTIVE=0</text>
<text x="865" y="994" text-anchor="middle" class="state-title">STOPPED</text>
<text x="865" y="1025" text-anchor="middle" class="state-desc">命令或限位停止,DONE=0</text>
<text x="865" y="1053" text-anchor="middle" class="flag">停止原因锁存</text>
<text x="1380" y="994" text-anchor="middle" class="state-title">ERROR</text>
<text x="1380" y="1025" text-anchor="middle" class="state-desc">不可恢复运行错误,DONE=0</text>
<text x="1380" y="1053" text-anchor="middle" class="flag">禁止新脉冲并锁存错误</text>

<!-- 主运行链 -->
<path d="M520 257 L692 257" class="blue"/>
<text x="606" y="244" text-anchor="middle" class="label">初始化成功</text>

<path d="M865 310 L865 355 L355 355 L355 422" class="blue"/>
<text x="610" y="345" text-anchor="middle" class="label">合法START:校验并建立快照</text>

<path d="M520 490 L692 490" class="blue"/>
<text x="606" y="478" text-anchor="middle" class="label">达到目标频率</text>

<path d="M1030 490 L1202 490" class="blue"/>
<text x="1116" y="478" text-anchor="middle" class="label">需要减速或反向</text>

<path d="M1375 430 L1375 405 L865 405 L865 422" class="blue dash"/>
<text x="1120" y="395" text-anchor="middle" class="label">下一同向段或继续运行</text>

<!-- WAIT -->
<path d="M700 500 L610 500 L610 748 L528 748" class="orange"/>
<text x="625" y="675" class="label">段完成且等待条件未满足</text>
<path d="M355 690 L355 558" class="orange dash"/>
<text x="340" y="632" text-anchor="end" class="label">条件满足,进入下一段</text>

<!-- PAUSE -->
<path d="M1375 550 L1375 640 L865 640 L865 682" class="orange"/>
<text x="1120" y="629" text-anchor="middle" class="label">PAUSE减速到0</text>
<path d="M700 748 L620 748 L620 615 L470 615 L470 558" class="orange dash"/>
<text x="635" y="735" text-anchor="middle" class="label">RESUME</text>

<!-- 正常完成 -->
<path d="M355 805 L355 942" class="green"/>
<text x="340" y="880" text-anchor="end" class="label">等待后正常结束</text>
<path d="M700 535 L650 535 L650 830 L350 830 L350 942" class="green"/>
<text x="500" y="820" text-anchor="middle" class="label">最后一段正常完成</text>

<!-- 停止汇总入口 -->
<rect x="650" y="850" width="430" height="68" rx="14" fill="#FFF3E7" stroke="#D97925" stroke-width="2"/>
<text x="865" y="877" text-anchor="middle" class="note-title">停止入口</text>
<text x="865" y="902" text-anchor="middle" class="note-text">STOP_DECEL到0 / STOP_IMMEDIATE收尾</text>
<path d="M865 918 L865 942" class="orange"/>

<!-- 错误与复位 -->
<rect x="1210" y="850" width="340" height="68" rx="14" fill="#FDEEEF" stroke="#C64545" stroke-width="2"/>
<text x="1380" y="877" text-anchor="middle" class="note-title">任意状态不可恢复错误</text>
<text x="1380" y="902" text-anchor="middle" class="note-text">参数、定时器、计数或非法转换</text>
<path d="M1380 918 L1380 942" class="red"/>
<path d="M1555 1010 L1850 1010 L1850 170 L1030 170 L1030 245" class="red dash"/>
<text x="1450" y="158" text-anchor="middle" class="label">RESET_ERROR成功:仅回IDLE,不自动续跑</text>

<!-- 说明与图例 -->
<rect x="1580" y="205" width="285" height="335" rx="18" fill="#F8FAFC" stroke="#B9C8D5" stroke-width="2"/>
<text x="1722" y="242" text-anchor="middle" class="state-title" style="font-size:23px">转换原则</text>
<text x="1605" y="282" class="note-text">1. 每个周期只执行一次转换</text>
<text x="1605" y="320" class="note-text">2. 高优先级事件先于普通事件</text>
<text x="1605" y="358" class="note-text">3. 状态切换不直接产生脉冲</text>
<text x="1605" y="396" class="note-text">4. 硬件安全收尾后确认终态</text>
<text x="1605" y="434" class="note-text">5. 终态原因和错误均需锁存</text>
<text x="1605" y="472" class="note-text">6. 零任务直接进入完成态</text>
<line x1="1605" y1="505" x2="1655" y2="505" stroke="#2F78B7" stroke-width="4"/>
<text x="1670" y="512" class="note-text">正常运行</text>
<line x1="1605" y1="535" x2="1655" y2="535" stroke="#D97925" stroke-width="4"/>
<text x="1670" y="542" class="note-text">等待/暂停/停止</text>

<text x="1000" y="1145" text-anchor="middle" class="subtitle">COMPLETED 或 STOPPED 收到下一次合法 START:清除旧完成标志,重新校验并建立运行快照</text>
</svg>

Двоични данни
Document/PLSR_document/图片/PLSR数据流关系图.png Целия файл

Преди След
Ширина: 1800  |  Височина: 1100  |  Големина: 204 KiB

+ 179
- 0
Document/PLSR_document/图片/PLSR数据流关系图.svg Целия файл

@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1800" height="1100" viewBox="0 0 1800 1100" role="img" aria-labelledby="title desc">
<title id="title">PLSR 4.2.1 数据流关系图</title>
<desc id="desc">展示PLSR逻辑软元件、参数快照、路径和速度处理、轴状态机、硬件与软件计数、状态发布及持久化之间的数据关系。</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#F8FBFF"/>
<stop offset="1" stop-color="#EEF3F9"/>
</linearGradient>
<filter id="shadow" x="-12%" y="-12%" width="124%" height="135%">
<feDropShadow dx="0" dy="5" stdDeviation="7" flood-color="#183A61" flood-opacity="0.14"/>
</filter>
<marker id="blueArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#3478B9"/>
</marker>
<marker id="orangeArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#D96F1E"/>
</marker>
<marker id="greenArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#398760"/>
</marker>
<marker id="purpleArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#7759A7"/>
</marker>
<style>
.title { font: 700 34px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.subtitle { font: 400 16px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #5E7187; }
.layer { font: 700 21px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.box-title { font: 700 18px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.box-text { font: 400 14px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #445C75; }
.small { font: 400 13px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #5A6E83; }
.white-title { font: 700 19px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #FFFFFF; }
.white-text { font: 400 14px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #F4F8FD; }
.blue { fill: none; stroke: #3478B9; stroke-width: 3; marker-end: url(#blueArrow); }
.orange { fill: none; stroke: #D96F1E; stroke-width: 3; marker-end: url(#orangeArrow); }
.green { fill: none; stroke: #398760; stroke-width: 3; marker-end: url(#greenArrow); }
.purple { fill: none; stroke: #7759A7; stroke-width: 3; marker-end: url(#purpleArrow); }
.dash { stroke-dasharray: 8 7; }
</style>
</defs>

<rect width="1800" height="1100" fill="url(#bg)"/>
<text x="900" y="50" text-anchor="middle" class="title">PLSR 数据流关系图</text>
<text x="900" y="78" text-anchor="middle" class="subtitle">参数数据、运行快照、运动计算、实时计数、状态发布与持久化</text>

<!-- 输入数据层 -->
<g filter="url(#shadow)">
<rect x="70" y="105" width="1660" height="145" rx="20" fill="#FFFFFF" stroke="#A9C5E2" stroke-width="2"/>
</g>
<text x="105" y="140" class="layer">输入数据层</text>

<rect x="260" y="135" width="310" height="83" rx="14" fill="#EDF5FE" stroke="#9CBFE1"/>
<text x="415" y="167" text-anchor="middle" class="box-title">S0 / S1 动态数据</text>
<text x="415" y="194" text-anchor="middle" class="box-text">路径段 · 定位模式 · 起始段</text>

<rect x="600" y="135" width="310" height="83" rx="14" fill="#EDF5FE" stroke="#9CBFE1"/>
<text x="755" y="167" text-anchor="middle" class="box-title">S2 与固定配置</text>
<text x="755" y="194" text-anchor="middle" class="box-text">HSD460~539 · SFD900~1419</text>

<rect x="940" y="135" width="310" height="83" rx="14" fill="#EDF5FE" stroke="#9CBFE1"/>
<text x="1095" y="167" text-anchor="middle" class="box-title">D 与输出配置</text>
<text x="1095" y="194" text-anchor="middle" class="box-text">模式 · 高速点 · DIR点 · 极性</text>

<rect x="1280" y="135" width="310" height="83" rx="14" fill="#EDF5FE" stroke="#9CBFE1"/>
<text x="1435" y="167" text-anchor="middle" class="box-title">命令与运行变量</text>
<text x="1435" y="194" text-anchor="middle" class="box-text">START/STOP · Wait/EXT · 动态频率</text>

<!-- 参数提交 -->
<path d="M415 218 L415 276 L675 276" class="blue"/>
<path d="M755 218 L755 276" class="blue"/>
<path d="M1095 218 L1095 276 L825 276" class="blue"/>

<g filter="url(#shadow)">
<rect x="610" y="285" width="580" height="96" rx="17" fill="#FFFFFF" stroke="#6E9FD0" stroke-width="2"/>
</g>
<text x="900" y="320" text-anchor="middle" class="box-title">PlsrParser_BuildSnapshot</text>
<text x="900" y="349" text-anchor="middle" class="box-text">边界与组合校验 · 原子申请资源 · 生成不可变执行副本</text>

<path d="M900 381 L900 409" class="blue"/>
<g filter="url(#shadow)">
<rect x="650" y="418" width="500" height="84" rx="16" fill="#2F70AF"/>
</g>
<text x="900" y="451" text-anchor="middle" class="white-title">PlsrJobSnapshot</text>
<text x="900" y="479" text-anchor="middle" class="white-text">S0段快照 · S1模式 · S2参数 · D绑定 · 计数器租约</text>

<!-- 运动处理层 -->
<text x="80" y="548" class="layer">运动处理层</text>

<path d="M900 502 L900 530 L320 530 L320 565" class="blue"/>
<path d="M900 502 L900 565" class="blue"/>
<path d="M900 502 L900 530 L1480 530 L1480 565" class="blue"/>

<rect x="140" y="575" width="360" height="112" rx="16" fill="#FFFFFF" stroke="#86AFD6" stroke-width="2"/>
<text x="320" y="610" text-anchor="middle" class="box-title">PlsrPath 路径解释</text>
<text x="320" y="638" text-anchor="middle" class="box-text">段进入 · Wait/ACT/EXT · 动态跳转</text>
<text x="320" y="663" text-anchor="middle" class="box-text">输出:段目标、方向、结束与事件</text>

<rect x="720" y="575" width="360" height="112" rx="16" fill="#FFFFFF" stroke="#86AFD6" stroke-width="2"/>
<text x="900" y="610" text-anchor="middle" class="box-title">PlsrProfile 速度规划</text>
<text x="900" y="638" text-anchor="middle" class="box-text">直线/S形/正弦 · 短距离 · 动态调频</text>
<text x="900" y="663" text-anchor="middle" class="box-text">输出:命令频率与PSC/ARR/CCR</text>

<rect x="1300" y="575" width="360" height="112" rx="16" fill="#FFFFFF" stroke="#86AFD6" stroke-width="2"/>
<text x="1480" y="610" text-anchor="middle" class="box-title">PlsrResource 资源管理</text>
<text x="1480" y="638" text-anchor="middle" class="box-text">Q0~Q3 · DIR · TIM9/TIM12</text>
<text x="1480" y="663" text-anchor="middle" class="box-text">输出:输出租约与计数模式</text>

<!-- 轴运行对象 -->
<path d="M320 687 L320 702 L575 702 L575 760 L597 760" class="blue"/>
<path d="M900 687 L900 710" class="blue"/>
<path d="M1480 687 L1480 700 L1215 700 L1215 760 L1203 760" class="blue"/>

<g filter="url(#shadow)">
<rect x="605" y="718" width="590" height="132" rx="20" fill="#173F69"/>
</g>
<text x="900" y="757" text-anchor="middle" class="white-title">PlsrAxis 四轴运行对象</text>
<text x="900" y="787" text-anchor="middle" class="white-text">状态机 · 当前段 · 运行快照 · 计数模式 · 停止原因</text>
<text x="900" y="815" text-anchor="middle" class="white-text">64位逻辑位置 · 任务累计 · 总累计 · 事件序号</text>

<!-- 实时硬件数据路径 -->
<path d="M1080 650 L1120 650 L1120 690 L1210 690 L1210 762 L1217 762" class="orange"/>
<rect x="1225" y="718" width="245" height="88" rx="14" fill="#FFF2E8" stroke="#E29A65" stroke-width="2"/>
<text x="1347" y="750" text-anchor="middle" class="box-title">TIM6 控制刷新</text>
<text x="1347" y="777" text-anchor="middle" class="box-text">0.1 ms / 1 ms</text>

<path d="M1347 718 L1347 704 L1575 704 L1575 718" class="orange"/>
<rect x="1480" y="718" width="250" height="88" rx="14" fill="#FFF2E8" stroke="#E29A65" stroke-width="2"/>
<text x="1605" y="750" text-anchor="middle" class="box-title">PWM输出定时器</text>
<text x="1605" y="777" text-anchor="middle" class="box-text">TIM10/13/11/14</text>

<path d="M1605 806 L1605 821" class="orange"/>
<rect x="1435" y="830" width="295" height="90" rx="14" fill="#FFF2E8" stroke="#E29A65" stroke-width="2"/>
<text x="1582" y="859" text-anchor="middle" class="box-title">脉冲累计与ISR事件</text>
<text x="1582" y="885" text-anchor="middle" class="box-text">TIM9/TIM12硬件计数优先</text>
<text x="1582" y="908" text-anchor="middle" class="box-text">输出定时器软件计数兜底</text>

<path d="M1435 875 L1220 875 L1220 784 L1203 784" class="orange"/>
<text x="1260" y="864" class="small">块累计 / 最终比较 / 故障事件</text>

<!-- 状态与持久化 -->
<path d="M780 850 L780 927" class="green"/>

<rect x="80" y="936" width="390" height="105" rx="16" fill="#F0FAF4" stroke="#7DB899" stroke-width="2"/>
<text x="275" y="970" text-anchor="middle" class="box-title">Flash / Backup SRAM</text>
<text x="275" y="998" text-anchor="middle" class="box-text">固定配置 · K0 · 位置与累计检查点</text>
<text x="275" y="1023" text-anchor="middle" class="box-text">复位后不自动恢复运动</text>
<path d="M650 850 L650 900 L275 900 L275 927" class="green"/>

<rect x="600" y="936" width="360" height="105" rx="16" fill="#F0FAF4" stroke="#7DB899" stroke-width="2"/>
<text x="780" y="970" text-anchor="middle" class="box-title">PlsrStatusPublish</text>
<text x="780" y="998" text-anchor="middle" class="box-text">版本化一致快照</text>
<text x="780" y="1023" text-anchor="middle" class="box-text">状态 · 频率 · 位置 · 计数 · 错误</text>

<path d="M960 988 L1000 988" class="purple"/>
<rect x="1010" y="936" width="350" height="105" rx="16" fill="#F5F0FC" stroke="#A995C7" stroke-width="2"/>
<text x="1185" y="970" text-anchor="middle" class="box-title">固定运行状态</text>
<text x="1185" y="998" text-anchor="middle" class="box-text">HSD0~15 · SM · SD</text>
<text x="1185" y="1023" text-anchor="middle" class="box-text">I6000~6399段事件</text>

<path d="M1360 988 L1400 988" class="purple"/>
<rect x="1410" y="936" width="320" height="105" rx="16" fill="#F5F0FC" stroke="#A995C7" stroke-width="2"/>
<text x="1570" y="970" text-anchor="middle" class="box-title">外部读取</text>
<text x="1570" y="998" text-anchor="middle" class="box-text">Modbus RTU · 内部API</text>
<text x="1570" y="1023" text-anchor="middle" class="box-text">读取一致状态,不直接写运行对象</text>

<!-- 动态命令到状态机 -->
<path d="M1435 218 L1435 270 L1240 270 L1240 755 L1203 755" class="purple dash"/>
<text x="1255" y="293" class="small">运行命令与条件变量</text>

<!-- 图例 -->
<circle cx="90" cy="1073" r="6" fill="#3478B9"/>
<text x="105" y="1078" class="small">配置与运动数据</text>
<circle cx="265" cy="1073" r="6" fill="#D96F1E"/>
<text x="280" y="1078" class="small">硬实时数据与事件</text>
<circle cx="470" cy="1073" r="6" fill="#398760"/>
<text x="485" y="1078" class="small">持久化数据</text>
<circle cx="615" cy="1073" r="6" fill="#7759A7"/>
<text x="630" y="1078" class="small">状态/命令接口</text>
</svg>

Document/PLSR_document/PLSR系统结构图.png → Document/PLSR_document/图片/PLSR系统结构图.png Целия файл


Document/PLSR_document/PLSR系统结构图.svg → Document/PLSR_document/图片/PLSR系统结构图.svg Целия файл


Двоични данни
Document/PLSR_document/图片/PLSR高速脉冲与硬件计数架构图.png Целия файл

Преди След
Ширина: 1800  |  Височина: 1100  |  Големина: 196 KiB

+ 166
- 0
Document/PLSR_document/图片/PLSR高速脉冲与硬件计数架构图.svg Целия файл

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1800" height="1100" viewBox="0 0 1800 1100" role="img" aria-labelledby="title desc">
<title id="title">PLSR高速脉冲与硬件计数架构图</title>
<desc id="desc">展示TIM6控制刷新、四路PWM输出、TIM9和TIM12硬件计数二选一连接、软件计数兜底以及最终完整边沿关闭流程。</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#F8FBFF"/>
<stop offset="1" stop-color="#EEF3F9"/>
</linearGradient>
<filter id="shadow" x="-12%" y="-12%" width="124%" height="135%">
<feDropShadow dx="0" dy="5" stdDeviation="7" flood-color="#183A61" flood-opacity="0.14"/>
</filter>
<marker id="blueArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#3478B9"/>
</marker>
<marker id="orangeArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#D96F1E"/>
</marker>
<marker id="purpleArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#7357A5"/>
</marker>
<marker id="greenArrow" markerWidth="11" markerHeight="11" refX="9" refY="5.5" orient="auto">
<path d="M0,0 L11,5.5 L0,11 z" fill="#398760"/>
</marker>
<style>
.title { font: 700 34px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.subtitle { font: 400 16px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #5E7187; }
.layer { font: 700 21px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.box-title { font: 700 18px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #17385F; }
.box-text { font: 400 14px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #445C75; }
.small { font: 400 13px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #5A6E83; }
.white-title { font: 700 19px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #FFFFFF; }
.white-text { font: 400 14px "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; fill: #F4F8FD; }
.blue { fill: none; stroke: #3478B9; stroke-width: 3; marker-end: url(#blueArrow); }
.orange { fill: none; stroke: #D96F1E; stroke-width: 3; marker-end: url(#orangeArrow); }
.purple { fill: none; stroke: #7357A5; stroke-width: 3; marker-end: url(#purpleArrow); }
.green { fill: none; stroke: #398760; stroke-width: 3; marker-end: url(#greenArrow); }
.dash { stroke-dasharray: 8 7; }
</style>
</defs>

<rect width="1800" height="1100" fill="url(#bg)"/>
<text x="900" y="50" text-anchor="middle" class="title">PLSR 高速脉冲与硬件计数架构图</text>
<text x="900" y="78" text-anchor="middle" class="subtitle">硬件PWM维持边沿 · TIM9/TIM12硬件计数优先 · 软件周期计数兜底</text>

<!-- 控制配置 -->
<g filter="url(#shadow)">
<rect x="90" y="105" width="1620" height="120" rx="20" fill="#FFFFFF" stroke="#A8C4E0" stroke-width="2"/>
</g>
<text x="125" y="140" class="layer">控制与配置</text>

<rect x="330" y="130" width="330" height="70" rx="14" fill="#EAF4FE" stroke="#94B9DD"/>
<text x="495" y="158" text-anchor="middle" class="box-title">PlsrProfile 速度规划</text>
<text x="495" y="183" text-anchor="middle" class="box-text">命令频率 · PSC/ARR/CCR</text>

<rect x="735" y="130" width="330" height="70" rx="14" fill="#EAF4FE" stroke="#94B9DD"/>
<text x="900" y="158" text-anchor="middle" class="box-title">TIM6 控制刷新</text>
<text x="900" y="183" text-anchor="middle" class="box-text">0.1 ms / 1 ms · 安全预装载</text>

<rect x="1140" y="130" width="330" height="70" rx="14" fill="#EAF4FE" stroke="#94B9DD"/>
<text x="1305" y="158" text-anchor="middle" class="box-title">PlsrResource 资源管理</text>
<text x="1305" y="183" text-anchor="middle" class="box-text">输出租约 · 计数器租约 · 计数模式</text>

<path d="M660 165 L727 165" class="blue"/>
<path d="M1065 165 L1132 165" class="blue"/>

<!-- PWM输出层 -->
<text x="95" y="285" class="layer">硬件PWM输出层</text>
<path d="M900 200 L900 258" class="blue"/>
<path d="M900 258 L265 258 L265 315" class="blue"/>
<path d="M900 258 L690 258 L690 315" class="blue"/>
<path d="M900 258 L1110 258 L1110 315" class="blue"/>
<path d="M900 258 L1535 258 L1535 315" class="blue"/>

<g filter="url(#shadow)">
<rect x="100" y="325" width="330" height="125" rx="17" fill="#FFF3E9" stroke="#E29A64" stroke-width="2"/>
<rect x="525" y="325" width="330" height="125" rx="17" fill="#FFF3E9" stroke="#E29A64" stroke-width="2"/>
<rect x="945" y="325" width="330" height="125" rx="17" fill="#FFF3E9" stroke="#E29A64" stroke-width="2"/>
<rect x="1370" y="325" width="330" height="125" rx="17" fill="#FFF3E9" stroke="#E29A64" stroke-width="2"/>
</g>

<text x="265" y="360" text-anchor="middle" class="box-title">Q0 · PF6</text>
<text x="265" y="389" text-anchor="middle" class="box-text">TIM10_CH1 · 168 MHz</text>
<text x="265" y="417" text-anchor="middle" class="box-text">PWM / A相 / CW或CCW</text>

<text x="690" y="360" text-anchor="middle" class="box-title">Q1 · PF8</text>
<text x="690" y="389" text-anchor="middle" class="box-text">TIM13_CH1 · 84 MHz</text>
<text x="690" y="417" text-anchor="middle" class="box-text">PWM / B相 / CW或CCW</text>

<text x="1110" y="360" text-anchor="middle" class="box-title">Q2 · PF7</text>
<text x="1110" y="389" text-anchor="middle" class="box-text">TIM11_CH1 · 168 MHz</text>
<text x="1110" y="417" text-anchor="middle" class="box-text">PWM / A相 / CW或CCW</text>

<text x="1535" y="360" text-anchor="middle" class="box-title">Q3 · PF9</text>
<text x="1535" y="389" text-anchor="middle" class="box-text">TIM14_CH1 · 84 MHz</text>
<text x="1535" y="417" text-anchor="middle" class="box-text">PWM / B相 / CW或CCW</text>

<!-- 物理输出 -->
<path d="M265 450 L265 490" class="orange"/>
<path d="M690 450 L690 490" class="orange"/>
<path d="M1110 450 L1110 490" class="orange"/>
<path d="M1535 450 L1535 490" class="orange"/>
<rect x="100" y="500" width="1600" height="60" rx="15" fill="#273D55"/>
<text x="900" y="526" text-anchor="middle" class="white-title">物理高速输出 Q0~Q3</text>
<text x="900" y="550" text-anchor="middle" class="white-text">PULSE/DIR:上升沿计数 · AB相:完整四状态周期计数 · CW/CCW:当前方向通道计数</text>

<!-- 内部计数连接 -->
<text x="95" y="620" class="layer">内部硬件计数与软件兜底</text>

<path d="M265 450 L265 590 L440 590 L440 665" class="purple"/>
<path d="M1110 450 L1110 590 L620 590 L620 665" class="purple"/>
<path d="M690 450 L690 610 L1120 610 L1120 665" class="purple"/>
<path d="M1535 450 L1535 610 L1300 610 L1300 665" class="purple"/>

<text x="305" y="582" class="small">TIM10_OC · ITR2</text>
<text x="935" y="582" class="small">TIM11_OC · ITR3</text>
<text x="735" y="603" class="small">TIM13_OC · ITR2</text>
<text x="1390" y="603" class="small">TIM14_OC · ITR3</text>

<g filter="url(#shadow)">
<rect x="280" y="675" width="500" height="145" rx="19" fill="#F3EEFC" stroke="#9F88C4" stroke-width="2"/>
<rect x="1020" y="675" width="500" height="145" rx="19" fill="#F3EEFC" stroke="#9F88C4" stroke-width="2"/>
</g>
<text x="530" y="712" text-anchor="middle" class="box-title">TIM9 · 16位硬件累计</text>
<text x="530" y="741" text-anchor="middle" class="box-text">Q0/TIM10 或 Q2/TIM11 二选一</text>
<text x="530" y="768" text-anchor="middle" class="box-text">External Clock Mode 1 · 65536脉冲块</text>
<text x="530" y="795" text-anchor="middle" class="box-text">100 kHz时块中断约1.53次/秒</text>

<text x="1270" y="712" text-anchor="middle" class="box-title">TIM12 · 16位硬件累计</text>
<text x="1270" y="741" text-anchor="middle" class="box-text">Q1/TIM13 或 Q3/TIM14 二选一</text>
<text x="1270" y="768" text-anchor="middle" class="box-text">External Clock Mode 1 · 65536脉冲块</text>
<text x="1270" y="795" text-anchor="middle" class="box-text">100 kHz时块中断约1.53次/秒</text>

<rect x="660" y="850" width="480" height="88" rx="16" fill="#FFF8E9" stroke="#D9AD50" stroke-width="2"/>
<text x="900" y="882" text-anchor="middle" class="box-title">软件周期计数兜底</text>
<text x="900" y="909" text-anchor="middle" class="box-text">计数器不可达或被占用时,启用对应PWM定时器更新中断</text>

<path d="M530 820 L530 840 L652 840 L652 872" class="purple dash"/>
<path d="M1270 820 L1270 840 L1148 840 L1148 872" class="purple dash"/>
<text x="900" y="837" text-anchor="middle" class="small">未获得租约的轴自动回退,不拒绝合法任务</text>

<!-- 计数结果与尾停 -->
<path d="M530 820 L530 962 L680 962" class="green"/>
<path d="M1270 820 L1270 962 L1120 962" class="green"/>
<path d="M900 938 L900 952" class="green"/>
<g filter="url(#shadow)">
<rect x="690" y="958" width="420" height="88" rx="17" fill="#EAF8F0" stroke="#73B18F" stroke-width="2"/>
</g>
<text x="900" y="990" text-anchor="middle" class="box-title">目标数量到达与最终完整边沿</text>
<text x="900" y="1017" text-anchor="middle" class="box-text">PULSE/CW/CCW:末脉冲下降沿 · AB:第四次状态跳变</text>

<path d="M1110 1002 L1280 1002" class="green"/>
<rect x="1290" y="958" width="400" height="88" rx="17" fill="#EAF8F0" stroke="#73B18F" stroke-width="2"/>
<text x="1490" y="990" text-anchor="middle" class="box-title">安全关闭并发布完成事件</text>
<text x="1490" y="1017" text-anchor="middle" class="box-text">关闭通道 · 释放租约 · 更新位置和段状态</text>

<!-- 图例 -->
<circle cx="100" cy="1075" r="6" fill="#3478B9"/>
<text x="115" y="1080" class="small">控制配置</text>
<circle cx="230" cy="1075" r="6" fill="#D96F1E"/>
<text x="245" y="1080" class="small">物理脉冲</text>
<circle cx="355" cy="1075" r="6" fill="#7357A5"/>
<text x="370" y="1080" class="small">计数连接/回退</text>
<circle cx="535" cy="1075" r="6" fill="#398760"/>
<text x="550" y="1080" class="small">完成与状态事件</text>
</svg>

Document/PLSR_document/任务要求.png → Document/PLSR_document/图片/任务要求.png Целия файл


Двоични данни
Document/PLSR_document/框图/PLSR运动控制流程图 - 副本.vsdx Целия файл


Двоични данни
Document/PLSR_document/框图/PLSR运动控制流程图 - 副本_修改前备份.vsdx Целия файл


Двоични данни
Document/PLSR_document/框图/PLSR运动控制流程图.vsdx Целия файл


Двоични данни
Document/PLSR_document/框图/PLSR运动控制流程图_完整版.vsdx Целия файл


Двоични данни
Document/PLSR_document/框图/PLSR运动控制流程图_完整预览.png Целия файл

Преди След
Ширина: 2969  |  Височина: 1913  |  Големина: 198 KiB

Двоични данни
Document/PLSR_document/框图/PLSR运动控制流程图_当前预览.png Целия файл

Преди След
Ширина: 2318  |  Височина: 1788  |  Големина: 113 KiB

Двоични данни
Document/PLSR_document/框图/PLSR高速脉冲与硬件计数架构图.vsdx Целия файл


Двоични данни
Document/PLSR_document/框图/~$$PLSR运动控制流程图 - 副本.~vsdx Целия файл


Двоични данни
Document/PLSR_document/框图/状态机图解.vsdx Целия файл


Двоични данни
Document/PLSR_document/虞文昊_PLSR_2026.8.6.zip Целия файл


Двоични данни
Document/PLSR_document/虞文昊_PLSR_2026.8.6/设计方案书.docx Целия файл


Двоични данни
Document/PLSR_document/虞文昊_PLSR_2026.8.6/需求规格书.docx Целия файл


Двоични данни
Document/PLSR_document/设计方案书.docx Целия файл


Двоични данни
Document/PLSR_document/设计方案书2.docx Целия файл


Двоични данни
Document/PLSR_document/需求规格书.docx Целия файл


+ 0
- 12
Modbus/Inc/modbus_rtu_slave.h Целия файл

@@ -66,17 +66,6 @@ typedef struct
uint32_t droppedFrameCount; ///< 接收槽占用或长度错误导致的丢帧数
uint32_t uartErrorCount; ///< HAL 串口错误计数
} MODBUS_SLAVE_STATS;
/**
* @brief 一次Modbus RTU通信的历史记录
*/
typedef struct
{
uint32_t tick; ///< 通信发生时的系统时间
uint16_t requestLength; ///< 请求ADU长度
uint16_t responseLength; ///< 响应ADU长度
uint8_t request[256]; ///< 请求ADU数据
uint8_t response[256]; ///< 响应ADU数据
} MODBUS_HISTORY_ITEM;
/** @brief Modbus 从站通信统计数据 */
extern volatile MODBUS_SLAVE_STATS ModbusSlaveStatistics;
/**
@@ -153,7 +142,6 @@ uint8_t ModbusSlaveGetCoil(uint16_t address, uint8_t *state);
uint8_t ModbusSlaveIsConnected(uint32_t timeoutMs);
void ModbusRetainedRegistersLoad(void);
void ModbusRetainedRegistersPoll(void);
void HistorySaveToRegisters(void);

#ifdef __cplusplus
}


+ 0
- 135
Modbus/Src/modbus_rtu_slave.c Целия файл

@@ -1,5 +1,4 @@
#include "modbus_rtu_slave.h"
#include "ucos_ii.h"
#include <string.h>

#define MODBUS_RTU_ADU_SIZE_MAX (256U) // Modbus RTU 最大 ADU 长度,单位为字节
@@ -25,12 +24,7 @@

static UART_HandleTypeDef *ModbusUart;
static uint8_t ModbusSlaveAddress;
static void ModbusHistorySave(uint32_t tick, const uint8_t *request,
uint16_t requestLength, const uint8_t *response,
uint16_t responseLength);
static HAL_StatusTypeDef ModbusStartReceive(void);
static MODBUS_HISTORY_ITEM ModbusHistory[16];
static uint16_t ModbusHistoryWriteIndex;
/*最近一次字节尾到字节头的间隔周期数*/
static volatile uint32_t ModbusLastInterFrameGapCycles;
/**
@@ -457,73 +451,6 @@ tx:
return (uint16_t)(5U + quantity * 2U);
}

/*
* 返回帧
*从站地址 | 14 | 总字节数 | 子响应长度 | 06 | 寄存器数据 | CRC
*
* 01 从站地址
* 14 功能码
* 06 后续响应数据共6字节
* 05 当前子响应长度,共5字节
* 06 引用类型
* 12 34 第一个寄存器
* 56 78 第二个寄存器
*/
static uint16_t ModbusProcessFile(const uint8_t *request,
uint16_t requestLength)
{
uint16_t fileNumber;
uint16_t recordNumber;
uint16_t quantity;
uint16_t index;
uint16_t value;
uint16_t *historyRegister;
if (requestLength != 12U)
{
ModbusSlaveStatistics.illegalValueCount++;
return ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
}
if ((request[2] != 7U) || (request[3] != 0x06U))
{
ModbusSlaveStatistics.illegalValueCount++;
return ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
}

quantity = ModbusGetU16Be(&request[8]);
fileNumber = ModbusGetU16Be(&request[4]);
recordNumber = ModbusGetU16Be(&request[6]);
if ((quantity == 0U) || (quantity > 124U)) // 数量0或者数量大于最大值
{
ModbusSlaveStatistics.illegalValueCount++;
return ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
}
/* 检查文件号、记录号和读取范围 */
if ((fileNumber > 15U) || (recordNumber >= 260U)
|| (((uint32_t)recordNumber + quantity) > 260UL))
{
ModbusSlaveStatistics.illegalAddressCount++;
return ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_ADDRESS);
}
ModbusTxFrame[0] = ModbusSlaveAddress;
ModbusTxFrame[1] = 0X14;
ModbusTxFrame[2] = (uint8_t)(2U + quantity * 2U);
ModbusTxFrame[3] = (uint8_t)(1U + quantity * 2U);

ModbusTxFrame[4] = 0X06;
historyRegister = (uint16_t *)ModbusHistory;
for (index = 0U; index < quantity; index++)
{
uint16_t address = fileNumber * 260 + recordNumber + index;

value = *(historyRegister + address);
ModbusTxFrame[5U + index * 2U] = (uint8_t)(value & 0x00FFU);
ModbusTxFrame[6U + index * 2U] = (uint8_t)(value >> 8U);
}

ModbusAppendCrc(ModbusTxFrame, (uint16_t)(5U + quantity * 2U));
return (uint16_t)(7U + quantity * 2U);
}

/**
* @brief 处理写单个保持寄存器功能码 0x06
* @param[in] request RTU 请求帧
@@ -893,11 +820,6 @@ static uint16_t ModbusProcessRequest(const uint8_t *request,
return (isBroadcast != 0U)
? 0U
: ModbusProcessReadHolding(request, requestLength);
case 0x14U:
return (isBroadcast != 0U)
? 0U
: ModbusProcessFile(request, requestLength);

case 0x05U: // 写单个线圈
return ModbusProcessWriteSingleCoil(request, requestLength,
isBroadcast);
@@ -959,9 +881,6 @@ void ModbusSlavePoll(void)
}

responseLength = ModbusProcessRequest(ModbusRxFrame, ModbusRxFrameLength);
ModbusHistorySave(OSTimeGet() / 1000, ModbusRxFrame, ModbusRxFrameLength,
ModbusTxFrame, responseLength);

if (responseLength > 0U)
{
ModbusTxBusy = 1U;
@@ -1192,57 +1111,3 @@ void ModbusRetainedRegistersPoll(void)
ModbusRetainedSnapshot[index] = value;
}
}
static void ModbusHistorySave(uint32_t tick, const uint8_t *request,
uint16_t requestLength, const uint8_t *response,
uint16_t responseLength)
{
MODBUS_HISTORY_ITEM *item;

if (requestLength > 256U)
{
requestLength = 256U;
}

if (responseLength > 256U)
{
responseLength = 256U;
}

item = &ModbusHistory[ModbusHistoryWriteIndex];

item->tick = tick;
item->requestLength = requestLength;
item->responseLength = responseLength;

(void)memcpy(item->request, request, requestLength);

if (responseLength > 0U)
{
(void)memcpy(item->response, response, responseLength);
}

ModbusHistoryWriteIndex++;

if (ModbusHistoryWriteIndex >= 16U)
{
ModbusHistoryWriteIndex = 0U;
}
}
void HistorySaveToRegisters(void)
{


uint16_t index;

if (ModbusHistoryWriteIndex == 0U)
{
index = 15U;
}
else
{
index = ModbusHistoryWriteIndex - 1U;
}

(void)memcpy(&ModbusHoldingRegisters[1000U + index * 260U],
&ModbusHistory[index], sizeof(ModbusHistory[index]));
}

Зареждане…
Отказ
Запис