- PlsrHwStartPwmTimer 补配 CCMR1.OC1M=PWM模式1:裸定时器复位为冻结模式, 通道输出恒定电平(上板实测 PF6 无方波,仅一段 672ms 恒高) - ARR/CCR 使能预装载(ARPE/OC1PE)+ 启动时 EGR.UG 加载影子寄存器: 运行中调频不再因 CNT 超调提前回绕,加速段多余脉冲消除(7517→7500) - 方向延时仅在方向变化时生效(首次/换向/换方向点), 段间同向衔接由 14.9ms 缩短至 ~2ms - 上电自测扩展为 3 段(2000Hz/1000 脉冲、5000Hz/6000、1000Hz/500), 上电延时 1s 后启动,顺带验证段间跳转 - 新增波形分析脚本(破译 16bit/CH0/100MS/s 导出格式 + 时频曲线拟合), 实测三段总脉冲 7500,与理论完全一致 已知遗留(不影响脉冲计数与位置精度,留待 P4 上板调试): - 段尾 profile DONE 后冻结频率收尾(段3 尾部 150Hz 平台 38 脉冲) - 段首第一周期被压缩(首脉冲占空比异常)deepseek
| @@ -200,9 +200,9 @@ int main(void) | |||||
| Error_Handler(); | Error_Handler(); | ||||
| } | } | ||||
| /* 上电自测:Q0 发一段测试脉冲(验证后删除)。 */ | |||||
| /* 上电自测:延时 1s 待电源/外设稳定后,Q0 发一段测试脉冲(验证后删除)。 */ | |||||
| HAL_Delay(1000U); | |||||
| (void)PlsrSelfTestQueue(); | (void)PlsrSelfTestQueue(); | ||||
| OSStart(); | OSStart(); | ||||
| /* USER CODE END 2 */ | /* USER CODE END 2 */ | ||||
| @@ -0,0 +1,826 @@ | |||||
| ===== PDF page 162 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 152 | |||||
| 1-4.输出端子接线及注意事项 | |||||
| Y0 | |||||
| COM0 | |||||
| Y1 | |||||
| COM1 | |||||
| Y2 | |||||
| COM2 | |||||
| 下面是 T 型输出端子与步进电机驱动器的接线示意图: | |||||
| PLC侧 步进电机驱动侧 | |||||
| Y0 | |||||
| PU | |||||
| PU | |||||
| Y1 | |||||
| 【注】:如果步进电机脉冲和方向端子是 DC5V驱动,请在脉冲输出端子和方向输出端子后接2.2K电阻。 | |||||
| 下面是 T 型输出端子与信捷伺服电机驱动器的接线示意图: | |||||
| 【注】 :请将 P+5V和 D+5V悬空。 | |||||
| 下面是差分型输出端子与伺服驱动器的接线示意图: | |||||
| 详细的硬件接线图请参考《XD/XL系列可编程控制器用户手册【硬件篇】 》 。 | |||||
| COM0 | |||||
| Y0 | |||||
| +24V | |||||
| P- | |||||
| R=3.3K | |||||
| COM1 | |||||
| Y1 D- | |||||
| R=3.3K | |||||
| P+5V | |||||
| D+5V | |||||
| 屏蔽层0V | |||||
| D+24V | |||||
| P+24V | |||||
| Y0+ | |||||
| 双绞线 | |||||
| Y0- | |||||
| COM | |||||
| Y1+ | |||||
| Y1- | |||||
| A+ | |||||
| A- | |||||
| FG | |||||
| B+ | |||||
| B- | |||||
| Y0 | |||||
| Y1 | |||||
| PLC侧-差分输出端 负载端 | |||||
| X0+ | |||||
| X0- | |||||
| COM | |||||
| X1+ | |||||
| X1- | |||||
| 双绞线 | |||||
| A+ | |||||
| A- | |||||
| FG | |||||
| B+ | |||||
| B- | |||||
| 编码器端 | |||||
| A | |||||
| B | |||||
| PLC侧-差分输入端 | |||||
| X0+ | |||||
| X0- | |||||
| X1+ | |||||
| X1- | |||||
| PLC侧-差分输入端 | |||||
| + | |||||
| -5VDC | |||||
| NPN型 | |||||
| PNP型 | |||||
| X0+ | |||||
| X0- | |||||
| X1+ | |||||
| X1- | |||||
| PLC侧-差分输入端 | |||||
| NPN型 | |||||
| PNP型 | |||||
| 3KΩ/0.5W | |||||
| 3KΩ/0.5W | |||||
| NPN传感器 | |||||
| PNP传感器 | |||||
| + | |||||
| -24VDC | |||||
| NPN传感器 | |||||
| PNP传感器 | |||||
| 输出端口 Y0:脉冲输出口 1(单相) | |||||
| 输出端口 Y1:脉冲输出口 2(单相) | |||||
| ===== PDF page 163 ===== | |||||
| XD/XL系列可编程控制器用户手册[定位控制篇] 1.脉冲输出 | |||||
| 153 | |||||
| 1-4-1.连接设备的构成 | |||||
| 1)XD系列T型输出PLC | |||||
| 晶体管输出 | |||||
| ※:可控制 2~10 轴伺服电机或者步进电机。 | |||||
| 2)XL系列T型输出PLC | |||||
| 晶体管输出 | |||||
| ※:可控制 2~10 轴伺服电机或者步进电机。 | |||||
| 伺服电机或者 | |||||
| 步进电机 | |||||
| 伺服电机或者 | |||||
| 步进电机 | |||||
| ===== PDF page 164 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 154 | |||||
| 1-4-2.脉冲输出性能规格 | |||||
| 脉冲输出性能规格如下表所示: | |||||
| 机型 T、RT | |||||
| 型 T4 型 T6型 T10 型 D4T4型 D2T2型 XDH XLH | |||||
| 控制轴数 独立 | |||||
| 2 轴 | |||||
| 独立 | |||||
| 4轴 | |||||
| 独立 | |||||
| 6 轴 | |||||
| 独立 | |||||
| 10轴 | |||||
| 独立 | |||||
| 8 轴 | |||||
| 独立 | |||||
| 4 轴 | |||||
| 独立 | |||||
| 4 轴 | |||||
| 独立 | |||||
| 4 轴 | |||||
| 插补功能 不支持 | |||||
| 仅 | |||||
| XDM/XDME | |||||
| /XLME 支持 | |||||
| 不支持 | |||||
| 仅 | |||||
| XDM/XDME | |||||
| /XLME 支持 | |||||
| 不支持 支持 | |||||
| 输出方式 OC OC、差分 OC | |||||
| 输出形式 脉冲+方向 | |||||
| 最大频率 100KHz OC:100KHz | |||||
| 差分:920KHz 100KHz | |||||
| 加减速处理 直线加减速+S型曲线加减速+正弦曲线加减速 | |||||
| 控制单位 脉冲、1mm、0.1mm、0.01mm、1um | |||||
| 定位范围 -2147483648~2147483647(脉冲) | |||||
| 编程语言 梯形图 | |||||
| 手脉连接 不支持 | |||||
| 仅 | |||||
| XDM/XDME | |||||
| /XLME 支持 | |||||
| 不支持 | |||||
| 仅 | |||||
| XDM/XDME | |||||
| /XLME 支持 | |||||
| 不支持 支持 | |||||
| 【注】 : | |||||
| (1)所有 XD/XL系列 PLC的脉冲输出必须为晶体管或差分输出类型,否则无法发送脉冲! | |||||
| (2)PLC 可以输出 100KHz~200KHz的高速脉冲(XD3-24T4/32T4 的 Y2、Y3 为 10KHz),但不能保证 | |||||
| 所有伺服都正常运行,请在输出端和 24V电源之间接入约 500Ω电阻,电阻功率需>2W。 | |||||
| 1-4-3.定位控制接线以及布线注意事项 | |||||
| >>>>> 设计注意事项 <<<<< | |||||
| 危险! | |||||
| 请在可编程控制器的外部设置安全回路,以便在出现外部电源异常、可编程控制器故障等情况 | |||||
| 时,也能确保整个系统在安全状态下运行。误动作、误输出有可能会导致事故发生。 | |||||
| 1. 请务必在可编程控制器的外部设置紧急停止回路、保护回路、防止正反转等相反动作同时进行的互 | |||||
| 锁回路、定位上下限等防止机械破损的互锁回路等。 | |||||
| 2. 当可编程控制器 CPU 通过看门狗定时器出错等的自诊断功能检测出异常时,所有的输出变为OFF。 | |||||
| 此外,当发生了可编程控制器 CPU 不能检测出的输入输出控制部分等的异常时,输出控制有时候会 | |||||
| 失效。 | |||||
| 此时,请设计外部回路以及结构,以确保机械在安全状态下运行。 | |||||
| 3. 由于输出单元的继电器、晶体管、晶闸管等的故障,有时候会导致输出一直接通,或是一直断开。 | |||||
| 为了确保机械在安全状态下运行,请为可能导致重大事故的输出信号设计外部回路以及结构。 | |||||
| 注意! | |||||
| 1. 控制线请勿与主回路或动力线等捆在一起接线,或是靠近接线。 | |||||
| ===== PDF page 165 ===== | |||||
| XD/XL系列可编程控制器用户手册[定位控制篇] 1.脉冲输出 | |||||
| 155 | |||||
| 原则上请离开100mm以上或者远离主回路。否则会因噪音引起误动作。 | |||||
| 2. 使用时,请确保内置编程接口、电源连接器、输入输出连接器不受外力。 | |||||
| 否则会导致断线以及故障。 | |||||
| >>>>> 接线注意事项 <<<<< | |||||
| 危险! | |||||
| 1. 进行安装、接线等作业时, 请务必在外部将所有电源均断开后方可进行操作。 | |||||
| 否则有触电、产品损坏的危险。 | |||||
| 2. 在安装、接线等作业后执行上电运行时,请务必在产品上安装附带的接线端子盖板。 | |||||
| 否则有触电的危险性。 | |||||
| 注意! | |||||
| 1. AC 电源的配线请与基本单元手册记载的专用端子连接。 | |||||
| 如果将AC电源连接到直流的输出输入端子及DC电源端子,可编程控制器将被烧毁。 | |||||
| 2. DC 电源的配线请与基本单元手册记载的专用端子连接。 | |||||
| 如果将AC电源连接到直流的输出输入端子及DC电源端子,可编程控制器将被烧毁。 | |||||
| 3. 请不要在外部对空端子进行配线。 | |||||
| 有可能会损坏产品。 | |||||
| 4. XD/XL 系列基本单元的接地端子请使用2mm | |||||
| 2 | |||||
| 以上的电线进行D种接地(接地电阻:100Ω以下)。 | |||||
| 但是,请勿与强电流共同接地(参照XD/XL系列可编程控制器用户手册【硬件篇】)。 | |||||
| 5. 在进行螺栓孔加工及配线作业时, 请不要将切屑及电线屑落入可编程控制器的通风孔内。 | |||||
| 否则有可能导致火灾、故障及误动作。 | |||||
| 6. 使用时,请确保输入输出连接器不受外力。 | |||||
| 否则会导致断线以及故障。 | |||||
| 7. 输入输出电缆请牢固地安装在所规定的连接器上。 | |||||
| 接触不良会导致误动作。 | |||||
| 8. 对 XD/XL 系列基本单元以及XD/XL 系列扩展设备的端子排型产品进行接线时,请遵照以下的注意事 | |||||
| 项操作。 | |||||
| 否则有可能导致触电、故障、短路、断线、误动作、损坏产品。 | |||||
| --请依据手册中记载的尺寸对电线的末端进行处理。 | |||||
| --紧固扭矩请依照手册中记载的扭矩。 | |||||
| >>>>> 启动维护保养时的注意事项 <<<<< | |||||
| 危险! | |||||
| 1. 在通电时请勿触碰到端子。 | |||||
| 否则有触电的危险性,并且有可能引起误动作。 | |||||
| 2. 进行清扫以及拧紧接线端子时,请务必在断开所有外部电源后方可操作。 | |||||
| 如果在通电的状态下进行操作,则有触电的危险。 | |||||
| 3. 要在运行过程中更改程序、执行强制输出、RUN、STOP等操作前,请务必先熟读手册,在充分确认安 | |||||
| 全的情况下方可进行操作。 | |||||
| 操作错误有可能导致机械破损及事故发生。 | |||||
| ===== PDF page 166 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 156 | |||||
| 注意! | |||||
| 1. 请勿擅自拆解、改动产品。 | |||||
| 否则有可能引起故障、误动作、火灾。 | |||||
| 2. 对扩展电缆等连接电缆进行拆装时请在断开电源之后再进行操作。 | |||||
| 否则有可能引起故障、误动作。 | |||||
| 3. 在对以下的设备进行拆装时请务必将电源切断。 | |||||
| 否则有可能引起故障、误动作。 | |||||
| --外围设备、扩展功能板、特殊适配器、 | |||||
| --输入输出扩展模块、网络模块等。 | |||||
| 1-4-4.伺服放大器(驱动单元)侧的设定 | |||||
| 1)可编程控制器侧的脉冲输出形式 | |||||
| XD/XL系列 PLC的脉冲输出类型全部为集电极开路信号(脉冲+方向) ,如下图所示: | |||||
| 脉冲输出端口Y0 | |||||
| 任意的输出Y□ | |||||
| (指定旋转方向) | |||||
| 脉冲输出端口Y1 | |||||
| 任意的输出Y□ | |||||
| (指定旋转方向) | |||||
| H | |||||
| L | |||||
| H | |||||
| L | |||||
| H | |||||
| L | |||||
| H | |||||
| L | |||||
| 正转 反转 | |||||
| ON | |||||
| ON | |||||
| OFF | |||||
| OFF | |||||
| 脉冲输出端口Y2 | |||||
| 任意的输出Y□ | |||||
| (指定旋转方向) | |||||
| 脉冲输出端口Y11 | |||||
| 任意的输出Y□ | |||||
| (指定旋转方向) | |||||
| H | |||||
| L | |||||
| H | |||||
| L | |||||
| H | |||||
| L | |||||
| H | |||||
| L | |||||
| 正转 反转 | |||||
| ON | |||||
| ON | |||||
| OFF | |||||
| OFF | |||||
| 正转 反转 | |||||
| 【注】 :ON、OFF表示可编程控制器的输出状态;H、L表示波形的 HIGH、LOW。 | |||||
| 2)伺服放大器(驱动单元)的指令脉冲输入形式的设定 | |||||
| 如下表所示,请使伺服放大器(驱动单元)参数中的脉冲串输入形式与可编程控制器的脉冲输出形式相 | |||||
| 符合。 | |||||
| 伺服放大器 | |||||
| (驱动单元) | |||||
| 基本单元的脉冲输出形式 集电极转差分板DC-Diff | |||||
| 晶体管输出(漏型输出) 差动驱动 | |||||
| 脉冲+方向 正转脉冲、反转脉冲 | |||||
| 指令脉冲输入形式 脉冲+符号 正转脉冲、反转脉冲 | |||||
| 指令脉冲逻辑 负逻辑 负逻辑 | |||||
| 【注】 :XD/XL系列 PLC本体脉冲输出形式为集电极开路信号输出(脉冲+方向) ,可以通过集电极转差分 | |||||
| 扩展板 OC-Diff将集电极开路信号输出(脉冲+方向)转化为差动信号输出。 | |||||
| 集电极开路信号(脉冲+方向)通过 OC-Diff转化为差分信号接线图(以 DS2-21P5-A为例): | |||||
| ===== PDF page 167 ===== | |||||
| XD/XL系列可编程控制器用户手册[定位控制篇] 1.脉冲输出 | |||||
| 157 | |||||
| 1 | |||||
| 5 | |||||
| 6 | |||||
| 10 | |||||
| 11 | |||||
| 15 | |||||
| +24V 2P- +5V +24V 1P- +5V | |||||
| 24V+ 24V- PUL2- PUL2+ PUL1- PUL1+ | |||||
| 开关电源 | |||||
| 集电极转差分OC-Diff | |||||
| Z0 | |||||
| GN | |||||
| 24V | |||||
| 0V | |||||
| 差分输出 | |||||
| CN1口 | |||||
| DS系列伺服放大器的各系列的参数设定: | |||||
| 系列名称 参数号 设定值 | |||||
| 脉冲+方向(负逻辑) 差动信号(负逻辑) | |||||
| DS2系列 AS — √ — | |||||
| DS2系列 AS2 — √ — | |||||
| DS2系列 AS6 P2-00 2 1 | |||||
| DS2系列 BS — √ — | |||||
| DS2系列 BS6 P2-00 2 1 | |||||
| DS2系列 BSW — √ — | |||||
| DS2系列 BSW6 P2-00 2 1 | |||||
| DS3系列 PQA P2-00 2 1 | |||||
| DS3E系列 PFA P2-00 2 1 | |||||
| DS3系列 P0-10 2 1 | |||||
| DS3E系列 P0-10 2 1 | |||||
| 3)伺服放大器(驱动单元)电子齿轮比的设定(以DS2系列为例) | |||||
| 通过使用伺服电机的电子齿轮,可以设定每个脉冲的移动量。 | |||||
| 关于电子齿轮的设定,请参考使用的伺服电机以及伺服放大器的手册,设定与用途相符合的数值。 | |||||
| (1)例 1 | |||||
| 将每个脉冲的移动量设定为 10μm时(使用丝杆的机械时)。 | |||||
| 机械规格 | |||||
| 伺服放大器 DS2系列 | |||||
| 伺服电机的额定转速 3000r/min | |||||
| 滚珠丝杆导程螺距(Pb) 10mm | |||||
| 减速机减速比(n) 1:5 | |||||
| 伺服电机分辨率(Pt) 10000PLS/REV | |||||
| 伺服电机 减速 | |||||
| 机构 | |||||
| 工作台 | |||||
| f0:指令脉冲频率 | |||||
| CMX:电子齿轮/分子 | |||||
| CDV:电子齿轮/分母 | |||||
| NR:伺服电机转速r/min | |||||
| X:每个脉冲的移动量mm | |||||
| ===== PDF page 168 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 158 | |||||
| 电子齿轮比计算公式如下: | |||||
| = X ×CMX | |||||
| CDV | |||||
| Pt | |||||
| n×Pb | |||||
| =10×10 ×-3 10000 | |||||
| 1/5×10 | |||||
| 50 | |||||
| 1 | |||||
| = | |||||
| 由上图可知,伺服驱动器电子齿轮比应该设定为 50:1 | |||||
| 此时,基本单元最大输出脉冲频率(200,000Hz)时的伺服电机的旋转速度如下计算所示: | |||||
| ×CMX | |||||
| CDV | |||||
| = | |||||
| NR = 60 | |||||
| Pt | |||||
| × f0 | |||||
| 50 | |||||
| 1 | |||||
| × 60 | |||||
| 10000 | |||||
| × 200000 | |||||
| = 60000r/min > 3000r/min(额定转速) | |||||
| 注意:请设定可编程控制器侧的最高速度,以使伺服电机的旋转速度控制在额定转速以下。 | |||||
| (2)例 2 | |||||
| 将每个脉冲的移动量设定为 0.01°时(旋转台时)。 | |||||
| 机械规格 | |||||
| 伺服放大器 DS2系列 | |||||
| 伺服电机的额定转速 3000r/min | |||||
| 旋转台角度 360°/ REV | |||||
| 减速比(n) 1:5 | |||||
| 伺服电机分辨率(Pt) 10000PLS/REV | |||||
| 伺服电机 | |||||
| Pt=10000[PLS/REV] | |||||
| 旋转台 | |||||
| 同步皮带:1:5 | |||||
| F0 :指令脉冲频率[Hz](集电极开路方式) | |||||
| CMX:电子齿轮(指令脉冲倍率分子) | |||||
| CDV:电子齿轮(指令脉冲倍率分母) | |||||
| NR :伺服电机旋转速度[r/min] | |||||
| X :每个脉冲的移动量[°] | |||||
| 电子齿轮比计算公式如下: | |||||
| = X ×CMX | |||||
| CDV | |||||
| Pt | |||||
| n×360 | |||||
| = 1×10 ×-2 10000 | |||||
| 1/5×360 | |||||
| 25 | |||||
| 18 | |||||
| = | |||||
| 由上图可知,伺服驱动器电子齿轮比应该设定为 25:18 | |||||
| 此时,基本单元最大输出脉冲频率(200,000Hz)时的伺服电机的旋转速度如下计算所示: | |||||
| CMX | |||||
| CDV | |||||
| × 60 | |||||
| Pt | |||||
| × f0 | |||||
| 25 | |||||
| 18 | |||||
| × 60 | |||||
| 10000 | |||||
| × 100000= | |||||
| = 833.33r/min < 3000r/min(额定转速) | |||||
| NR= | |||||
| 因为伺服电机的旋转速度在额定转速以下,所以可编程控制器侧的最高速度不需要有限制。 | |||||
| ===== PDF page 169 ===== | |||||
| XD/XL系列可编程控制器用户手册[定位控制篇] 1.脉冲输出 | |||||
| 159 | |||||
| 4)伺服放大器(驱动单元)准备好信号设定(以DS2系列为例) | |||||
| DS2系列伺服使能信号有效代表伺服电机通电工作,当伺服使能信号无效时,电机不运行。 | |||||
| 系列名 参数号 设定值 | |||||
| DS2系列 P5-10 0010 | |||||
| 1-4-5.定位指令脉冲发送完成标志位的使用及注意事项 | |||||
| 正在发脉冲标志位SM1000、SM1020、SM1040……等标志位由ON变为OFF时,意味着指令的动作 | |||||
| (脉冲输出动作等)结束了。但是,并不意味着伺服电机的动作也结束(停止)了。为了确切掌握伺服电机 | |||||
| 的动作结束情况,请正确使用正在发脉冲标志位。 | |||||
| 正在发脉冲标志位如下表所示: | |||||
| 序号 线圈 轴数 说明 | |||||
| 1 SM1000 Y0 当脉冲发送时线圈置 ON, 脉冲发送结束后立即置OFF, | |||||
| 利用线圈的下降沿判断脉冲发送是否结束。 | |||||
| t0 | |||||
| 频率 | |||||
| SM1000 | |||||
| 脉冲段 | |||||
| 2 SM1020 Y1 | |||||
| 3 SM1040 Y2 | |||||
| 4 SM1060 Y3 | |||||
| 5 SM1080 Y4 | |||||
| 6 SM1100 Y5 | |||||
| 7 SM1120 Y6 | |||||
| 8 SM1140 Y7 | |||||
| 9 SM1160 Y10 | |||||
| 10 SM1180 Y11 | |||||
| 如果编写多个同一脉冲输出端口的定位指令, 那么指令执行时, 正在发送脉冲标志位SM1000、SM1020、 | |||||
| SM1040……等随着各个指令而ON/0FF变化。因此,如果将多个指令执行正在发送脉冲标志位 SM1000、 | |||||
| SM1020、SM1040……等同时用在同一段程序内,则无法判断是因为执行哪条指令而ON/OFF,同时也不能 | |||||
| 正常获取与各个指令相支持的标志位。 | |||||
| 错误的写法如下: | |||||
| ===== PDF page 170 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 160 | |||||
| 正确的写法如下: | |||||
| 1-4-6.定位指令触发条件注意事项 | |||||
| XD/XL 系列 PLC 定位指令主要有 PLSR(边沿触发) 、PLSF(常开/常闭触发) 、DRVI(边沿触发) 、 | |||||
| DRV A(边沿触发) 、ZRN(边沿触发) ;除了PLSF指令外,其余的脉冲指令全部是边沿触发,同一脉冲输 | |||||
| 出端口(例如Y0)在执行一条定位指令的过程中,正在发送脉冲标志位(SM1000)会一直处于导通状态, | |||||
| 此时再触发其它同一脉冲输出端口的脉冲指令,则PLC将不会予以响应,直到正在执行的脉冲输出指令脉 | |||||
| 冲发送结束,正在发送脉冲标志位复位以后才会响应。 | |||||
| 由于 PLSF脉冲指令的导通条件为常开/常闭,所以在使用 PLSF指令时,当脉冲发送结束不需要执行 | |||||
| 时,请立即对 PLSF 指令的导通条件进行复位(不要只将脉冲输出频率设定为 0Hz,而不对脉冲导通条件 | |||||
| 进行复位) 。 | |||||
| 1-4-7.定位指令与系统参数块相关参数 | |||||
| 下表整理了脉冲输出指令与系统参数块有关参数设定: | |||||
| 系统参数块内容 PLSR PLSF DRVI DRVA ZRN | |||||
| 公共参数—脉冲方向逻辑 必须设定 必须设定 必须设定 必须设定 必须设定 | |||||
| 公共参数—启用软限位功能 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—机械回原点默认方向 × × × × 必须设定 | |||||
| 公共参数—脉冲单位 必须设定 必须设定 必须设定 必须设定 必须设定 | |||||
| 公共参数—插补坐标模式 × × × × × | |||||
| 公共参数—脉冲发送模式 必须设定 必须设定 必须设定 必须设定 必须设定 | |||||
| 公共参数—脉冲数(1转) 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—移动量(1转) 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—脉冲方向端子 可不设 可不设 可不设 可不设 必须设定 | |||||
| 公共参数—脉冲方向延时时间 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—齿轮间隙正向补偿 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—齿轮间隙负向补偿 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—电气原点位置 × × × × × | |||||
| ===== PDF page 171 ===== | |||||
| XD/XL系列可编程控制器用户手册[定位控制篇] 1.脉冲输出 | |||||
| 161 | |||||
| 系统参数块内容 PLSR PLSF DRVI DRVA ZRN | |||||
| 公共参数—原点开关状态设置 × × × × 必须设定 | |||||
| 公共参数—原点信号端子设定 × × × × 必须设定 | |||||
| 公共参数—Z 相开关状态设置 × × × × 可不设 | |||||
| 公共参数—Z 相端子设定 × × × × 可不设 | |||||
| 公共参数—正极限开关状态设置 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—正极限端子设定 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—负极限开关状态设置 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—负极限端子设定 可不设 可不设 可不设 可不设 可不设 | |||||
| 公共参数—归零清零 CLR 信号输出端子 | |||||
| 设定 × × × × 可不设 | |||||
| 公共参数—回归速度 VH × × × × 必须设定 | |||||
| 公共参数—爬行速度 VC × × × × 必须设定 | |||||
| 公共参数—机械原点位置 × × × × 必须设定 | |||||
| 公共参数—Z 相个数 × × × × 可不设 | |||||
| 公共参数—CLR信号延时时间 × × × × 可不设 | |||||
| 公共参数—软限位正极限值 可不设 可不设 可不设 可不设 × | |||||
| 公共参数—软限位负极限值 可不设 可不设 可不设 可不设 × | |||||
| 公共参数—快速定位指令默认参数块 × × 可不设 可不设 × | |||||
| 公共参数—插补指令默认参数块 × × × × × | |||||
| 第 1 套参数—脉冲默认速度 必须设定 必须设定 × × 必须设定 | |||||
| 第 1 套参数—脉冲默认速度加速时间 必须设定 必须设定 × × 必须设定 | |||||
| 第 1 套参数—脉冲默认速度减速时间 必须设定 必须设定 × × 必须设定 | |||||
| 第 1 套参数—补间加减速时间 可不设 可不设 可不设 可不设 可不设 | |||||
| 第 1 套参数—脉冲加减速模式 必须设定 必须设定 必须设定 必须设定 必须设定 | |||||
| 第 1 套参数—最高速度 必须设定 必须设定 必须设定 必须设定 必须设定 | |||||
| 第 1 套参数—起始速度 必须设定 必须设定 必须设定 必须设定 必须设定 | |||||
| 第 1 套参数—终止速度 必须设定 必须设定 必须设定 必须设定 必须设定 | |||||
| 第 1 套参数—脉冲频率刷新时间 可不设 可不设 可不设 可不设 可不设 | |||||
| 第 1 套参数—回归速度 VH × × × × 必须设定 | |||||
| 第 1 套参数—爬行速度 VC × × × × 必须设定 | |||||
| 【注】 : | |||||
| ※1:第 0、2、3、4套参数设定请参照第 1套参数设定。 | |||||
| ※2:设定了“第 1套参数—回归速度 VH” 、 “第1套参数—爬行速度 VC”的情况下,公共参数的 VH、 | |||||
| VC可不设定。 | |||||
| 1-4-8.伺服电机、步进电机不动作故障排查 | |||||
| 伺服电机、步进电机不转时,请确认以下项目: | |||||
| 1)请确认接线。 | |||||
| 2)请执行定位指令,确认以下的 LED的状态。 | |||||
| -设定为脉冲输出端软元件的输出信号的LED; | |||||
| -设定为旋转方向输出的输出信号的 LED。 | |||||
| 3)请确认可编程控制器执行定位指令时,各轴累计脉冲寄存器的数值是否在变化。 | |||||
| 各脉冲输出累积寄存器如下表所示: | |||||
| ===== PDF page 172 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 162 | |||||
| 编号 功能 说明 轴数 | |||||
| HSD0 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y0 HSD1 累计脉冲量高 16位 | |||||
| HSD2 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD3 累计脉冲量高 16位 | |||||
| HSD4 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y1 HSD5 累计脉冲量高 16位 | |||||
| HSD6 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD7 累计脉冲量高 16位 | |||||
| HSD8 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y2 | |||||
| HSD9 累计脉冲量高 16位 | |||||
| HSD10 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD11 累计脉冲量高 16位 | |||||
| HSD12 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y3 HSD13 累计脉冲量高 16位 | |||||
| HSD14 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD15 累计脉冲量高 16位 | |||||
| HSD16 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y4 HSD17 累计脉冲量高 16位 | |||||
| HSD18 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD19 累计脉冲量高 16位 | |||||
| HSD20 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y5 | |||||
| HSD21 累计脉冲量高 16位 | |||||
| HSD22 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD23 累计脉冲量高 16位 | |||||
| HSD24 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y6 HSD25 累计脉冲量高 16位 | |||||
| HSD26 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD27 累计脉冲量高 16位 | |||||
| HSD28 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y7 HSD29 累计脉冲量高 16位 | |||||
| HSD30 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD31 累计脉冲量高 16位 | |||||
| HSD32 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y10 | |||||
| HSD33 累计脉冲量高 16位 | |||||
| HSD34 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD35 累计脉冲量高 16位 | |||||
| HSD36 累计脉冲量低 16位 脉冲个数为单位 | |||||
| Y11 HSD37 累计脉冲量高 16位 | |||||
| HSD38 累计脉冲量低 16位 脉冲当量为单位 | |||||
| HSD39 累计脉冲量高 16位 | |||||
| 4)请确认可编程控制器侧和伺服放大器(驱动单元)的脉冲输出形式是否相符。 | |||||
| ===== PDF page 173 ===== | |||||
| XD/XL系列可编程控制器用户手册[定位控制篇] 1.脉冲输出 | |||||
| 163 | |||||
| 5)请确认脉冲输出停止标志位是否动作。 | |||||
| 各脉冲输出端软元件的脉冲输出标志位如下表所示: | |||||
| 序号 线圈 轴数 说明 | |||||
| 1 SM1001 Y0 当脉冲数值为正值正向发送脉冲时,线圈置 ON; | |||||
| 当脉冲数值为负值反向发送脉冲时,线圈置 OFF。 | |||||
| t0 | |||||
| 频率 | |||||
| SM1001 | |||||
| 脉冲段 | |||||
| 2 SM1021 Y1 | |||||
| 3 SM1041 Y2 | |||||
| 4 SM1061 Y3 | |||||
| 5 SM1081 Y4 | |||||
| 6 SM1101 Y5 | |||||
| 7 SM1121 Y6 | |||||
| 8 SM1141 Y7 | |||||
| 9 SM1161 Y10 | |||||
| 10 SM1181 Y11 | |||||
| 6)请确认极限(正转限位、反转限位)是否动作。 | |||||
| 7)请确认定位指令的动作时序。 | |||||
| 正在发送脉冲标志位为ON时,使用同一脉冲输出端软元件的定位指令或者脉冲输出指令不能被执 | |||||
| 行。 | |||||
| 1-4-9.伺服电机、步进电机停止位置不正确故障排查 | |||||
| 停止位置不正确时,请确认以下项目: | |||||
| 1)请确认伺服放大器(驱动单元)的电子齿轮的设定是否正确。 | |||||
| 2)请确认原点位置是否偏移。 | |||||
| A、设计原点信号时,请考虑有足够为ON的时间能充分减速到爬行速度。 | |||||
| ZRN指令在原点前端开始减速到停止,延时反向加速到爬行速度,在脱离原点时停止, 清除当前值 | |||||
| 寄存器。 | |||||
| 在原点后端前,没有能够减速到爬行速度时,会导致停止位置偏移。 | |||||
| B、请使爬行速度足够的慢。 | |||||
| 原点回归指令的停止是不进行减速停止的, 所以如果爬行速度过快, 会由于惯性导致停止位置偏 | |||||
| 移。 | |||||
| C、关于原点信号的软元件。 | |||||
| 原点信号端子可以选择 PLC本体上所有的输入点; 但是如果选择的输入点为PLC上的外部中断端子, | |||||
| 则回机械原点的过程中都会按照中断进行处理,从而可以进一步的提高回机械原点的精度(如果使用Z 相 | |||||
| 回原点则无影响) ;而选择的输入点为非PLC本体上的外部中断端子,会机械原点的过程中则会受到PLC | |||||
| 扫描周期的影响(如果使用 Z相回原点则无影响) 。 | |||||
| 3)进行正反转动作(往返动作)后,停止位置有偏离。 | |||||
| 由于移动工作台与滚珠丝杠之间存在接触间隙,工作台由正向移动结束切到反向移动时,从而导致反 | |||||
| 向实际移动距离小于设定距离;工作台由反向移动结束切到正向移动时,从而导致正向实际移动距离小于 | |||||
| 设定距。 | |||||
| 可以通过正向齿轮间隙补偿和反向齿轮间隙补偿进行修正。 | |||||
| ===== PDF page 174 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 164 | |||||
| 1-5.定位指令案例程序 | |||||
| 本节主要通过几个样例程序来介绍 PLSR、PLSF、DRV A、DRVI、ZRN指令的使用方式。 | |||||
| 动作 指令 程序举例 | |||||
| 顺控梯形图 流程梯形图 | |||||
| 多段脉冲定位 PLSR 1-5-4、1-5-6 1-5-5、1-5-7 | |||||
| 可变频脉冲输出 PLSF 1-5-2、1-5-4 1-5-3、1-5-5 | |||||
| 相对单段定位 DRVI 1-5-2、1-5-6 1-5-3、1-5-7 | |||||
| 绝对单段定位 DRV A 1-5-2、1-5-6 1-5-3、1-5-7 | |||||
| 机械原点回归 ZRN 1-5-2、1-5-4、1-5-6 1-5-3、1-5-5、1-5-7 | |||||
| 1-5-1.I/O点分配 | |||||
| 程序举例中使用脉冲输出端 Y0(1 轴)。使用其它脉冲输出端的时候,请修改对应的脉冲轴软元件。 | |||||
| 信号名称 输入输出编号 备注 | |||||
| 脉冲输出端口 Y0 | |||||
| 脉冲方向端口 Y2 | |||||
| CLR清零信号 Y3 | |||||
| 伺服准备好 X0 | |||||
| 停止控制 X1 | |||||
| 脉冲继续 X13 | |||||
| 原点回归控制 X4 | |||||
| 点动前进控制 X5 | |||||
| 点动后退控制 X6 | |||||
| 正转定位控制 X7 | |||||
| 反转定位控制 X10 | |||||
| 原点输入端子 X3 使用外部中断端子 | |||||
| 正向限位开关 X11 | |||||
| 反向限位开关 X12 | |||||
| 1-5-2.正反转顺控样例程序【PLSF、DRVI、DRVA、ZRN】 | |||||
| 例1:根据下图运行,采用绝对单段定位方式进行定位。 | |||||
| 10000Hz | |||||
| 原点 | |||||
| 加减速时间 | |||||
| 200ms | |||||
| (50000,0) | |||||
| 10000Hz加减速时间 | |||||
| 200ms | |||||
| (100,0) | |||||
| (0,0) | |||||
| 加减速时间 | |||||
| 200ms | |||||
| ===== PDF page 175 ===== | |||||
| XD/XL系列可编程控制器用户手册[定位控制篇] 1.脉冲输出 | |||||
| 165 | |||||
| 首先,编写梯形图程序,如下: | |||||
| X4 | |||||
| X6 X5 | |||||
| M100 | |||||
| X5 X6 | |||||
| M101 | |||||
| X7 X10 | |||||
| 原点回 | |||||
| 归控制 | |||||
| 点动后 | |||||
| 退控制 | |||||
| 点动前 | |||||
| 进控制 | |||||
| 点动前进 | |||||
| 运行中 | |||||
| 点动前 | |||||
| 进控制 | |||||
| 点动后 | |||||
| 退控制 | |||||
| 点动后退 | |||||
| 运行中 | |||||
| 正转定位 | |||||
| 控制 | |||||
| 反转定位 | |||||
| 控制 | |||||
| ZRN K1 Y0 | |||||
| PLSF K10000 K1 Y0 | |||||
| ( ) | |||||
| M100 | |||||
| PLSF K-10000 K1 Y0 | |||||
| ( ) | |||||
| M101 | |||||
| 点动前进运行中 | |||||
| 点动后退运行中 | |||||
| DRVA K50000 K10000 K200 Y0 Y2 | |||||
| X10 X7 | |||||
| 正转定位 | |||||
| 控制 | |||||
| 反转定位 | |||||
| 控制 | |||||
| DRVA K100 K10000 K200 Y0 Y2 | |||||
| X0 X5 X6 | |||||
| STOP Y0 K0 | |||||
| X1 | |||||
| 停止控制 | |||||
| 伺服准备 | |||||
| 好 | |||||
| 点动前 | |||||
| 进控制 | |||||
| 点动后 | |||||
| 退控制 | |||||
| X13 | |||||
| GOON Y0 | |||||
| 脉冲继续 | |||||
| 由于样例程序中除 DRVI和 DRV A,其余所有的脉冲指令使用的系统参数块都为第一套参数,所以, | |||||
| 我们点击 PLC编程软件左边的工程栏中的“脉冲配置参数” ,如下图: | |||||
| //机械回原点指令(选用第一套系统参数块参数) | |||||
| //点动前进控制, 速度为10000Hz(选用第一套系统参 | |||||
| 数块参数) | |||||
| //点动后退控制, 速度为-10000Hz(选用第一套系统参 | |||||
| 数块参数) | |||||
| //正转定位控制 | |||||
| //反转定位控制 | |||||
| //脉冲停止发送控制(缓停) | |||||
| //脉冲没有发送完执行脉冲继续将剩余的脉冲发送完 | |||||
| ===== PDF page 176 ===== | |||||
| 1.脉冲输出 XD/XL系列可编程控制器用户手册[定位控制篇] | |||||
| 166 | |||||
| 将会打开如下窗口: | |||||
| 点击打开窗口中的“配置”选项,在下拉菜单中选择“Y0轴” : | |||||
| 在打开的参数配置表格中按如下进行配置(圈起来的参数指需要在默认参数下进行修改的参数) : | |||||
| 系统参数块配置一 | |||||
| @@ -0,0 +1,162 @@ | |||||
| # -*- coding: utf-8 -*- | |||||
| """逻辑分析仪波形 .bin → 时频曲线拟合。 | |||||
| 文件格式(自动探测): | |||||
| 16 通道逻辑分析仪导出:每采样 2 字节(小端 uint16),bit0..15 = CH0..CH15。 | |||||
| 信号通道 = 值 0x0100 的位(bit8),即字节流的奇数索引字节承载 CH8。 | |||||
| 采样率默认 100MS/s(可用 --fs 覆盖;也可自动验证 2000/5000Hz 命中)。 | |||||
| 用法: | |||||
| python plot_waveform.py <xxx.bin> [--fs 100e6] [--ch 8] [--out <png>] | |||||
| """ | |||||
| import argparse | |||||
| import sys | |||||
| import numpy as np | |||||
| import matplotlib | |||||
| matplotlib.use("Agg") | |||||
| import matplotlib.pyplot as plt | |||||
| def extract_channel(m, ch): | |||||
| """从 2 字节/采样(小端 uint16)格式中提取通道 ch 的数字序列。""" | |||||
| # 目标位在 16bit 值中的字节位置:bit<8 → 低字节(偶索引);>=8 → 高字节(奇索引) | |||||
| if ch < 8: | |||||
| lo = m[0::2] | |||||
| return (lo >> ch) & 1 | |||||
| hi = m[1::2] | |||||
| return (hi >> (ch - 8)) & 1 | |||||
| def rising_edges(sig): | |||||
| """上升沿索引(数字序列)。""" | |||||
| return np.nonzero((sig[1:] == 1) & (sig[:-1] == 0))[0] + 1 | |||||
| def main(): | |||||
| ap = argparse.ArgumentParser() | |||||
| ap.add_argument("bin_path") | |||||
| ap.add_argument("--fs", type=float, default=None, help="采样率 Hz") | |||||
| ap.add_argument("--ch", type=int, default=0, help="信号通道号") | |||||
| ap.add_argument("--out", default=None, help="输出png路径") | |||||
| args = ap.parse_args() | |||||
| m = np.memmap(args.bin_path, dtype=np.uint8, mode="r") | |||||
| if len(m) % 2 != 0: | |||||
| sys.exit("odd file size, not 2-byte/sample format?") | |||||
| nsamp = len(m) // 2 | |||||
| print("samples:", nsamp) | |||||
| ch = args.ch | |||||
| sig = extract_channel(m, ch) | |||||
| ones = int(sig.sum()) | |||||
| print("CH%d: %d ones / %d samples (%.2f%%)" | |||||
| % (ch, ones, nsamp, 100.0 * ones / nsamp)) | |||||
| nz = np.nonzero(sig)[0] | |||||
| if len(nz) == 0: | |||||
| sys.exit("channel has no signal") | |||||
| lo, hi = int(nz[0] * 0.97), int(nz[-1] * 1.03) | |||||
| print("signal range: sample %d .. %d" % (lo, hi)) | |||||
| # ---- 采样率:自动验证(检查匀速段 2000/5000Hz 命中) ---- | |||||
| if args.fs is None: | |||||
| candidates = [100e6, 50e6, 200e6, 25e6] | |||||
| best = [] | |||||
| for fs in candidates: | |||||
| down = max(1, int(fs // 5000000)) | |||||
| s = sig[lo:hi:down] | |||||
| r = rising_edges(s) | |||||
| if len(r) < 20: | |||||
| continue | |||||
| per = np.diff(r) * down / fs | |||||
| f = 1.0 / np.maximum(per, 1e-9) | |||||
| f = f[(f > 100) & (f < 20000)] | |||||
| if len(f) < 10: | |||||
| continue | |||||
| h, e = np.histogram(f, bins=400, range=(0, 20000)) | |||||
| e2 = h[(e[:-1] >= 1940) & (e[:-1] <= 2060)].sum() | |||||
| e5 = h[(e[:-1] >= 4850) & (e[:-1] <= 5150)].sum() | |||||
| best.append(((e2 + e5) / max(h.sum(), 1), fs)) | |||||
| best.sort(reverse=True) | |||||
| fs = best[0][1] | |||||
| print("sample-rate ranking:", ["%g:%.3f" % (f, s) for s, f in best]) | |||||
| print("using fs = %g Hz" % fs) | |||||
| else: | |||||
| fs = float(args.fs) | |||||
| # ---- 上升沿 → 时频 ---- | |||||
| r = rising_edges(sig[lo:hi]) | |||||
| r = r + lo | |||||
| t_rise = r / fs | |||||
| per = np.diff(t_rise) | |||||
| freq = 1.0 / np.maximum(per, 1e-9) | |||||
| t_mid = (t_rise[:-1] + t_rise[1:]) / 2.0 | |||||
| print("rising edges: %d" % len(r)) | |||||
| print("first pulse @ %.3fs, last @ %.3fs" % (t_rise[0], t_rise[-1])) | |||||
| print("total pulses: %d" % len(r)) | |||||
| print("average freq: %.1f Hz" | |||||
| % (len(r) / max(t_rise[-1] - t_rise[0], 1e-9))) | |||||
| # ---- 三段结构(按 10ms 桶取中位频率) ---- | |||||
| buckets = np.arange(t_rise[0] - 0.05, t_rise[-1] + 0.05, 0.01) | |||||
| med = [] | |||||
| bt = [] | |||||
| for i in range(len(buckets) - 1): | |||||
| sel = (t_mid >= buckets[i]) & (t_mid < buckets[i + 1]) | |||||
| if sel.sum() > 0: | |||||
| med.append(np.median(freq[sel])) | |||||
| bt.append((buckets[i] + buckets[i + 1]) / 2) | |||||
| med = np.array(med) | |||||
| bt = np.array(bt) | |||||
| active = med > 100 | |||||
| edges = np.diff(active.astype(int)) | |||||
| starts = bt[1:][edges == 1] | |||||
| stops = bt[1:][edges == -1] | |||||
| if len(bt) > 0 and active[0]: | |||||
| starts = np.concatenate(([bt[0]], starts)) | |||||
| if len(bt) > 0 and active[-1]: | |||||
| stops = np.concatenate((stops, [bt[-1]])) | |||||
| print("segments:") | |||||
| for s, e in zip(starts, stops): | |||||
| sel = (t_rise >= s) & (t_rise <= e) | |||||
| n = sel.sum() | |||||
| print(" %.3f ~ %.3fs dur=%.3fs pulses=%d avg=%.0fHz" | |||||
| % (s, e, e - s, n, n / max(e - s, 1e-9))) | |||||
| for i in range(len(stops) - 1): | |||||
| print(" gap seg%d->%d: %.3fms" % (i + 1, i + 2, | |||||
| (starts[i + 1] - stops[i]) * 1e3)) | |||||
| # ---- 画图 ---- | |||||
| out = args.out or (args.bin_path.rsplit(".", 1)[0] + "_timefreq.png") | |||||
| fig, axes = plt.subplots(2, 1, figsize=(14, 9), sharex=True, | |||||
| gridspec_kw={"height_ratios": [1, 3]}) | |||||
| ax = axes[0] | |||||
| step = max(1, int(fs // 200000)) | |||||
| xs = np.arange(lo, hi, step) / fs | |||||
| ax.plot(xs, sig[lo:hi:step], lw=0.4, color="steelblue") | |||||
| ax.set_ylabel("CH%d raw" % ch) | |||||
| ax.set_yticks([0, 1]) | |||||
| ax.grid(alpha=0.3) | |||||
| ax = axes[1] | |||||
| ax.plot(t_mid, freq, lw=0.8, color="crimson") | |||||
| ax.axhline(2000, color="gray", ls="--", lw=0.8) | |||||
| ax.axhline(5000, color="gray", ls="--", lw=0.8) | |||||
| ax.set_ylabel("instantaneous freq (Hz)") | |||||
| ax.set_xlabel("time (s)") | |||||
| ax.set_ylim(0, 6000) | |||||
| ax.grid(alpha=0.3) | |||||
| ax.legend(["freq", "2000Hz", "5000Hz"], loc="upper right", fontsize=8) | |||||
| fig.suptitle("CH%d time-frequency: %d pulses, fs=%g Hz, ch=%d" | |||||
| % (ch, len(r), fs, ch)) | |||||
| fig.tight_layout() | |||||
| fig.savefig(out, dpi=130) | |||||
| print("saved:", out) | |||||
| if __name__ == "__main__": | |||||
| main() | |||||
| @@ -51,6 +51,8 @@ uint8_t PlsrHwResolveDirectionPoint(uint8_t pointNumber); | |||||
| /* 模拟寄存器访问与中断触发(测试用)。 */ | /* 模拟寄存器访问与中断触发(测试用)。 */ | ||||
| uint32_t PlsrHwTestGetArr(uint8_t axis); | uint32_t PlsrHwTestGetArr(uint8_t axis); | ||||
| uint32_t PlsrHwTestGetCcr(uint8_t axis); | uint32_t PlsrHwTestGetCcr(uint8_t axis); | ||||
| uint32_t PlsrHwTestGetCcmr1(uint8_t axis); | |||||
| uint32_t PlsrHwTestGetCr1(uint8_t axis); | |||||
| uint32_t PlsrHwTestGetPsc(uint8_t axis); | uint32_t PlsrHwTestGetPsc(uint8_t axis); | ||||
| uint8_t PlsrHwTestGetPwmEnabled(uint8_t axis); | uint8_t PlsrHwTestGetPwmEnabled(uint8_t axis); | ||||
| uint8_t PlsrHwTestGetDirLevel(uint8_t axis); | uint8_t PlsrHwTestGetDirLevel(uint8_t axis); | ||||
| @@ -89,6 +89,7 @@ typedef struct | |||||
| uint32_t psc; | uint32_t psc; | ||||
| uint32_t arr; | uint32_t arr; | ||||
| uint32_t ccr1; | uint32_t ccr1; | ||||
| uint32_t ccmr1; | |||||
| uint32_t ccer; | uint32_t ccer; | ||||
| uint8_t dirLevel; | uint8_t dirLevel; | ||||
| } PLSR_HW_TIMER_REGS; | } PLSR_HW_TIMER_REGS; | ||||
| @@ -170,6 +171,18 @@ static void PlsrHwTimerSetCc1e(uint8_t axis, uint32_t value) | |||||
| #endif | #endif | ||||
| } | } | ||||
| /* 通道 1 输出模式 = PWM 模式 1(OC1M=110)+ CCR 预装载(OC1PE)。 | |||||
| * 上电复位后 CCMR1=0(冻结),通道输出恒定电平、无方波,必须显式配置。 */ | |||||
| static void PlsrHwTimerSetPwmMode1(uint8_t axis) | |||||
| { | |||||
| #ifdef PLSR_HOST_TEST | |||||
| PlsrHwTimers[axis].ccmr1 = 0x0068UL; | |||||
| #else | |||||
| PlsrHwAxisMap[axis].timer->CCMR1 = (TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2) | |||||
| | TIM_CCMR1_OC1PE; | |||||
| #endif | |||||
| } | |||||
| static void PlsrHwTimerSetUie(uint8_t axis, uint32_t value) | static void PlsrHwTimerSetUie(uint8_t axis, uint32_t value) | ||||
| { | { | ||||
| #ifdef PLSR_HOST_TEST | #ifdef PLSR_HOST_TEST | ||||
| @@ -195,7 +208,9 @@ static void PlsrHwTimerClearUif(uint8_t axis) | |||||
| #endif | #endif | ||||
| } | } | ||||
| /* ---- DIR 输出 ---- */ | |||||
| /* ---- DIR 输出 ---- | |||||
| * XDM 为晶体管(NPN 漏型)输出:ON(导通)= 引脚低电平。 | |||||
| * 信捷正逻辑:正向发脉冲时方向端子置 ON(低)。 */ | |||||
| static void PlsrHwSetDirLevel(uint8_t axis, uint8_t positive) | static void PlsrHwSetDirLevel(uint8_t axis, uint8_t positive) | ||||
| { | { | ||||
| @@ -213,19 +228,60 @@ static void PlsrHwSetDirLevel(uint8_t axis, uint8_t positive) | |||||
| { | { | ||||
| const PLSR_HW_OUTPUT_PIN *pin = | const PLSR_HW_OUTPUT_PIN *pin = | ||||
| &PlsrHwOutputPins[state->directionPoint]; | &PlsrHwOutputPins[state->directionPoint]; | ||||
| GPIO_InitTypeDef gpio; | |||||
| if (pin->port != NULL) | if (pin->port != NULL) | ||||
| { | { | ||||
| HAL_GPIO_WritePin(pin->port, pin->pin, | |||||
| (positive != 0U) ? GPIO_PIN_SET : GPIO_PIN_RESET); | |||||
| /* DIR 点按需配置为推挽输出(上电默认高阻=截止,安全)。 */ | |||||
| gpio.Pin = pin->pin; | |||||
| gpio.Mode = GPIO_MODE_OUTPUT_PP; | |||||
| gpio.Pull = GPIO_NOPULL; | |||||
| gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; | |||||
| HAL_GPIO_Init(pin->port, &gpio); | |||||
| /* 漏型输出:ON(导通)= 低电平。 */ | |||||
| HAL_GPIO_WritePin(pin->port, | |||||
| pin->pin, | |||||
| (positive != 0U) ? GPIO_PIN_RESET | |||||
| : GPIO_PIN_SET); | |||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| /* ---- PWM 启停 ---- */ | |||||
| /* ---- PWM 启停 ---- | |||||
| * ARR/CCR 使用预装载(ARPE/OC1PE):运行中调频写入延迟到更新事件生效, | |||||
| * 避免 ARR 变小瞬间 CNT 超调提前回绕(每段加速会多出 ~ln(f1/f0) 个假脉冲)。 | |||||
| * 首次启动用 EGR.UG 把预装载值加载到影子寄存器,杜绝首个周期用复位值。 */ | |||||
| static void PlsrHwTimerSetArpe(uint8_t axis, uint32_t value) | |||||
| { | |||||
| #ifdef PLSR_HOST_TEST | |||||
| PlsrHwTimers[axis].cr1 = (PlsrHwTimers[axis].cr1 & ~0x0080UL) | |||||
| | ((value != 0UL) ? 0x0080UL : 0UL); | |||||
| #else | |||||
| if (value != 0UL) | |||||
| { | |||||
| PlsrHwAxisMap[axis].timer->CR1 |= TIM_CR1_ARPE; | |||||
| } | |||||
| else | |||||
| { | |||||
| PlsrHwAxisMap[axis].timer->CR1 &= ~TIM_CR1_ARPE; | |||||
| } | |||||
| #endif | |||||
| } | |||||
| /* 生成更新事件:立即加载 ARR/CCR/PSC 影子寄存器(启动时用)。 */ | |||||
| static void PlsrHwTimerSetUg(uint8_t axis) | |||||
| { | |||||
| #ifdef PLSR_HOST_TEST | |||||
| PlsrHwTimers[axis].sr &= ~PLSR_HW_TIMER_UPDATE_BIT; | |||||
| #else | |||||
| PlsrHwAxisMap[axis].timer->EGR = TIM_EGR_UG; | |||||
| #endif | |||||
| } | |||||
| static void PlsrHwStartPwmTimer(uint8_t axis, uint32_t frequencyHz) | |||||
| /* 配置 PWM 定时器(预装载写入;启动/调频共用,不触碰使能位)。 */ | |||||
| static void PlsrHwConfigurePwm(uint8_t axis, uint32_t frequencyHz) | |||||
| { | { | ||||
| uint16_t psc; | uint16_t psc; | ||||
| uint16_t arr; | uint16_t arr; | ||||
| @@ -240,6 +296,14 @@ static void PlsrHwStartPwmTimer(uint8_t axis, uint32_t frequencyHz) | |||||
| PlsrHwTimerSetPsc(axis, psc); | PlsrHwTimerSetPsc(axis, psc); | ||||
| PlsrHwTimerSetArr(axis, arr); | PlsrHwTimerSetArr(axis, arr); | ||||
| PlsrHwTimerSetCcr(axis, (uint32_t)arr / 2UL); /* 50% 占空比 */ | PlsrHwTimerSetCcr(axis, (uint32_t)arr / 2UL); /* 50% 占空比 */ | ||||
| PlsrHwTimerSetPwmMode1(axis); | |||||
| PlsrHwTimerSetArpe(axis, 1UL); | |||||
| } | |||||
| /* 首次启动输出:加载影子寄存器后使能更新中断、通道与计数。 */ | |||||
| static void PlsrHwPwmBegin(uint8_t axis) | |||||
| { | |||||
| PlsrHwTimerSetUg(axis); | |||||
| PlsrHwTimerSetUie(axis, 1UL); | PlsrHwTimerSetUie(axis, 1UL); | ||||
| PlsrHwTimerSetCc1e(axis, 1UL); | PlsrHwTimerSetCc1e(axis, 1UL); | ||||
| PlsrHwTimerSetCen(axis, 1UL); | PlsrHwTimerSetCen(axis, 1UL); | ||||
| @@ -295,9 +359,8 @@ PLSR_RESULT PlsrHwInit(void) | |||||
| #ifndef PLSR_HOST_TEST | #ifndef PLSR_HOST_TEST | ||||
| { | { | ||||
| GPIO_InitTypeDef gpio; | GPIO_InitTypeDef gpio; | ||||
| uint8_t point; | |||||
| /* 1. 输出点 GPIO 时钟。 */ | |||||
| /* 1. 输出点 GPIO 时钟(DIR 点按需配置时使用)。 */ | |||||
| __HAL_RCC_GPIOF_CLK_ENABLE(); | __HAL_RCC_GPIOF_CLK_ENABLE(); | ||||
| __HAL_RCC_GPIOI_CLK_ENABLE(); | __HAL_RCC_GPIOI_CLK_ENABLE(); | ||||
| __HAL_RCC_GPIOE_CLK_ENABLE(); | __HAL_RCC_GPIOE_CLK_ENABLE(); | ||||
| @@ -305,22 +368,8 @@ PLSR_RESULT PlsrHwInit(void) | |||||
| __HAL_RCC_GPIOH_CLK_ENABLE(); | __HAL_RCC_GPIOH_CLK_ENABLE(); | ||||
| __HAL_RCC_GPIOB_CLK_ENABLE(); | __HAL_RCC_GPIOB_CLK_ENABLE(); | ||||
| /* 2. 全部输出点上电安全电平(推挽输出、低)。 */ | |||||
| gpio.Mode = GPIO_MODE_OUTPUT_PP; | |||||
| gpio.Pull = GPIO_NOPULL; | |||||
| gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; | |||||
| for (point = 0U; point < PLSR_HW_OUTPUT_POINT_COUNT; point++) | |||||
| { | |||||
| if (PlsrHwOutputPins[point].port != NULL) | |||||
| { | |||||
| gpio.Pin = PlsrHwOutputPins[point].pin; | |||||
| HAL_GPIO_WritePin(PlsrHwOutputPins[point].port, | |||||
| PlsrHwOutputPins[point].pin, | |||||
| GPIO_PIN_RESET); | |||||
| HAL_GPIO_Init(PlsrHwOutputPins[point].port, | |||||
| &gpio); | |||||
| } | |||||
| } | |||||
| /* 2. 上电安全:输出点保持复位默认高阻(漏型输出 = 截止 = OFF)。 | |||||
| * 不驱动任何 Y 点,DIR 点仅在 PlsrHwSetDirLevel 时按需配置。 */ | |||||
| /* 3. 定时器时钟。 */ | /* 3. 定时器时钟。 */ | ||||
| __HAL_RCC_TIM10_CLK_ENABLE(); | __HAL_RCC_TIM10_CLK_ENABLE(); | ||||
| @@ -329,8 +378,10 @@ PLSR_RESULT PlsrHwInit(void) | |||||
| __HAL_RCC_TIM14_CLK_ENABLE(); | __HAL_RCC_TIM14_CLK_ENABLE(); | ||||
| /* 4. 脉冲点切定时器复用(PF6/7=AF3、PF8/9=AF9)。 | /* 4. 脉冲点切定时器复用(PF6/7=AF3、PF8/9=AF9)。 | ||||
| * 定时器通道尚未使能(CC1E=0),输出为无效电平(低),无毛刺。 */ | |||||
| * 定时器通道尚未使能(CC1E=0),输出级断开,无毛刺。 */ | |||||
| gpio.Mode = GPIO_MODE_AF_PP; | gpio.Mode = GPIO_MODE_AF_PP; | ||||
| gpio.Pull = GPIO_NOPULL; | |||||
| gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; | |||||
| gpio.Pin = GPIO_PIN_6 | GPIO_PIN_7; | gpio.Pin = GPIO_PIN_6 | GPIO_PIN_7; | ||||
| gpio.Alternate = 3U; | gpio.Alternate = 3U; | ||||
| HAL_GPIO_Init(GPIOF, &gpio); | HAL_GPIO_Init(GPIOF, &gpio); | ||||
| @@ -355,6 +406,7 @@ PLSR_RESULT PlsrHwInit(void) | |||||
| PLSR_RESULT PlsrHwStartPulse(uint8_t axis, const PLSR_HW_START_PARAMS *params) | PLSR_RESULT PlsrHwStartPulse(uint8_t axis, const PLSR_HW_START_PARAMS *params) | ||||
| { | { | ||||
| PLSR_HW_AXIS_STATE *state; | PLSR_HW_AXIS_STATE *state; | ||||
| uint8_t directionChanged; | |||||
| if ((axis >= PLSR_HW_AXIS_COUNT) || (params == NULL)) | if ((axis >= PLSR_HW_AXIS_COUNT) || (params == NULL)) | ||||
| { | { | ||||
| @@ -370,13 +422,20 @@ PLSR_RESULT PlsrHwStartPulse(uint8_t axis, const PLSR_HW_START_PARAMS *params) | |||||
| return PLSR_RESULT_BUSY; | return PLSR_RESULT_BUSY; | ||||
| } | } | ||||
| /* 方向延时只在方向发生变化时生效(首次启动/换向/换方向点): | |||||
| * 段间同向衔接不再等待 10ms,直接进入 PWM 待启动。 */ | |||||
| directionChanged = (state->directionPoint == PLSR_HW_DIR_POINT_NONE) | |||||
| || (state->directionPoint != params->directionPoint) | |||||
| || (state->directionPositive != params->directionPositive); | |||||
| state->targetPulses = params->targetPulses; | state->targetPulses = params->targetPulses; | ||||
| state->emittedPulses = 0; | state->emittedPulses = 0; | ||||
| state->currentFrequencyHz = params->frequencyHz; | state->currentFrequencyHz = params->frequencyHz; | ||||
| state->directionPoint = params->directionPoint; | state->directionPoint = params->directionPoint; | ||||
| state->directionDelayRemainingMs = params->directionDelayMs; | |||||
| state->directionDelayRemainingMs = | |||||
| (directionChanged != 0U) ? params->directionDelayMs : 0U; | |||||
| PlsrHwSetDirLevel(axis, params->directionPositive); | PlsrHwSetDirLevel(axis, params->directionPositive); | ||||
| state->state = (params->directionDelayMs > 0U) | |||||
| state->state = (state->directionDelayRemainingMs > 0U) | |||||
| ? PLSR_HW_STATE_DIR_SETTLING | ? PLSR_HW_STATE_DIR_SETTLING | ||||
| : PLSR_HW_STATE_PWM_PENDING; | : PLSR_HW_STATE_PWM_PENDING; | ||||
| return PLSR_RESULT_OK; | return PLSR_RESULT_OK; | ||||
| @@ -396,7 +455,8 @@ PLSR_RESULT PlsrHwSetFrequency(uint8_t axis, uint32_t frequencyHz) | |||||
| { | { | ||||
| if (frequencyHz > 0UL) | if (frequencyHz > 0UL) | ||||
| { | { | ||||
| PlsrHwStartPwmTimer(axis, frequencyHz); | |||||
| /* 运行中调频:预装载写入,更新事件时生效,不触碰使能位。 */ | |||||
| PlsrHwConfigurePwm(axis, frequencyHz); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -406,7 +466,8 @@ PLSR_RESULT PlsrHwSetFrequency(uint8_t axis, uint32_t frequencyHz) | |||||
| else if ((state->state == PLSR_HW_STATE_PWM_PENDING) | else if ((state->state == PLSR_HW_STATE_PWM_PENDING) | ||||
| && (frequencyHz > 0UL)) | && (frequencyHz > 0UL)) | ||||
| { | { | ||||
| PlsrHwStartPwmTimer(axis, frequencyHz); | |||||
| PlsrHwConfigurePwm(axis, frequencyHz); | |||||
| PlsrHwPwmBegin(axis); | |||||
| state->state = PLSR_HW_STATE_RUNNING; | state->state = PLSR_HW_STATE_RUNNING; | ||||
| } | } | ||||
| return PLSR_RESULT_OK; | return PLSR_RESULT_OK; | ||||
| @@ -481,7 +542,8 @@ void PlsrHwTick(uint8_t axis) | |||||
| case PLSR_HW_STATE_PWM_PENDING: | case PLSR_HW_STATE_PWM_PENDING: | ||||
| if (state->currentFrequencyHz > 0UL) | if (state->currentFrequencyHz > 0UL) | ||||
| { | { | ||||
| PlsrHwStartPwmTimer(axis, state->currentFrequencyHz); | |||||
| PlsrHwConfigurePwm(axis, state->currentFrequencyHz); | |||||
| PlsrHwPwmBegin(axis); | |||||
| state->state = PLSR_HW_STATE_RUNNING; | state->state = PLSR_HW_STATE_RUNNING; | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -528,6 +590,16 @@ uint32_t PlsrHwTestGetCcr(uint8_t axis) | |||||
| return PlsrHwTimers[axis].ccr1; | return PlsrHwTimers[axis].ccr1; | ||||
| } | } | ||||
| uint32_t PlsrHwTestGetCcmr1(uint8_t axis) | |||||
| { | |||||
| return PlsrHwTimers[axis].ccmr1; | |||||
| } | |||||
| uint32_t PlsrHwTestGetCr1(uint8_t axis) | |||||
| { | |||||
| return PlsrHwTimers[axis].cr1; | |||||
| } | |||||
| uint32_t PlsrHwTestGetPsc(uint8_t axis) | uint32_t PlsrHwTestGetPsc(uint8_t axis) | ||||
| { | { | ||||
| return PlsrHwTimers[axis].psc; | return PlsrHwTimers[axis].psc; | ||||
| @@ -6,12 +6,15 @@ | |||||
| /* 上电自测(验证后可删除): | /* 上电自测(验证后可删除): | ||||
| * - 方向端子设为 Y4(SFD906=4),其余用出厂默认参数(K1) | * - 方向端子设为 Y4(SFD906=4),其余用出厂默认参数(K1) | ||||
| * - 任务:Q0 发 1 段 2000Hz / 1000 脉冲,H00 完成,梯形曲线 | |||||
| * - 任务:Q0 发 3 段脉冲(H00 完成,顺序衔接),同时验证段间跳转: | |||||
| * 段1:2000Hz / 1000 脉冲(已单段验证) | |||||
| * 段2:5000Hz / 6000 脉冲(加速 500ms + 匀速 200ms + 减速 500ms) | |||||
| * 段3:1000Hz / 500 脉冲 | |||||
| * 数据源为静态数组,仅自测使用(正式 D 设备适配器见 Modbus 阶段)。 */ | * 数据源为静态数组,仅自测使用(正式 D 设备适配器见 Modbus 阶段)。 */ | ||||
| #define SELF_TEST_WORD_CAPACITY (64U) | #define SELF_TEST_WORD_CAPACITY (64U) | ||||
| #define SELF_TEST_S0_BASE (10U) | #define SELF_TEST_S0_BASE (10U) | ||||
| #define SELF_TEST_S1_BASE (30U) | |||||
| #define SELF_TEST_S1_BASE (60U) | |||||
| #define SELF_TEST_DIR_POINT (4U) | #define SELF_TEST_DIR_POINT (4U) | ||||
| static uint16_t SelfTestWords[3][SELF_TEST_WORD_CAPACITY]; | static uint16_t SelfTestWords[3][SELF_TEST_WORD_CAPACITY]; | ||||
| @@ -76,10 +79,14 @@ PLSR_RESULT PlsrSelfTestQueue(void) | |||||
| /* 方向端子 Y4(PULSE/DIR 模式必需,接线参数)。 */ | /* 方向端子 Y4(PULSE/DIR 模式必需,接线参数)。 */ | ||||
| (void)PlcDeviceWriteSfd(906U, SELF_TEST_DIR_POINT); | (void)PlcDeviceWriteSfd(906U, SELF_TEST_DIR_POINT); | ||||
| /* S0:1 段,2000Hz / 1000 脉冲,H00 完成,顺序跳转。 */ | |||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 1U); | |||||
| /* S0:3 段,H00 完成,顺序跳转。 */ | |||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 3U); | |||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 10U, 2000UL); | SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 10U, 2000UL); | ||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 12U, 1000UL); | SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 12U, 1000UL); | ||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 20U, 5000UL); | |||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 22U, 6000UL); | |||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 30U, 1000UL); | |||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 32U, 500UL); | |||||
| /* S1:相对模式,起始段 0(=段1)。 */ | /* S1:相对模式,起始段 0(=段1)。 */ | ||||
| SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U); | SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U); | ||||
| @@ -189,6 +189,25 @@ static void TestDirDelaySequence(void) | |||||
| CHECK(PlsrHwTestGetArr(0U) == arr); | CHECK(PlsrHwTestGetArr(0U) == arr); | ||||
| CHECK(PlsrHwTestGetPsc(0U) == psc); | CHECK(PlsrHwTestGetPsc(0U) == psc); | ||||
| CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL); | CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL); | ||||
| /* PWM 模式 1(OC1M=110):复位后 CCMR1=0 冻结,无此配置输出恒定电平。 */ | |||||
| CHECK((PlsrHwTestGetCcmr1(0U) & 0x70UL) == 0x60UL); | |||||
| /* ARR/CCR 预装载(ARPE=CR1 bit7,OC1PE=CCMR1 bit3): | |||||
| * 运行中调频不产生提前回绕,否则加速段多出 ~ln(f1/f0) 个假脉冲。 */ | |||||
| CHECK((PlsrHwTestGetCr1(0U) & 0x80UL) == 0x80UL); | |||||
| CHECK((PlsrHwTestGetCcmr1(0U) & 0x08UL) == 0x08UL); | |||||
| /* 段间同向衔接:方向不变时跳过方向延时,直接进入 PWM 待启动。 */ | |||||
| CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK); | |||||
| params.targetPulses = 50; | |||||
| CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK); | |||||
| CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING); | |||||
| CHECK(PlsrHwTestGetDirLevel(0U) == 1U); | |||||
| /* 反向时方向延时仍生效。 */ | |||||
| params.directionPositive = 0U; | |||||
| CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK); | |||||
| CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING); | |||||
| CHECK(PlsrHwTestGetDirLevel(0U) == 0U); | |||||
| } | } | ||||
| static void TestZeroFrequencyWaits(void) | static void TestZeroFrequencyWaits(void) | ||||