资讯动态

CANoe+VH6501采样点测试:硬件级bit扰动定位原理与CAPL实现

发布时间:2026/10/26 14:22:35 来源:尧图企业网站定制
简介本资源是一份面向汽车电子测试工程师与CAN总线开发人员的专业级采样点鲁棒性验证方案聚焦于利用CANoe软件与VH6501硬件协同开展DUT采样点定位与抗干扰能力评估。核心解决CAN节点在噪声环境下因采样时刻偏移导致Form Error误判的关键问题适用于ECU通信可靠性验证、CAN物理层调试及功能安全预研等场景。压缩包为单文件PDF文档365KB完整涵盖测试原理、CAPL脚本源码含变量定义、on errorFrame事件处理、干扰报文序列控制逻辑、VH6501通道配置图示及影响因素分析如CRC Delimiter/ACK Slot位长微调机制、Error Active状态维持策略。文档由Vector中国技术团队编写并发布内容严谨、步骤可复现已获7639人学习下载是掌握CANoeVH6501联合测试方法不可多得的实操型参考资料。1. CANoe VH6501 采样点测试不是“调个参数看报错”它是一套闭环扰动—捕获—定位的硬核时序工程你有没有试过在 CANoe 里点开 VH6501 的 CAPL 测试模块把一段看似完整的脚本拖进去一运行——DUT 没报错、CANoe 没抓到 RxErr、VH6501 界面状态灯绿得刺眼但采样点数值始终为 0这不是脚本写错了而是你还没真正理解VH6501 的采样点测试本质是用硬件级 bit 级扰动在真实物理层上“逼出”DUT 的采样窗口边界。它不依赖 DUT 自报寄存器值也不靠示波器目测边沿而是让 DUT 自己用 Form Error 告诉你“我的采样点就卡在这个 bit 段里”。这套方法由 Vector 中国团队实车验证并固化为标准流程核心价值在于——可复现、可量化、可映射到 ISO 11898-1 的 TQ 分配模型。适合正在做 CAN 物理层兼容性认证、ECU 抗干扰鲁棒性摸底、或被 OEM 要求提供采样点实测报告的嵌入式工程师、测试工程师和系统集成工程师。别再拿“CANoe 能抓错误帧”当万能解真正的门槛在 CAPL 对 VH6501 干扰序列的原子级控制、对 errorFrame 事件的精准计数逻辑、以及对 DUT 错误状态机的主动维稳——这三者缺一不可。2. 从原理到 CAPL为什么必须用 CRC Delimiter 缩短 ACK Slot 延长组合扰动2.1 采样点定位的物理层逻辑不是“加噪声”而是“造确定性边沿偏移”CAN 总线采样点Sample Point定义为在一个位时间Bit Time内控制器对总线电平进行采样的时刻通常以 TQTime Quantum为单位表示为占整个位时间的百分比如 75%。关键点在于——采样点位置由 DUT 的 CAN 控制器寄存器配置决定但它的实际生效效果必须通过总线电平在该时刻的显隐性来验证。VH6501 的设计精妙之处在于它不直接修改 DUT 的寄存器而是利用 CAN 协议帧结构的刚性约束制造一个“可控漂移的显性边沿”。原文明确指出“每次干扰循环发送结束微调干扰报文的【CRC Delimiter】位长度使其逐次缩短并将后一位【ACK Slot】的长度增加。导致的结果为后一位【ACK Slot 0】前移。” 这句话是整套方法的物理基石。我们来拆解CRC Delimiter是 CAN 帧中固定为隐性recessive逻辑 1的 1-bit 字段位于 CRC 字段之后、ACK 字段之前ACK Slot是紧随其后的 1-bit 字段DUT 在此位置发送显性应答dominant逻辑 0而总线上其他节点包括 VH6501默认发送隐性即“不驱动”形成“线与”效果VH6501 的干扰报文ID0x0被强制设置为ACK Slot 位也输出显性“0”文档强调“为系统默认无需额外特殊设置”这就打破了协议默认行为使该位成为总线上的强驱动源当 VH6501缩短 CRC Delimiter 长度例如从标准 1TQ 减为 0.9375TQ同时等量延长 ACK Slot 长度0.0625TQ物理效果是原本在 CRC Delimiter 结束处才出现的、由 VH6501 主动拉低的显性电平提前了 0.0625TQ 出现在总线上这个“提前的显性边沿”会像一把探针逐步扫过 DUT 的采样窗口。一旦该边沿在 DUT 执行采样动作的瞬间被识别为“显性”而协议要求此处应为“隐性”CRC Delimiter 结束后应为隐性等待 DUT 应答DUT 即判定为 Form Error格式错误立即发送主动错误帧Active Error Flag。提示这个“0.0625TQ”的步进值不是随意定的。它对应 VH6501 最小可调分辨率6.25ns而典型 CAN 波特率 500kbps 下1TQ 1/500k 2000ns故 6.25ns 2000ns × 0.003125 0.3125% of Bit Time。这意味着每步进一次干扰边沿前移约 0.3% 的位时间足够精细地定位采样点区间。2.2 CAPL 程序的核心控制流三个事件钩子如何协同完成闭环测试CAPL 脚本绝非线性执行而是基于 CANoe 事件驱动模型构建的精密状态机。本程序围绕on errorFrame、on message 0x1、on sysvar ...::Trigger::State三个关键钩子展开形成“扰动→捕获→维稳→再扰动”的闭环。我们逐段解析其不可替代性on errorFrame { if(this.msgChannel sysvar::CANDisturbanceInterface1::ChannelNo) { errfrmcount; if((errfrmcount 1) (first_error_occur 0)) { first_err_bit_length frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0]; first_error_occur 1; write(First error frame occurs.); } if(errfrmcount repetition_times_in_one_cycle) { ten_error_occur 1; testSupplyTextEvent(spTestDone); } } }这段代码是采样点定位的“判决器”。它只监听 VH6501 所在通道sysvar::CANDisturbanceInterface1::ChannelNo的错误帧。关键逻辑errfrmcount统计当前扰动周期内捕获的错误帧数量first_error_occur标记首次出错时的CRCDelimiter当前长度即边沿前移量这是计算采样点下限的原始数据repetition_times_in_one_cycle 10默认值意味着必须连续捕获到 10 次错误帧才认为该扰动强度已稳定触发 DUT 的采样点边界避免单次偶发干扰导致误判。testSupplyTextEvent(spTestDone)是向主测试例SamplePointTest_forVH6501()发送完成信号触发下一步。on message 0x1 { if(MsgCntKeepErrorActive CountMsgKeepErrorActive) { MsgCntKeepErrorActive; output(Keep_DUT_ErrorActive); } else { ActivateTriggerAgain(); } }这段是DUT 错误状态维稳的“生命线”。DUT 在发送主动错误帧后错误计数器TEC/REC会累加。若连续发送 16 次主动错误帧DUT 将进入 Error Passive 状态此时其错误帧为被动错误帧Passive Error Flag波形特征弱、不易被 CANoe 可靠捕获文档第 3 节明确指出“passive error frame is not easily to be observed and identified”。因此程序强制在每个扰动周期结束后发送CountMsgKeepErrorActive 30次 ID0x1 的正常报文。这些报文被 DUT 正常接收无错误从而降低其 REC确保其始终维持在 Error Active 状态保证后续错误帧的可观测性。else分支调用ActivateTriggerAgain()正是启动下一轮更激进扰动的开关。void ActivateTriggerAgain() { if(ten_error_occur 0) { errfrmcount 0; --frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0]; frameSequence.AckSlot.BitSequence[0].segmentLength[0]; result canDisturbanceTriggerEnable(sysvar::CANDisturbanceInterface1::DeviceNo, frameTrigger, frameSequence, repetitions); // ... error handling } }这是扰动强度迭代的“执行器”。它只在ten_error_occur 0即本轮未达到 10 次错误时执行意味着只要 DUT 还没稳定报错就继续前移干扰边沿。--和操作直接修改 VH6501 内部帧序列的 bit 级时序参数canDisturbanceTriggerEnable()则将新参数下发至硬件。注意result返回值必须检查1表示成功非1则需排查硬件连接或 sysvar 配置。2.3 Testcase 主入口初始化、触发与结果计算的黄金三角testcase SamplePointTest_forVH6501()是整个测试的“大脑”它完成三件不可妥协的事环境初始化重置所有计数器first_error_occur,ten_error_occur,errfrmcount确保每次测试从干净状态开始扰动序列绑定frameSequence.SetMessage(sysvar::CANDisturbanceInterface1::DeviceNo, spTestMsg)将 ID0x0 的干扰报文spTestMsg绑定到 VH6501 设备frameTrigger.SetMessage(triggerMessage, ...)将 ID0x100 的触发报文triggerMessage绑定为扰动启动条件触发时机精控frameTrigger.TriggerFieldOffset 9是玄学级参数。它指定扰动在触发报文0x100的第 9 个 bit 位置启动。查阅 CAN 帧结构SOF(1)ID(11)RTR(1)IDE(1)r0(1)DLC(4)Data(0~64)CRC(15)CRC Delim(1)ACK(1)ACK Delim(1)EOF(7)IFS(3)。Offset9意味着扰动起始点落在 ID 字段末尾附近ID 共 11bitoffset 9 即第 10bit这确保了干扰发生在 DUT 发送完 ID、正准备发送 RTR/IDE 的空闲间隙避开总线竞争提高扰动成功率。最终结果计算逻辑藏在testWaitForTextEvent(spTestDone, 10000)之后if(result 1) { write(frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0] %d , sample point lies in %f%%~%f%%, frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0], (frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0] * 100.00) / frameSequence.DLC.BitSequence[1].segmentLength[0], (first_err_bit_length * 100.00) / frameSequence.DLC.BitSequence[1].segmentLength[0]); }这里frameSequence.DLC.BitSequence[1].segmentLength[0]是 DLC 字段的长度单位TQ作为整个位时间的代理基准因 DLC 位置固定且易获取。计算出的两个百分比分别对应采样点上限current CRCDelimiter length / DLC length * 100%—— 即最后一次未触发错误时的边沿位置采样点下限first_err_bit_length / DLC length * 100%—— 即首次触发错误时的边沿位置。 二者构成 DUT 采样点的可信区间。例如若输出为sample point lies in 72.3%~74.8%则可断言 DUT 采样点落在此范围内符合多数 OEM 要求的 75%±5% 规范。3. VH6501 通道与 CANoe 环境配置5 个必须死磕的硬性参数3.1 VH6501 硬件接口配置Sysvar 是唯一真相源VH6501 的所有行为均由 CANoe 系统变量Sysvar控制而非图形界面点击。任何界面操作若未同步更新 Sysvar均无效。以下是必须在 CANoe 的System Variables窗口View → System Variables中手动核验的 5 个核心 Sysvar 路径及其合法值Sysvar 路径必须值作用说明不匹配后果sysvar::CANDisturbanceInterface1::DeviceNo0或1取决于 VH6501 物理连接的 USB 口编号指定控制哪个 VH6501 设备canDisturbanceTriggerEnable()调用失败返回0sysvar::CANDisturbanceInterface1::ChannelNo1若 VH6501 接在 CANoe 的 Channel 1指定 VH6501 所在的 CAN 通道号on errorFrame无法过滤到目标通道的错误帧sysvar::CANDisturbanceInterface1::Trigger::State0Idle或1Running监控 VH6501 当前状态用于on sysvar事件无法触发ActivateTriggerAgain()测试卡死在首周期sysvar::CanDisturbance::Enums::FieldType::EndOfFrame2该枚举值在 CAPL 中已预定义frameTrigger.TriggerFieldType的合法值表示在帧结束处触发若设为0StartOfFrame或1MiddleOfFrame扰动时机完全错误sysvar::CANDisturbanceInterface1::Trigger::Repetitions10与 CAPL 中repetition_times_in_one_cycle严格一致VH6501 硬件层面的单次循环重复次数软件计数errfrmcount与硬件实际发送次数错位ten_error_occur永远不置位注意DeviceNo和ChannelNo的值必须与 VH6501 实际物理连接一一对应。常见翻车点VH6501 插在电脑 USB2.0 口但 CANoe 里DeviceNo误设为2对应 USB3.0 口导致所有canDisturbance*API 调用静默失败。务必在 CANoe 启动后先打开Hardware Configuration窗口确认 VH6501 设备已被正确识别并分配了正确的Device Index。3.2 CANoe 通道基础设置波特率与采样点的“双重锁定”VH6501 的扰动精度高度依赖 CANoe 通道的底层时序精度。以下设置必须在 CANoe 的Network Hardware配置中完成Configuration → Network Hardware → [Your CAN Channel] → SettingsBaudrate (kbps)必须与 DUT 实际运行波特率完全一致如 500、250、125。误差 0.1% 即可导致扰动边沿漂移测试失效。Sample Point (%)必须设为 50%文档原文“CANoe 测试逻辑通道VH6501 所在通道采样点须选取靠前位置e.g. 50%”。原因在于CANoe 作为监控方其自身采样点若设得靠后如 80%可能在 VH6501 干扰边沿到达前就已采样到“错误”电平导致 CANoe 误报RxErr污染测试数据。50% 是平衡点确保 CANoe 采样发生在总线电平相对稳定的中间区域。TQ Cycles (Number of Time Quanta)必须设为 16文档原文“建议将 VH6501 的采样点设置为 50%TQ 数BTL Cycles为 16”。TQ 数决定了位时间的离散化粒度。16 TQ 是 CAN 标准推荐值也是 VH6501 内部时序引擎的默认基准。若设为 8 或 32segmentLength[0]的单位ns换算关系将改变--操作的实际步进值失真。SJW (Synchronization Jump Width)必须设为 4文档原文同上。SJW 影响 CAN 控制器对相位误差的容忍度。设为 4 是为了匹配 VH6501 扰动引入的相位跳变范围防止 DUT 因过度重同步而掩盖真实的采样点响应。提示这些参数一旦设定必须重启 CANoe 才能生效。切勿在运行测试时动态修改否则 VH6501 硬件时钟与 CANoe 软件时钟不同步canDisturbanceTriggerEnable()可能返回0或触发不可预测的硬件异常。3.3 CAPL Test Module 节点部署路径与权限的隐形陷阱CAPL 程序必须部署在特定节点否则事件钩子无法注册。正确路径是Test Setup → Test Modules → [Right Click] → Insert Node → CAPL Test Module。然后将.can文件拖入该节点。常见错误部署位置及后果❌ 部署在Simulation Setup → Nodes下on errorFrame和on message事件完全不触发因为 Simulation Nodes 不处理总线错误帧和消息事件❌ 部署在Test Setup → Test Modules的根节点下未创建子节点testcase无法被识别maintest()不执行❌ 部署后未右键该 CAPL 节点 →Properties→ 勾选Activate程序处于禁用状态所有代码静默❌Properties→General→Execution Mode未设为Automatic需要手动点击Run无法实现自动化循环测试。此外#includes {}块为空是故意为之。VH6501 的 CAPL APIcanDisturbanceTriggerEnable等是 CANoe 内置函数无需额外 include 头文件。若误加#include CANoe.h等不存在的文件编译直接报错。4. 避坑指南5 条血泪经验总结的高频翻车现场4.1 现象canDisturbanceTriggerEnable()返回0write输出Enable trigger error Result 0原因sysvar::CANDisturbanceInterface1::DeviceNo或sysvar::CANDisturbanceInterface1::ChannelNo的值与 VH6501 实际物理连接不匹配或 VH6501 设备未被 CANoe 正确识别USB 连接松动、驱动未安装、设备管理器显示黄色感叹号。解决第一步关闭 CANoe拔插 VH6501 USB 线观察 Windows 设备管理器中Vector VH6501是否稳定显示第二步打开 CANoeHardware Configuration确认 VH6501 设备状态为OK并记录其Device Index第三步在System Variables中将DeviceNo设为该IndexChannelNo设为 VH6501 所连 CAN 通道号如1第四步重启 CANoe 后重试。4.2 现象on errorFrame完全不触发errfrmcount始终为0但 CANoe 的 Trace 窗口可见 DUT 发送的主动错误帧原因on errorFrame事件默认监听所有通道但脚本中if(this.msgChannel sysvar::CANDisturbanceInterface1::ChannelNo)的判断条件失效。根本原因是sysvar::CANDisturbanceInterface1::ChannelNo的值被错误修改如从1改为2或 VH6501 实际连接在 Channel 2 但 Sysvar 仍为1。解决在on errorFrame钩子开头添加调试语句write(Error Frame on Channel: %d, Target Channel: %d, this.msgChannel, sysvar::CANDisturbanceInterface1::ChannelNo);运行后对比输出。若两者不等立即修正 Sysvar。切记this.msgChannel是 CANoe 内部标识符sysvar::CANDisturbanceInterface1::ChannelNo是用户定义的逻辑通道号二者必须严格一致。4.3 现象测试运行几秒后卡住ten_error_occur始终为0errfrmcount在1到3之间波动无法累积到10原因DUT 进入了 Error Passive 状态导致其发送的错误帧为被动错误帧Passive Error Flag其波形幅度小、持续时间短VH6501 或 CANoe 的硬件收发器无法可靠捕获on errorFrame事件丢失。根源是on message 0x1发送的维稳报文未被 DUT 正确接收如 DUT 的接收缓冲区溢出、ID 过滤器未放行 0x1、或 DUT 正忙于处理其他高优先级任务。解决首先在 CANoe Trace 窗口开启Show Error Frames确认看到的是Active Error还是Passive Error。若是后者立即检查 DUT 的 CAN 接收配置其次将CountMsgKeepErrorActive从30提高到50并确保on message 0x1的output()调用频率足够高可在output()后加delay(100)确保报文间隔最后用示波器实测 DUT 的 CAN_H/CAN_L 波形确认其错误帧是否为标准主动错误帧6 个连续显性位。4.4 现象testWaitForTextEvent(spTestDone, 10000)超时返回0write输出Result 0测试例退出原因testSupplyTextEvent(spTestDone)未被成功调用。最常见原因是on errorFrame中ten_error_occur 1被置位但testSupplyTextEvent()调用被if条件包裹而该条件因errfrmcount计数逻辑错误未满足。例如repetition_times_in_one_cycle在 CAPL 中定义为10但 VH6501 硬件 Sysvar 中Trigger::Repetitions被设为5导致硬件只发送 5 次干扰errfrmcount最大只能到5永远达不到10。解决在on errorFrame的if(errfrmcount repetition_times_in_one_cycle)前添加write(errfrmcount %d, target %d, errfrmcount, repetition_times_in_one_cycle);实时打印。若发现errfrmcount无法增长检查on sysvar ...::Trigger::State事件是否被触发在on sysvar内加write(Trigger State Changed to: %d, sysvar::CANDisturbanceInterface1::Trigger::State);确认硬件循环是否真正结束。终极方案统一所有10相关参数确保 CAPL 变量、Sysvar、硬件配置三者完全一致。4.5 现象测试结果输出的采样点区间如72.3%~74.8%与 DUT 数据手册标称值如75%偏差超过±3%且多次复测结果发散原因物理层干扰源未被隔离。文档第 3 节明确指出“CAN 线长度会影响采样点测试的结果”、“CAN 由于并非实时进行同步且有通讯距离带来的延迟影响”。这意味着测试环境中的线缆长度、终端电阻匹配度、邻近电源线/电机电缆的电磁干扰都会引入额外的传播延迟和信号畸变叠加在 VH6501 的精确扰动上导致测量值漂移。解决必须在屏蔽实验室环境下进行测试。使用标准 120Ω 双绞线长度严格控制在0.5m模拟 ECU 近端连接或2.0m模拟整车线束典型长度两端加装 120Ω 终端电阻DUT 与 VH6501 的供电必须使用同一台高质量线性电源禁止共用开关电源测试全程关闭手机、Wi-Fi、蓝牙设备。若条件允许用示波器抓取 DUT 的 TX 引脚波形确认其上升/下降时间、过冲、振铃均在规范内排除 DUT 自身驱动能力缺陷。5. 进阶技巧用三次扫描法交叉验证采样点并建立你的误差补偿模型5.1 为什么单次扫描不够—— 理解“首次错误”与“稳定错误”的物理意义差异CAPL 程序默认输出的first_err_bit_length首次错误时的 CRC Delimiter 长度和current第十次错误时的长度构成一个区间但这只是最简模型。实际上DUT 的采样点响应存在固有迟滞和统计波动。first_err_bit_length对应的是采样点下限的保守估计——它捕捉到的是 DUT 在极少数情况下如温度略低、电压略高最早可能出错的边沿位置而current对应的是采样点上限的工程估计——它要求 DUT 在连续 10 次扰动下都稳定报错反映了其在常规工况下的鲁棒边界。二者之差如2.5%正是 DUT 采样点的“工艺容差带”。要获得更高置信度的结果我一般会执行三次独立扫描每次使用不同的初始扰动强度和步进策略扫描类型初始CRCDelimiter长度步进值 (TQ)扫描目标用途粗扫 (Coarse)16标准值-0.25即 -500ns快速定位错误发生的大致区间如65%~85%缩小后续精扫范围避免盲目遍历精扫 (Fine)first_err_bit_lengthfrom Coarse 0.1-0.0625即 -125nsVH6501 最小步进获取高分辨率的上下限如72.3%~74.8%生成最终报告数据反向扫 (Reverse)first_err_bit_lengthfrom Fine -0.10.0625从错误态往回退观察 DUT 从错误恢复正常的临界点如71.5%验证迟滞效应计算 hysteresis提示-0.25和0.0625这些值需换算为segmentLength[0]的整数。例如1TQ2000ns则-0.25TQ -500ns而 VH6501 的最小分辨率为6.25ns故-500 / 6.25 -80。因此--操作需改为frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0] - 80;。务必在修改步进前用write(1 TQ %d units, 2000 / 6.25);打印换算系数避免手算错误。5.2 构建你的误差补偿表线长、温度、电压的三维校准文档第 3 节坦诚指出“CAN 线长度会影响采样点测试的结果”、“CAN 由于并非实时进行同步...波动属于正常现象”。这意味着一份脱离具体测试环境的“绝对采样点值”没有工程意义。我所在某公司实验室的做法是为每一款被测 DUT 建立专属的误差补偿表Compensation Table。该表是一个三维查找表3D LUT坐标轴为X 轴CAN 总线物理长度单位米覆盖0.3mECU 板级到5.0m整车最长分支Y 轴环境温度单位℃覆盖-40℃冷凝到85℃引擎舱Z 轴DUT 供电电压单位V覆盖5.5V欠压到16.0V抛负载。表内存储的是在该(Length, Temp, Voltage)组合下实测采样点区间中值(lower upper) / 2相对于标准 0.5m/25℃/13.5V 条件下的偏移量Δ%。例如某 DUT 在2.0m/70℃/14.0V下的精扫结果为71.2%~73.6%中值72.4%而在标准条件下为74.5%则补偿值Δ 72.4 - 74.5 -2.1%。当 OEM 要求提供“整车工况下采样点”时我们直接查表将标准报告值74.5%加上-2.1%得出72.4%并附上补偿表作为附件。这比单纯报告一个数字更有说服力。实施要点补偿表的生成需耗时。我们采用“正交实验法”选取3×3×327个关键点进行实测用双线性插值填充其余点。所有测试数据均用 Python 脚本自动采集、绘图、拟合并生成 CSV 和 PDF 报告。脚本核心逻辑是读取 CANoe 的Write日志用正则提取sample point lies in X.X%~Y.Y%计算中值存入 Pandas DataFrame。5.3 用 Python 自动化解析日志告别手动抄录CAPL 的write()输出会写入 CANoe 的Write Window但手动复制粘贴极易出错。我写的 Python 脚本parse_sp_log.py能自动完成监控 CANoe 日志文件*.log或Write Window导出的文本用正则rsample point lies in ([\d.])%~([\d.])%提取上下限计算中值、区间宽度、三次扫描的平均值与标准差生成 Markdown 报告包含趋势图Matplotlib和补偿建议。import re import pandas as pd import matplotlib.pyplot as plt def parse_sp_log(log_file): with open(log_file, r, encodinggbk) as f: log_text f.read() # 匹配所有采样点行 pattern rsample point lies in ([\d.])%~([\d.])% matches re.findall(pattern, log_text) if not matches: print(No SP data found!) return # 转为 DataFrame df pd.DataFrame(matches, columns[Lower, Upper]) df df.astype(float) df[Mid] (df[Lower] df[Upper]) / 2 df[Width] df[Upper] - df[Lower] # 统计 print(fScans: {len(df)}) print(fMean Mid: {df[Mid].mean():.3f}%) print(fStd Dev: {df[Mid].std():.3f}%) print(fMean Width: {df[Width].mean():.3f}%) # 绘图 plt.figure(figsize(10,4)) plt.subplot(1,2,1 p a hrefhttps://download.csdn.net/download/qq_36407982/76415906 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑