文档版本:V1.0 Rev.C
需求基线:PLSR需求规格统计_V1.3.md Rev.B
目标平台:XDM-60T4-E / STM32F407IG / uC/OS-II
编制日期:2026-08-10
文档状态:设计基线;标记为“待上板验证”的项目在验证完成前不得关闭
本项目在现有 XDM-60T4-E 控制器工程中实现 PLSR 定位控制功能。控制器采用
STM32F407IG、12 MHz 外部晶振、168 MHz 系统时钟和 uC/OS-II,现有工程已经具备
USART1 Modbus RTU、USB Device、Backup SRAM 和基本任务调度能力,但尚未实现高速脉冲、
路径解释、速度规划及轴状态管理。
PLSR V1.0 对标信捷 XD/XL 系列 PLC 的 PLSR 逻辑模型,保留 PLSR S0 S1 S2 D、
S0 多段数据、S1 用户参数、S2 K0~K4 参数组、D 输出端口以及固定 HSD/SFD/SM/SD/I
软元件语义。在此基础上增加四轴独立运行、CW/CCW、64 位内部位置、参数原子提交、命令防重、
诊断和 Backup SRAM 检查点等能力。
本文说明系统如何实现需求,重点覆盖:
V1.0 不实现多轴直线或圆弧插补、闭环位置修正、电子凸轮、龙门同步、完整机械回零和
安全认证急停。
| 名称 | 定义 |
|---|---|
| PLSR | 多段脉冲定位指令,逻辑调用形式为 PLSR S0 S1 S2 D |
| S0 | 动态首地址指定的路径数据块,保存总段数及各段频率、脉冲数、等待和跳转 |
| S1 | 动态首地址指定的用户参数块,保存相对/绝对模式和起始段 |
| S2 | K0~K4 运动参数套组,保存默认速度、速度限制、曲线、补偿、刷新周期及与独立FOLLOW指令共用的字段 |
| D | 输出资源操作数,兼容语义下选择 Y0~Y3,本项目对应 Q0~Q3 高速资源 |
| PULSE/DIR | 一个端口输出脉冲,另一个端口输出方向电平 |
| AB 相 | 两路相差四分之一周期的正交输出,通过相位先后表示方向 |
| CW/CCW | 正向和反向分别使用独立脉冲端口,两个端口不得同时输出 |
| 指令脉冲 | PULSE/DIR 的一个上升沿、CW/CCW 的一个完整脉冲或 AB 相的一个完整四状态周期 |
| 控制刷新周期 | 速度规划器更新目标频率的周期,只允许 0.1 ms 或 1 ms |
| 脉冲周期 | 由当前输出频率决定的物理波形周期,与 OS Tick 和控制刷新周期不同 |
| 运行快照 | START 接受后为轴生成的不可变 S0/S1/S2/D 执行副本 |
| BUSY | 轴存在已接受但尚未终止的任务,包括运动、WAIT和PAUSED |
| PULSE_ACTIVE | 当前物理脉冲正在输出 |
| DONE | 当前任务正常完成并锁存;STOP或ERROR不得置位 |
| 当量 | 通过每转脉冲数和每转移动量将工程单位换算为指令脉冲 |
| 固定软元件 | 信捷规定地址和含义的 HSD、SFD、SM、SD、I 数据 |
| 动态数据地址 | 调用者在允许数据区内为 S0、S1 选择的连续首地址 |
系统应实现四个独立逻辑轴。PULSE/DIR 可同时运行四轴;AB 相和 CW/CCW 使用 Q0/Q1、
Q2/Q3 固定点对,最多同时运行两轴。四轴之间不做插补,各轴独立启动、停止、调频、定位和查询。
主要功能如下:
| 类别 | V1.0功能 |
|---|---|
| 输出方式 | PULSE/DIR、AB相、CW/CCW |
| 轴数 | 四轴独立;AB/CW/CCW最多两轴 |
| 频率 | 1~100 kHz保证范围;100001~200000 Hz经板测后作为非保证扩展 |
| 脉冲数量 | 完整有符号32位;0表示跳过当前段 |
| 定位 | 相对定位、绝对定位、设置/清零当前位置 |
| 路径 | 1~100段,支持等待、ACT、EXT和动态跳转 |
| 曲线 | 无加减速、直线、S形、正弦 |
| 段衔接 | 完成方式、后续方式 |
| 控制 | START、STOP、PAUSE、RESUME、保存、清零、自测 |
| 刷新周期 | S2配置0.1 ms或1 ms,OS Tick保持1 ms |
| 保存 | Flash固定配置、Backup SRAM动态检查点 |
| 对标 | 固定HSD/SFD/SM/SD/I地址及S0/S1动态首地址语义 |
| 项目 | 现状/约束 | 方案处理 |
|---|---|---|
| MCU | STM32F407IG,168 MHz | 保持现有时钟配置 |
| OS | uC/OS-II,Tick为1 ms | 不提高OS Tick |
| Modbus | USART1+DMA,任务轮询 | 作为调用与监控适配层 |
| USB | OTG FS中断优先级已设为4 | 低于输出/计数中断优先级1和TIM6优先级2,仍需长稳并发板测 |
| PLSR定时器 | TIM6、TIM9/TIM12及TIM10/11/13/14已接入 | 保持固定资源映射并通过租约隔离冲突 |
| Modbus历史 | 1000起始历史区写入已删除 | S0/S1动态数据池不得恢复旧历史映射 |
| Backup SRAM | 已完成基础初始化 | 扩展为带版本和CRC的双检查点 |
| 急停 | 无外部硬件切断 | 仅实现软件立即关闭和状态锁存 |
图 2-1 PLSR系统结构图
图中蓝色表示控制与数据流,橙色表示硬实时及物理输出路径,绿色表示固定软元件、持久化和诊断等
数据服务。为方便纯文本环境阅读,结构关系同时保留如下文字版本。
┌──────────────────────────────────────────────────────────┐
│ PLC调用 / Modbus RTU / 内部测试接口 │
└───────────────────────────┬──────────────────────────────┘
│
┌───────────────────────────▼──────────────────────────────┐
│ 命令与软元件适配:调用上升沿、命令序号、状态快照 │
└───────────────────────────┬──────────────────────────────┘
│
┌───────────────────────────▼──────────────────────────────┐
│ 参数提交:读取S0/S1/S2/D、完整校验、资源申请、运行快照 │
└───────────────────────────┬──────────────────────────────┘
│
┌───────────────────────────▼──────────────────────────────┐
│ 四轴运动内核:状态机、路径解释、速度规划、位置与段事件 │
└───────────────┬───────────────────────────┬──────────────┘
│ │
┌───────────────▼──────────────┐ ┌─────────▼──────────────┐
│ OS任务控制面 │ │ 定时器/EXTI实时面 │
│ 命令、段切换、等待、保存 │ │ 脉冲、调频、尾停、限位 │
└───────────────┬──────────────┘ └─────────┬──────────────┘
│ │
└─────────────┬─────────────┘
│
┌─────────────────────────────▼────────────────────────────┐
│ STM32F407板级层:TIM6、TIM9/12、TIM10/11/13/14、GPIO、EXTI│
└─────────────────────────────┬────────────────────────────┘
│
Q0~Q3 / DIR
│
伺服驱动器
系统划分为控制面和实时面:
| 执行域 | 运行位置 | 负责内容 | 禁止内容 |
|---|---|---|---|
| 控制面 | PlsrTask |
命令、校验、快照、状态机慢路径、等待、段切换、保存和发布 | 逐脉冲翻转GPIO |
| 实时面 | TIM/EXTI中断 | 硬件累计、软件兜底计数、尾脉冲、速度刷新、限位和EXT锁存 | 阻塞、动态内存、Flash、通信解析、OS等待 |
| 编号 | 模块 | 建议源文件 | 主要职责 |
|---|---|---|---|
| M01 | PLSR运动控制核心 | plsr_core.c |
四轴对象、任务入口、事件分派和模块协调 |
| M02 | 参数解析与任务提交 | plsr_parser.c |
S0/S1/S2/D读取、校验、快照和提交 |
| M03 | 路径解释与段调度 | plsr_path.c |
段进入、等待、跳转、零段和段事件 |
| M04 | 速度规划 | plsr_profile.c |
三种曲线、短距离、衔接和动态调频 |
| M05 | 高速脉冲输出 | plsr_hal_f407.c |
PWM、TIM9/TIM12硬件累计、软件计数兜底、AB配对和安全关闭 |
| M06 | 状态机与命令 | plsr_state.c、plsr_command.c |
合法状态转换、命令幂等和优先级 |
| M07 | 输出资源管理 | plsr_resource.c |
高速点、DIR点及TIM9/TIM12计数资源的原子申请和释放 |
| M08 | 软元件与通信适配 | plsr_device.c |
HSD/SFD/SM/SD/I、S0/S1及Modbus边界 |
| M09 | 位置、当量与持久化 | plsr_position.c、plsr_persist.c |
64位位置、换算、限位、Flash和Backup SRAM |
| M10 | 诊断与自测 | plsr_diag.c |
错误映射、分频记录、性能统计和自测 |
建议工程目录:
PLSR/
Inc/
plsr.h
plsr_types.h
plsr_device.h
plsr_hal.h
Src/
plsr_core.c
plsr_parser.c
plsr_path.c
plsr_profile.c
plsr_hal_f407.c
plsr_state.c
plsr_command.c
plsr_resource.c
plsr_device.c
plsr_position.c
plsr_persist.c
plsr_diag.c
运动控制核心静态创建四个 PlsrAxis 对象,负责初始化各子模块、运行 PlsrTask、接收中断事件、
调用状态机、协调段调度和发布状态。模块不直接解释 Modbus 帧,也不直接操作 Flash 或具体 GPIO。
OS任务建议如下:
| 任务 | 建议优先级 | 触发方式 | 职责 |
|---|---|---|---|
PlsrTask |
4 | 事件唤醒,最长1 ms巡检 | 命令、路径慢处理、等待、状态发布和保存请求 |
| 现有Modbus任务 | 5 | 1 ms轮询 | 通信收发和协议解析 |
| 测试任务 | 6及以后 | 按需 | 非实时测试和日志 |
中断优先级首次配置建议如下,最终值通过 uC/OS-II 端口约束和上板测试冻结:
| 抢占优先级 | 中断 | 用途 |
|---|---|---|
| 1 | 硬限位EXTI | 锁存限位并禁止继续越界输出 |
| 2 | TIM9/TIM12、TIM10/11/13/14 | 硬件计数完成、软件兜底计数、参数边界和尾脉冲关闭 |
| 3 | TIM6 | 0.1 ms速度控制基准 |
| 4 | EXT输入EXTI | 路径切段边沿锁存 |
| 5 | USART1、DMA2 | 现有Modbus通信 |
| 6 | USB OTG FS | 从当前优先级0调低 |
| 15 | SysTick | 现有1 ms OS Tick |
实时中断不调用 OS API,只设置原子事件位。PlsrTask 获取事件后按急停、限位、立即停止、
减速停止、暂停和正常事件的顺序处理。
PlsrResult Plsr_Init(void);
void Plsr_Task(void *argument);
PlsrResult Plsr_Submit(const PlsrCall *call, uint32_t sequence);
PlsrResult Plsr_Command(const PlsrCommand *command);
bool Plsr_GetStatus(uint8_t axis, PlsrStatus *status);
void Plsr_IsrPost(uint8_t axis, uint32_t event_mask);
输入为调用参数、控制命令和硬件事件;输出为提交结果、状态快照、固定软元件状态和持久化请求。
图 3-1 PLSR单轴完整执行流程图
系统启动
-> 输出置安全状态
-> 初始化设备访问、资源和持久化
-> 初始化四轴对象
-> 初始化定时器和EXTI
-> 自检
-> 全部成功:进入IDLE
-> 任一失败:保持输出关闭并发布初始化错误
PlsrTask循环
-> 读取ISR事件
-> 按优先级处理停止和限位
-> 处理命令
-> 推进各轴状态机
-> 处理等待和段跳转
-> 发布一致状态
-> 执行非实时保存请求
该模块把 PLSR S0 S1 S2 D 转换为可执行任务。START 只在启动信号上升沿或新命令序号时接受。
模块先完整校验,再原子申请资源,最后生成运行快照;任何失败都不得影响正在运行的合法任务。
S0校验内容:
S0 + N*10 + 9 使用检查过的64位运算;S1只包含定位模式和起始段。S2只允许K0~K4,并校验默认速度、最高速度、起止频率、曲线、
补偿、刷新周期及FOLLOW共用字段的合法范围;FOLLOW共用字段不参与PLSR运算。D按输出模式检查
Y0~Y3或Y0/Y2固定点对。
PlsrResult PlsrParser_BuildSnapshot(
const PlsrCall *call,
PlsrJobSnapshot *snapshot,
PlsrErrorDetail *detail);
PlsrResult PlsrParser_ReadLiveFrequency(
const PlsrJobSnapshot *snapshot,
uint16_t segment,
uint32_t *frequency_hz);
输入为 S0/S1 首地址、S2选择值、D及输出配置;输出为完整快照或带错误数据块号的失败结果。
收到START
-> 检查上升沿/命令序号
-> 检查轴状态
-> 读取S0总段数并计算边界
-> 读取并校验全部S0段
-> 读取并校验S1
-> 读取并校验S2和D
-> 检查绝对位置、限位和组合参数
-> 原子申请输出资源
-> 生成不可变运行快照
-> 成功返回运动核心
任一步失败
-> 回滚已申请资源
-> 保持输出无效
-> 返回兼容码和增强错误
运行期间仅允许重新读取当前段目标频率。S0其它字段、S1、S2、D和资源绑定均使用快照;非法动态
频率写入被忽略,继续使用最近合法值并发布诊断。
路径模块负责1~100段的进入、执行完成条件、等待、动态跳转和段事件。相对模式把段脉冲数解释为
本段位移;绝对模式把它解释为目标坐标,并用目标坐标减当前逻辑位置求实际输出位移。
零值判断顺序固定为:
等待条件处理如下:
| 编码 | 条件 | 模块处理 |
|---|---|---|
| H00 | 脉冲完成 | 输出完成后立即跳转 |
| H01 | Wait时间 | 完成后计时;0按1 ms |
| H02 | Wait信号 | 完成后判断X/M/HM,未有效则保持WAIT |
| H03 | ACT时间 | 段开始计时;时间到放弃剩余脉冲,脉冲先完则等到时间 |
| H04 | EXT信号 | 新上升沿到达时放弃剩余脉冲;脉冲先完仍等待新边沿 |
| H05 | EXT或脉冲完成 | 原子锁存先到原因,先到者决定跳转 |
快照保存变量来源类型和编号,Wait/ACT数值、Wait信号和动态跳转值在实际求值时读取,以保留信捷
动态变量语义。跳转值0表示顺序执行,1~N表示指定段,自跳表示有意无限循环。
PULSE/DIR运行中由ACT/EXT提前结束时,控制面只冻结profile并保存待执行路径动作;HAL在下一次自然
update(端子完整下降沿)锁存硬件计数并停止PWM,再用段完成事件推进路径。不得在1 ms路径tick中
直接关闭CC1E,以免截断已经产生上升沿的末脉冲。
PlsrResult PlsrPath_Enter(PlsrAxis *axis, uint16_t segment);
PlsrResult PlsrPath_OnOutputDone(PlsrAxis *axis);
PlsrResult PlsrPath_OnExt(PlsrAxis *axis, uint32_t edge_sequence);
PlsrResult PlsrPath_PollWait(PlsrAxis *axis, uint64_t now_ms);
输出包括下一段请求、正常完成请求、停止剩余脉冲请求和段事件。
进入段
-> 检查段号
-> 计算相对位移或绝对位移
-> 位移为0:不输出并生成段事件
-> 位移非0:解析方向和目标频率
-> 启动输出/ACT/EXT监视
-> 等待脉冲完成或条件事件
-> 锁存段结束原因
-> 产生I6000~I6399对应事件
-> 求动态跳转值
-> 下一段 / WAIT / COMPLETED / ERROR
每次任务调度最多连续处理100次无脉冲跳转,达到上限后主动让出CPU,避免无限循环阻塞系统。
速度规划模块根据S2、段目标、剩余脉冲和下一段速度生成当前控制频率。TIM6提供10 kHz控制基准;
0.1 ms轴每次更新,1 ms轴每10次更新。无运行轴时关闭TIM6。
内部采用定点数:频率使用Q32.32,归一化曲线进度使用Q1.31,时间使用整数微秒,禁止在控制中断
使用浮点三角函数。
三种曲线定义为:
直线:g(u) = u
S形: g(u) = 3u² - 2u³
正弦:g(u) = (1 - cos(πu)) / 2
f(u) = f_start + (f_end - f_start) * g(u)
正弦函数使用只读查找表和线性插值。距离不足时通过有界二分求解峰值频率,自动形成三角或短距离
曲线;无法满足起止速度和脉冲数时返回参数冲突。
完成方式在当前段脉冲结束后再改变到下一段速度;后续方式在当前段内预留变速脉冲,使段边界时已达到
下一段入口速度。反向段必须先减速到0再切换方向或相序。
S2最高速度为0或超出硬件开放范围时拒绝启动。起始、目标和终止速度超过合法最高速度时限幅并发布
SPEED_CLAMPED。FOLLOW性能范围为1~100,前馈补偿范围为0~100;两者属于信捷独立
FOLLOW/FOLLOW_AB指令使用的共用S2字段。本PLSR模块保留存储、快照和范围校验,但不把它们
代入PLSR速度曲线,也不自行定义FOLLOW运算公式。
PlsrResult PlsrProfile_Prepare(
const PlsrSegmentRuntime *segment,
const PlsrS2Snapshot *s2,
PlsrProfile *profile);
void PlsrProfile_ControlTick(PlsrProfile *profile, uint32_t elapsed_us);
void PlsrProfile_SetTarget(PlsrProfile *profile, uint32_t target_hz);
输入为当前频率、目标频率、起止频率、加减速时间、曲线、剩余脉冲和衔接方式;输出为当前命令频率
和待提交的定时器分频参数。
准备段曲线
-> 校验S2和目标速度
-> 计算加速/减速所需脉冲
-> 距离足够:生成完整曲线
-> 距离不足:求解短距离峰值
-> 每0.1/1 ms推进定点曲线
-> 计算当前命令频率
-> 限幅并生成诊断
-> 计算待提交PSC/ARR/CCR
-> 脉冲模块在安全周期边界应用
运行中目标频率修改不改变剩余脉冲数。规划器在配置刷新周期内接收并开始过渡,物理周期参数在最近的
安全周期边界切换;低频时不得为了刷新指标截断一个完整脉冲。
高速输出模块使用硬件定时器维持脉冲边沿,OS不参与逐脉冲翻转。
图 3-2 PLSR高速脉冲与硬件计数架构图
| 逻辑点 | MCU引脚 | 定时器通道 | 定时器时钟 |
|---|---|---|---|
| Q0/Y0 | PF6 | TIM10_CH1 | 168 MHz |
| Q1/Y1 | PF8 | TIM13_CH1 | 84 MHz |
| Q2/Y2 | PF7 | TIM11_CH1 | 168 MHz |
| Q3/Y3 | PF9 | TIM14_CH1 | 84 MHz |
RM0090 Rev.22 第19.4.2节表101的TIM9/TIM12内部触发连接提供以下通路:
| 硬件计数器 | 触发选择 | 内部计数来源 | 对应输出 |
|---|---|---|---|
| TIM9 | ITR2 | TIM10_OC | Q0 |
| TIM9 | ITR3 | TIM11_OC | Q2 |
| TIM12 | ITR2 | TIM13_OC | Q1 |
| TIM12 | ITR3 | TIM14_OC | Q3 |
TIM9在同一时刻只能选择Q0或Q2中的一路,TIM12只能选择Q1或Q3中的一路。因此V1.0采用:
优先:TIM9/TIM12内部硬件累计
↓ 计数器不可达或已被其它轴占用
兜底:对应输出定时器的周期中断软件累计
计数方式在每段开始前确定并锁存到该段结束,不在脉冲活动期间切换。最多同时提供两套内部硬件
计数;四轴PULSE/DIR并发时,至少两轴硬件计数、其余轴软件计数。资源分配优先级依次为:
可同时硬件计数的PULSE/DIR组合为Q0+Q1、Q0+Q3、Q2+Q1或Q2+Q3。Q0与Q2竞争TIM9,
Q1与Q3竞争TIM12。
AB相每个相位通道每完整正交周期只产生一次同类内部比较事件,因此一组AB轴只需选择其中一个相位
作为周期计数基准。两组AB轴应通过匹配分配分别使用TIM9和TIM12,例如Q0/Q1轴选Q0→TIM9,
Q2/Q3轴选Q3→TIM12。
CW/CCW只对当前实际发脉冲的方向通道计数。发生方向切换时,在完全停止的段边界重新申请相应的
TIM9或TIM12;申请失败则该段切换为软件计数,不能在脉冲活动期间改源。
定时器采用向上计数和PWM输出:
f_actual = f_timer / ((PSC + 1) * (ARR + 1))
CCR1 = (ARR + 1) / 2
分频算法选择能容纳16位ARR的最小预分频,并比较相邻合法候选,取绝对频率误差最小者;误差相同时
选择更大的ARR以保留分辨率。记录目标频率、实际频率、PSC、ARR、CCR和误差。
硬件计数模式下不为每个PWM周期开启更新中断。TIM6控制刷新先短暂禁止输出定时器的更新装载,依次
写入PSC、ARR和CCR预装载值,再恢复更新装载;完整的新参数在随后自然更新事件一次性生效。若更新
边界在短暂禁止期间到达,则延后一个完整周期生效,不能出现混合分频值或截断周期。
PULSE/DIR先设置DIR,再等待默认10 ms或配置的方向建立时间,随后启动PWM。物理上升沿计1个指令
脉冲。硬件计数时由TIM9/TIM12在外部时钟模式1下累计每周期一次的内部OC事件;软件计数时由输出
定时器自然更新事件累计。进入目标脉冲时只武装一次尾边沿处理,最后一个脉冲下降沿到达后关闭通道,
防止出现下一个多余上升沿。
CW/CCW正向只启动CW端,反向只启动CCW端,另一路始终无效。检测到双通道同时活动时立即关闭配对
输出并进入ERROR。
AB相固定配对如下:
| 轴归属 | A相 | B相 | 正向状态顺序 |
|---|---|---|---|
| Y0 | Q0/TIM10 | Q1/TIM13 | 00→10→11→01→00 |
| Y2 | Q2/TIM11 | Q3/TIM14 | 00→10→11→01→00 |
反向交换A、B领先关系。两个定时器预装四分之一周期相位差;从已分配的一个相位内部OC事件累计
完整AB周期,落后相第四次跳变完成后关闭最后一周期。一个完整四状态周期只计1个指令脉冲,四次
相位跳变不得分别计数。
AB启动必须在GPIO仍持有安全低电平时完成以下顺序:停止两个定时器、强制OC无效并UG、把两个CNT
装入严格大于CCR且保持四分之一周期差的位置、使能通道、切回AF、切入PWM1后再同时开放计数。
禁止在运行中重写CNT维持相位。双AB分别以Q0→TIM9和Q3→TIM12作为完整周期计数源;到达目标前
武装落后相的00边界快速门控,并通过D1468~D1469记录该快速路径最大周期数。上述新序列和门控
代码已完成Host/IAR验证。PAUSE同样只在下一真实00边界停表,已经开始的周期计入完成数;双组
近同时完成时,ISR只快速gate并锁存,GPIO、计数器释放和事件发布延后到任务态;异常返回前再次
扫描另一组已武装的00标志,消除首轮扫描后到达的等优先级竞争。D1468取实际停表门控扫描与
返回前最终安全扫描的最大值,必须小于一个100kHz四分之一周期;整个输出ISR仍由独立ISR WCET
窗口约束。在四通道真机确认严格边沿数、
2.5us首相位间隔、变频及PAUSE/RESUME波形前仍标记为待上板验证。
TIM9和TIM12均为16位计数器。计数器配置为外部时钟模式1,ARR保持为0xFFFF,每收到一次选定的
内部OC事件,CNT自动加1。软件使用“16位硬件CNT + 64位块累计”扩展完整INT32脉冲范围:
每65536个指令脉冲
-> TIM9/TIM12产生一次更新中断
-> 软件块累计加65536
最终低16位到达比较值
-> 检查块累计是否已到目标高位
-> 是:武装最终完整脉冲/AB周期的尾边沿关闭
-> 否:清比较标志并继续硬件累计
目标低16位不为0时使用捕获比较事件判断最终余数;目标恰为65536的整数倍时,使用更新事件和块累计
判断完成,禁止把比较值0解释成启动瞬间已经完成。
100 kHz连续输出时,每个硬件计数轴的块中断频率约为100000/65536=1.53次/秒;除块中断、最终
比较和异常外,不产生逐脉冲计数中断。零脉冲段在进入硬件层前处理,绝对值计算使用64位,避免
INT32_MIN取反溢出。
TIM10/11/13/14的SMCR在寄存器表中为保留项,因此硬件计数器只能通知CPU达到目标,不能反向门控
输出定时器。最终比较事件到达后不得立即截断
活动波形,而应根据模式武装输出定时器的最终边沿:PULSE/DIR和CW/CCW在最后下降沿关闭,AB相在
第四次状态跳变后同时关闭配对通道。N=1时在启动前直接武装尾边沿。内部OC事件相位、同步延迟和
最终关闭窗口必须用逻辑分析仪确认。
四个高速定时器对应共享中断向量:
| 定时器 | 中断向量 |
|---|---|
| TIM10 | TIM1_UP_TIM10_IRQn |
| TIM11 | TIM1_TRG_COM_TIM11_IRQn |
| TIM13 | TIM8_UP_TIM13_IRQn |
| TIM14 | TIM8_TRG_COM_TIM14_IRQn |
两个硬件计数器的中断向量为:
| 计数器 | 中断向量 | 用途 |
|---|---|---|
| TIM9 | TIM1_BRK_TIM9_IRQn |
Q0/Q2硬件块计数和最终比较 |
| TIM12 | TIM8_BRK_TIM12_IRQn |
Q1/Q3硬件块计数和最终比较 |
热路径采用直接寄存器访问,不调用通用 HAL_TIM_IRQHandler()。共享中断入口先检查本定时器标志,
并为TIM1/TIM8未来用途保留分派能力。硬件计数轴关闭输出定时器的周期更新中断;软件计数轴才启用
周期更新中断。
PlsrResult PlsrHw_Init(void);
PlsrResult PlsrHw_Configure(const PlsrHwRequest *request);
PlsrResult PlsrHw_Start(uint8_t axis, uint64_t pulses);
PlsrResult PlsrHwCounter_Configure(const PlsrCounterLease *lease, uint64_t target_pulses);
void PlsrHwCounter_Stop(const PlsrCounterLease *lease);
void PlsrHw_SetPendingDivider(uint8_t axis, const PlsrDivider *divider);
void PlsrHw_RequestTailStop(uint8_t axis);
void PlsrHw_ForceSafe(uint32_t resource_mask);
输入为模式、方向、频率、脉冲数量、方向点和极性;输出为周期完成事件、实际计数、分频诊断和硬件错误。
启动硬件输出
-> 输出保持无效
-> 配置GPIO复用和安全电平
-> 装载PSC/ARR/CCR并清状态标志
-> PULSE/DIR设置方向并等待建立时间
-> AB装载配对相位 / CW选择单通道
-> 尝试申请并配置TIM9/TIM12硬件计数
成功:关闭逐周期计数中断
失败:启用输出定时器软件周期计数
-> 使能通道和定时器
-> 硬件持续输出
-> 硬件模式:每65536脉冲更新块累计
软件模式:周期ISR更新剩余量
-> TIM6通过预装载安全更新分频
-> 进入最后一个脉冲/AB周期
-> 比较事件完成尾边沿
-> 关闭输出并通知运动核心
TIM10/11/13/14没有重复计数寄存器,TIM9/TIM12内部连接又只能覆盖两路。四轴100 kHz时,若两路
硬件计数、两路软件计数,最坏约为每秒200,000次软件周期事件,加TIM6的10,000次控制事件和少量
硬件块中断。完整功能开发前必须完成两种计数模式原型,测量ISR最坏执行时间、CPU占用、计数模式
切换、USB/Modbus压力、尾脉冲和AB相位;未通过不得宣称四轴100 kHz验收完成。
每轴状态固定为:
UNINITIALIZED、IDLE、ACCEL、RUN、DECEL、WAIT、PAUSED、
COMPLETED、STOPPED、ERROR
图 3-3 PLSR单轴状态机与命令优先级图
主要合法转换如下:
| 当前状态 | 事件 | 下一状态 |
|---|---|---|
| UNINITIALIZED | 初始化成功 | IDLE |
| IDLE/COMPLETED/STOPPED | START成功 | ACCEL、RUN、WAIT或COMPLETED |
| ACCEL/RUN | 需要减速 | DECEL |
| 运动状态 | 等待条件未满足 | WAIT |
| 运动状态 | PAUSE且减速完成 | PAUSED |
| PAUSED | RESUME | ACCEL或RUN |
| 运行类状态 | 路径正常结束 | COMPLETED |
| 非终止状态 | STOP完成 | STOPPED |
| 可运行状态 | 不可恢复错误 | ERROR |
| ERROR | RESET_ERROR成功 | IDLE |
未列出的转换由统一入口拒绝并记录非法转换。DONE只在正常完成时置1,下一次START成功接受时清零;
STOP和ERROR不得置DONE。WAIT和PAUSED期间BUSY为1、PULSE_ACTIVE为0。
支持START、STOP_DECEL、STOP_IMMEDIATE、PAUSE、RESUME、SET_POSITION、CLEAR_POSITION、
CLEAR_TOTAL、SAVE_CONFIG、LOAD_CONFIG、RESET_ERROR和SELF_TEST。每轴保存最近命令序号与结果,
相同序号重发只返回上次结果,不重复执行。
PlsrResult PlsrState_Transition(
PlsrAxis *axis,
PlsrState target,
PlsrTransitionReason reason);
PlsrResult PlsrCommand_Execute(
PlsrAxis *axis,
const PlsrCommand *command);
收到命令
-> 比较命令序号
-> 重复序号:返回上次结果
-> 检查当前状态是否允许
-> 按命令执行动作
-> 通过唯一状态转换入口改变状态
-> 保存序号、结果和停止原因
-> 发布BUSY/PULSE_ACTIVE/DONE/WAIT/ERROR
事件优先级固定为:软件急停 > 硬限位 > STOP_IMMEDIATE > STOP_DECEL > PAUSE > 正常运行。
高优先级原因锁存后,低优先级命令不得覆盖。
资源管理器维护高速资源Q0~Q3、普通输出资源Q0~Q7/Q10~Q17/Q20,以及内部硬件计数器
TIM9/TIM12的占用位图。高速输出和DIR资源属于运动必需资源;硬件计数器属于优化资源,申请失败时
允许使用软件计数兜底。
| 模式 | D允许值 | 高速资源 | DIR资源 |
|---|---|---|---|
| PULSE/DIR | Y0~Y3 | D对应的一个Q点 | 一个未占用有效输出点 |
| AB相 | Y0或Y2 | Q0/Q1或Q2/Q3 | 无 |
| CW/CCW | Y0或Y2 | Q0/Q1或Q2/Q3 | 无 |
硬件计数资源规则:
| 脉冲来源 | 可申请计数器 | 冲突组 |
|---|---|---|
| Q0/TIM10 | TIM9 ITR2 | 与Q2互斥 |
| Q2/TIM11 | TIM9 ITR3 | 与Q0互斥 |
| Q1/TIM13 | TIM12 ITR2 | 与Q3互斥 |
| Q3/TIM14 | TIM12 ITR3 | 与Q1互斥 |
单轴或两轴运行时优先选择能全部硬件计数的组合。四轴运行时,资源管理器分别从Q0/Q2组和Q1/Q3组
选择一个轴使用硬件计数。既有运行租约不被抢占;同批竞争时按AB模式、预计中断负载和提交顺序选择。
计数器租约只在段停止边界申请或释放;任务运行期间如果某段不能获得计数器,则该段使用软件计数。
方向点板级映射如下:
| PLC点 | MCU引脚 | PLC点 | MCU引脚 |
|---|---|---|---|
| Q0 | PF6 | Q10 | PG7 |
| Q1 | PF8 | Q11 | PG6 |
| Q2 | PF7 | Q12 | PH9 |
| Q3 | PF9 | Q13 | PH8 |
| Q4 | PI8 | Q14 | PH7 |
| Q5 | PE6 | Q15 | PH6 |
| Q6 | PE5 | Q16 | PF11 |
| Q7 | PE4 | Q17 | PB0 |
| Q20 | PH5 |
完整申请掩码在短临界区内一次判断和占用,禁止逐点申请后失败而留下半组资源。运行期间模式、D、
配对关系、方向点和极性锁定。正常完成、STOP和ERROR统一通过幂等清理入口释放资源。
PlsrResult PlsrResource_Reserve(
uint8_t owner_axis,
const PlsrResourceRequest *request,
PlsrResourceLease *lease);
void PlsrResource_Release(PlsrResourceLease *lease);
PlsrCountMode PlsrResource_SelectCounter(
uint8_t owner_axis,
uint8_t pulse_source,
PlsrCounterLease *counter_lease);
构造完整资源掩码
-> 检查模式与D
-> 检查高速点和DIR点合法性
-> 进入短临界区
-> 任一冲突:退出并返回RESOURCE_CONFLICT
-> 无冲突:一次性占用全部资源
-> 尝试申请TIM9/TIM12计数优化资源
成功:锁存硬件计数租约
失败:锁存软件计数模式
-> 配置硬件
-> 配置失败:安全关闭并回滚
-> 任务终止:安全关闭并幂等释放
HSD、SFD、SM、SD、I、S0和S1是逻辑软元件命名空间,不等同于“Modbus通信地址表”。
PLSR内核通过统一设备接口访问逻辑软元件,Modbus只负责字节序、影子写入、命令序号和提交响应。
固定地址只采用 PLSR地址映射.md:
| 类别 | 固定范围 |
|---|---|
| K0配置 | HSD460~539 |
| 公共参数及K1~K4 | SFD900~1419 |
| 累计状态 | HSD0~15 |
| 运行/方向标志 | SM1000/1001、1020/1021、1040/1041、1060/1061 |
| 实时状态 | SD1000~1011、1020~1031、1040~1051、1060~1071 |
| 段事件 | I6000~6399 |
| 动态数据 | S0、S1 |
固定字段使用显式描述表保存地址、位宽、有符号性、读写属性、合法范围、所属轴和持久化类别,不得通过
自拟轴块改变信捷地址。保留字段仍占原地址,未实现字段不得挪作项目扩展。
32/64位状态采用版本化快照发布。Modbus断开不产生STOP;非法通信参数不得改变正在运行的任务。
本设计书不新增PLSR全局通信地址区,也不恢复已删除的Modbus历史功能。
Modbus数据存储提供相互隔离的X、M、HM三套10000位映像。FC01/FC05/FC0F访问M,FC02只读访问X;
PlsrModbusDataSourceInit()把PLSR readBit连接到对应映像。依据《实现PLSR指令.pdf》已建立
X0~X12、X14~X17、X20 的 GPIO 输入扫描映射;X13/PA14 因承担 SWDCLK,在调试构建中保留不用。
P19 初测由 Y4~Y7 回接 X0~X3;为同步观察 Y0 脉冲与四路触发,当前验证夹具改为 Y1~Y4
回接 X0~X3。真实 WAIT、EXT 和正/负硬限位链路已关闭。HM 映像尚未接入经板测的
保持介质,因此 HM 掉电保持不得宣称关闭。
bool PlsrDevice_Read(DeviceRef ref, int64_t *value);
bool PlsrDevice_Write(DeviceRef ref, int64_t value);
bool PlsrDevice_ReadBlock(DeviceRef first, uint16_t words, uint16_t *buffer);
void PlsrDevice_PublishAxis(uint8_t axis, const PlsrStatus *status);
void PlsrDevice_TriggerSegmentEvent(uint8_t axis, uint16_t segment);
外部读写请求
-> 解析逻辑软元件类型和地址
-> 检查位宽、权限和范围
-> 参数写入影子区
-> COMMIT时调用PLSR业务校验
-> 成功:切换版本并返回序号/结果
-> 失败:保持原有效参数
状态读取
-> 读取版本号
-> 复制完整状态
-> 再读版本号
-> 前后相同且为稳定版本:返回
-> 否则重试
每轴内部维护64位逻辑位置、本次任务累计、总累计和物理输出诊断计数,以及独立的
position_valid。高速ISR只更新当前块计数;任务在块边界、段边界或检查点时合并64位数据。
发布HSD固定32位累计前检查INT32范围。超出范围时保持最近合法发布值,锁存
COUNTER_OVERFLOW,不得回绕或静默截断。HSD记录只有一个全局位置有效元数据位,因此检查点按
四轴position_valid且无发布溢出的保守AND写入;单独校准一轴不得把其他未校准轴一起标为可信,
任何轴超出32位发布范围时也不得让旧HSD位置在重启后冒充当前可信坐标。
当量换算按每转指令脉冲数和每转移动量形成有理数比例,计算前约分并检查溢出,每轴保存换算余数,
避免连续多段累计舍入漂移。任一分母为0时返回兼容错误码2。
软限位按逻辑位置和预计停止距离判断:禁止向越界方向启动,允许运动离开已触发限位;运动中触发默认
减速停止。方向反转时插入内部齿隙补偿子段,补偿脉冲不计入用户段、逻辑位置或HSD,但计入物理输出
诊断。
固定配置使用Flash A/B双槽:
magic | format_version | payload_length | sequence | payload | CRC32
动态K0、64位位置、累计、有效标志和最近诊断保存到有VBAT维持的Backup SRAM双检查点。
正常完成、正常停止、设置/清零位置和清累计后立即保存;运行中初始按10 ms及段边界保存诊断检查点。
异常复位或上次BUSY时清除 position_valid,任何情况都不自动恢复未完成路径。
PlsrResult PlsrPosition_Set(uint8_t axis, int64_t position);
PlsrResult PlsrPosition_Clear(uint8_t axis);
PlsrResult PlsrPosition_ConvertToPulse(uint8_t axis, int64_t value, int64_t *pulse);
PlsrResult PlsrPersist_SaveConfig(void);
PlsrResult PlsrPersist_LoadConfig(void);
void PlsrPersist_SaveCheckpoint(uint32_t reason);
脉冲块完成
-> 原子交换当前块计数
-> 检查64位加法溢出
-> 更新逻辑位置和累计
-> 检查软限位
-> 检查HSD32位发布范围
-> 更新状态快照
-> 达到检查点条件:更新Backup SRAM
上电恢复
-> 输出保持安全
-> 读取复位原因
-> 校验Flash和Backup SRAM版本/CRC
-> 恢复允许的配置与诊断
-> 异常复位或上次BUSY:清position_valid
-> 清全部运行资源
-> 禁止自动启动
诊断模块记录每轴目标/实际频率、PSC/ARR/CCR、当前计数模式、TIM9/TIM12块累计、软件脉冲数、
物理边沿诊断值、当前段、停止原因、状态机非法转换、资源冲突和ISR执行周期。
P16诊断协议V7使用D1256~D1263发布整体/ISR最大周期,D1456~D1467发布六个任务阶段独立最大值,
D1468~D1469发布AB末周期快速门控最大值,D1470~D1515发布缓存的持久化诊断与受控验证应答,
D1516~D1537使用首尾generation发布USB CDC initialized及八个32位收发/错误统计。
Modbus只读功能码0x47提供40 WORD运行诊断;各32位字段不会撕裂,整组字段允许跨相邻通信事件;
USB CDC另记录收发、BUSY、失败和重挂统计。USB OTG FS优先级为4,长稳脚本可并发施加Modbus轮询、
原子动态频率写入、坏CRC、计划断线及可选USB OUT流量。
SELF_TEST 分为两级:
void PlsrDiag_RecordError(uint8_t axis, PlsrError error, const PlsrErrorDetail *detail);
void PlsrDiag_RecordDivider(uint8_t axis, const PlsrDivider *divider);
void PlsrDiag_RecordIsrCycles(uint8_t axis, uint32_t cycles);
PlsrResult PlsrDiag_SelfTest(uint32_t test_mask, bool allow_output);
收到SELF_TEST
-> 检查所有轴非BUSY
-> 执行静态地址和配置检查
-> 执行分频、路径、计数和状态机检查
-> 是否请求输出测试
否:汇总结果
是:检查显式授权和安全条件
-> 输出受限测试波形
-> 自动安全关闭
-> 发布逐项结果和首个失败原因
typedef enum {
PLSR_STATE_UNINITIALIZED,
PLSR_STATE_IDLE,
PLSR_STATE_ACCEL,
PLSR_STATE_RUN,
PLSR_STATE_DECEL,
PLSR_STATE_WAIT,
PLSR_STATE_PAUSED,
PLSR_STATE_COMPLETED,
PLSR_STATE_STOPPED,
PLSR_STATE_ERROR
} PlsrState;
typedef enum {
PLSR_OUTPUT_PULSE_DIR = 0,
PLSR_OUTPUT_AB = 1,
PLSR_OUTPUT_CW_CCW = 2
} PlsrOutputMode;
typedef enum {
PLSR_POSITION_RELATIVE = 0,
PLSR_POSITION_ABSOLUTE = 1
} PlsrPositionMode;
typedef enum {
PLSR_COUNT_SOFTWARE = 0,
PLSR_COUNT_TIM9 = 1,
PLSR_COUNT_TIM12 = 2
} PlsrCountMode;
typedef struct {
DeviceRef s0;
DeviceRef s1;
DeviceRef s2;
uint8_t d_axis;
} PlsrCall;
typedef struct {
uint32_t sequence;
uint16_t axis;
uint16_t opcode;
int64_t argument;
} PlsrCommand;
typedef struct {
uint32_t target_frequency_hz;
int32_t pulse_or_position;
uint16_t wait_word;
int32_t wait_argument;
uint16_t jump_word;
int32_t jump_argument;
} PlsrSegmentSnapshot;
四轴各保留最多100段的紧凑快照。快照同时保存当前段频率源地址,专供受控动态调频;其它字段不得
通过源地址重新读取。
typedef struct {
uint16_t segment_count;
uint16_t start_segment;
PlsrPositionMode position_mode;
PlsrOutputMode output_mode;
uint8_t d_axis;
PlsrS2Snapshot s2;
PlsrResourceLease resources;
PlsrSegmentSnapshot segments[PLSR_MAX_SEGMENTS];
} PlsrJobSnapshot;
硬件计数租约作为输出资源租约的一部分:
typedef struct {
PlsrCountMode mode;
uint8_t owner_axis;
uint8_t pulse_source;
uint8_t trigger_select;
bool valid;
} PlsrCounterLease;
TIM9和TIM12各只能存在一个有效租约。软件计数模式不占用硬件计数租约。
typedef struct {
PlsrState state;
PlsrJobSnapshot job;
PlsrSegmentRuntime segment;
PlsrProfile profile;
PlsrPulseFastContext pulse_fast;
int64_t logical_position;
int64_t task_pulses;
int64_t total_pulses;
uint64_t physical_edges;
bool position_valid;
uint32_t event_flags;
uint32_t event_sequence;
uint32_t last_command_sequence;
PlsrCommandResult last_command_result;
PlsrError error;
PlsrStatusPublish publish;
} PlsrAxis;
typedef struct {
volatile uint32_t remaining_in_block;
volatile uint32_t completed_in_block;
volatile uint32_t hardware_wrap_count;
volatile uint32_t pending_event;
volatile uint8_t divider_pending;
volatile uint8_t tail_stop_armed;
PlsrCountMode count_mode;
uint8_t pulse_source;
uint16_t final_compare;
uint64_t target_pulses;
PlsrDivider active_divider;
PlsrDivider pending_divider;
} PlsrPulseFastContext;
硬件计数模式下,hardware_wrap_count与TIM9/TIM12当前CNT组成完整累计;软件计数模式下使用
remaining_in_block逐周期递减。count_mode在段活动期间只读,只有输出完全停止后才允许改变。
快速上下文只保存ISR固定时间内需要的数据,不放置S0数组、Flash缓存和复杂状态对象。
typedef struct {
uint32_t version;
PlsrState state;
uint16_t current_segment;
uint16_t total_segments;
int8_t direction;
uint8_t busy;
uint8_t pulse_active;
uint8_t done;
uint32_t command_frequency_hz;
uint32_t actual_frequency_hz;
PlsrCountMode count_mode;
uint32_t hardware_counter_value;
int64_t segment_sent;
int64_t segment_remaining;
int64_t logical_position;
int64_t task_pulses;
int64_t total_pulses;
PlsrError error;
uint32_t stop_reason;
uint32_t version_end;
} PlsrStatus;
typedef struct {
PlsrDeviceType type;
uint16_t address;
uint8_t width_words;
uint8_t axis;
uint8_t access;
uint8_t persistence;
int64_t minimum;
int64_t maximum;
} PlsrDeviceDescriptor;
描述表必须覆盖HSD460~539、SFD900~1419、HSD0~15、固定SM、固定SD和I6000~6399,
并通过静态断言检查重复地址、位宽和轴归属。
图 4-1 PLSR数据流关系图
图中蓝色表示配置和运动数据,橙色表示硬实时数据及中断事件,绿色表示持久化数据,紫色表示命令与
状态接口。为方便纯文本环境阅读,保留如下简化关系。
S0/S1/S2/D逻辑软元件
|
v
PlsrParser_BuildSnapshot
|
v
PlsrJobSnapshot ----------> PlsrPath / PlsrProfile
| |
v v
PlsrAxis状态机 <---------- ISR事件和块计数
|
+----> PlsrStatusPublish ----> HSD/SM/SD/I与Modbus读取
|
+----> Flash / Backup SRAM检查点
| 数据 | 唯一写者 | 读取者 | 一致性方法 |
|---|---|---|---|
| ISR快速计数 | TIM9/TIM12块ISR或输出定时器兜底ISR | TIM6 ISR、PlsrTask | 计数模式锁存、32位原子交换 |
| 速度规划状态 | TIM6 ISR | 脉冲ISR、PlsrTask | 待提交双缓冲 |
| 状态机和路径游标 | PlsrTask | 状态发布 | 单写者 |
| 输出资源位图 | 资源管理器 | PlsrTask、诊断 | 短临界区 |
| 64位位置累计 | PlsrTask | 状态读取、保存 | 顺序锁/短临界区 |
| 对外状态影子 | 状态发布器 | Modbus、内部API | 版本号前后校验 |
| 固定配置镜像 | 参数模块 | 保存和设备访问 | 影子+COMMIT |
通信层禁止直接写 PlsrAxis。volatile只保证访问可见性,不代替原子性、临界区和内存屏障。
每轴使用32位事件字:
bit0 PULSE_BLOCK_DONE
bit1 SEGMENT_OUTPUT_DONE
bit2 LIMIT_POSITIVE
bit3 LIMIT_NEGATIVE
bit4 EXT_RISING
bit5 STOP_IMMEDIATE_DONE
bit6 TIMER_FAULT
bit7 COUNTER_FAULT
bit8 HW_COUNTER_WRAP
bit9 HW_COUNTER_TARGET
可合并事件采用原子置位;不能丢失的段事件另带单调递增序号。临界区内禁止遍历100段、除法、CRC、
Flash操作或通信发送,并使用DWT周期计数器测量最坏执行时间。
| 轴 | HSD累计 | SM标志 | SD实时状态 | 段事件 |
|---|---|---|---|---|
| Y0 | HSD0~3 | SM1000、SM1001 | SD1000~1011 | I6000~6099 |
| Y1 | HSD4~7 | SM1020、SM1021 | SD1020~1031 | I6100~6199 |
| Y2 | HSD8~11 | SM1040、SM1041 | SD1040~1051 | I6200~6299 |
| Y3 | HSD12~15 | SM1060、SM1061 | SD1060~1071 | I6300~6399 |
双字采用低地址低16位、下一地址高16位。第N段事件使用轴事件基址加 N-1,跳转目标不得改变原段
事件地址。
| 层级 | 示例 | 处理 |
|---|---|---|
| 告警 | SPEED_CLAMPED |
记录并继续运行 |
| 启动拒绝 | 参数越界、资源冲突、位置无效 | 不启动、不占资源、不破坏其它轴 |
| 轴错误 | 计数异常、定时器异常、动态跳转越界 | 安全停止该轴、释放资源并锁存ERROR |
| 全局严重错误 | HardFault、共享数据破坏 | 关闭全部高速输出并锁存全局故障 |
错误处理统一遵循:先禁止新脉冲,再锁存原因,再发布状态,最后在任务上下文执行资源释放和允许的
检查点保存。错误清除只回到IDLE,不自动恢复未完成任务。
以下时机调用统一 PlsrHw_ForceSafe():
安全关闭直接关闭TIM10/11/13/14通道和计数器,并把相关GPIO恢复为配置的安全无效电平。
故障处理函数不得写Flash。
| 编号 | 风险 | 处理及关闭条件 |
|---|---|---|
| RISK-01 | 四轴100 kHz仍有两轴可能采用软件计数,最坏约200k周期事件/秒 | 分别验证两硬件+两软件计数组合,记录ISR最坏周期、CPU占用和通信压力结果 |
| RISK-02 | TIM9/TIM12只能累计,不能反向自动关闭输出源 | 最终比较只武装尾边沿,逐数量边界验证无额外或窄脉冲 |
| RISK-03 | AB配对定时器时钟分别为168/84 MHz | 全频段测量两组AB频率、相位及方向 |
| RISK-04 | USB中断可能抢占运动实时路径 | 优先级已降为4;完成USB/Modbus/四轴长稳压力后关闭 |
| RISK-05 | 输出电路极性和可靠带宽待实测 | 测量Q0~Q3带载波形后冻结参数 |
| RISK-06 | 0.1 ms曲线计算量 | 定点化和预计算,DWT实测最坏执行时间小于周期预算 |
| RISK-07 | 16位通信写入造成32位动态频率撕裂 | 使用影子+COMMIT版本和内核二次校验 |
| RISK-08 | Backup SRAM不能保证掉电瞬间零误差 | 异常复位清position_valid,并记录恢复等级 |
| RISK-09 | 现有历史写入破坏S0/S1数据 | 删除历史写入并完成全地址越界测试 |
| RISK-10 | 信捷保留字段被扩展复用 | 固定描述表、静态断言和对标矩阵评审 |
| RISK-11 | 将共用S2字段误当作PLSR的FOLLOW运算 | 已关闭:FOLLOW/FOLLOW_AB按信捷手册属于独立指令,不在PLSR V1.0执行范围 |
| RISK-12 | TIM9/TIM12内部OC事件相位和跨时钟域同步延迟 | 测量Q0~Q3的计数对应边沿、首脉冲、末脉冲和动态调频后累计一致性 |
截至2026-08-10,P14端子实测Q0~Q3均为100kHz且各严格200000个上升沿;P16实测
PlsrProcess自身最大53748 cycles(319.929us)、响应最大85655 cycles,P14/P16已关闭。P15四轴
软限位矩阵亦已板测通过。双AB安全首沿/双计数器/00边界PAUSE/D1468完整快速窗口、0x47及
D1516~D1537 USB自动诊断、P18/K4长稳夹具和持久化分阶段掉电工具属于代码完成、Host/IAR已通过
但最终板测未关闭项;真实 X0~X3 GPIO 链已由 P19 回环板测关闭,HM保持介质仍待硬件定义。上述新批次落盘后必须重跑
P14/P15/P16回归,不能用修改前的通过记录替代发布回归。
| 兼容码 | 含义 | 处理 |
|---|---|---|
| 1 | 脉冲数据段配置错误 | 拒绝启动,错误块号写SD的B+11 |
| 2 | 每转脉冲数或每转移动量为0 | 拒绝启动 |
| 3 | S2参数块号错误 | 拒绝启动 |
| 4 | 脉冲参数块号或范围错误 | 拒绝启动 |
| 5 | 正限位触发 | 减速停止并禁止继续正向启动 |
| 6 | 负限位触发 | 减速停止并禁止继续反向启动 |
| 15 | FOLLOW性能不在1~100 | 拒绝启动 |
| 16 | FOLLOW前馈不在0~100 | 拒绝启动 |
| 26 | 控制块或高速资源分配失败 | 拒绝启动或进入ERROR |
| 错误 | 含义 | 级别 |
|---|---|---|
DEFAULT_SPEED_INVALID |
段频率0但S2默认速度非法 | 启动拒绝/轴错误 |
SEGMENT_OVERFLOW |
路径段数超过100 | 启动拒绝 |
OUTPUT_MODE_INVALID |
输出模式或D组合非法 | 启动拒绝 |
RESOURCE_CONFLICT |
脉冲点或DIR点冲突 | 启动拒绝 |
PARAMETER_LOCKED |
运行中修改锁定参数 | 写入拒绝 |
DONE_STATE_ERROR |
DONE状态转换异常 | 轴错误 |
SPEED_CLAMPED |
速度被S2最高速度限幅 | 告警 |
POSITION_INVALID |
绝对定位前位置无效 | 启动拒绝 |
COUNTER_OVERFLOW |
内部或兼容累计溢出 | 轴错误 |
ILLEGAL_TRANSITION |
非法状态机转换 | 轴错误 |
TIMER_FAULT |
定时器初始化或运行异常 | 轴/全局错误 |
PULSE_COUNT_MISMATCH |
软件计数与诊断计数不一致 | 轴错误 |
HW_COUNTER_FAULT |
TIM9/TIM12计数器意外停止、越权或累计不一致 | 轴错误 |
HW_COUNTER_FALLBACK |
硬件计数器不可用,当前段使用软件计数 | 诊断提示,不终止任务 |
typedef struct {
PlsrError error;
uint16_t compatible_code;
uint8_t axis;
uint16_t segment;
uint16_t bad_block;
uint32_t command_sequence;
uint32_t stop_reason;
uint32_t detail_a;
uint32_t detail_b;
uint64_t timestamp;
} PlsrErrorDetail;
错误信息通过增强状态接口发布;兼容码和错误块号同时写入固定SD字段。相同错误重复发生可增加计数,
但不得覆盖更高优先级停止原因。
| 验证阶段 | 内容 | 合格条件 |
|---|---|---|
| V1 | Q0~Q3固定频率与安全电平 | 引脚、极性、频率、占空比正确 |
| V2 | TIM9/TIM12单轴硬件计数及软件兜底计数 | 两种模式数量误差均为0,无窄脉冲和多余边沿 |
| V3 | 四轴100 kHz并发,两硬件计数+两软件计数 | 计数误差0,轴间无串扰,CPU和ISR数据可接受 |
| V4 | 两组AB及CW/CCW | 计数器分配、相序、周期、互斥和数量正确 |
| V5 | 0.1/1 ms曲线与调频 | 响应、曲线和段边界正确 |
| V6 | 多段、等待、跳转和事件 | 与S0语义一致 |
| V7 | STOP、PAUSE、限位和错误 | 优先级、尾脉冲和终态正确 |
| V8 | Modbus/USB压力及长稳 | 不影响脉冲和状态一致性 |
| V9 | Flash、Backup SRAM和复位 | CRC有效、不自动续跑、位置有效性正确 |
测试记录应包含固件版本、参数快照、接线、测量设备、原始波形、实际边沿数、方向建立时间、AB相位、
ISR平均/最坏周期、CPU占用和结论。
Core、Modbus、Middlewares、USB_DEVICE 和 EWARM 目录