拓冰建站拓冰建站
首页 / 资讯中心 / 正文

51单片机驱动VL53L0X:ToF测距与XTalk校准详解

简介ToF激光测距凭借毫米级精度和不受目标颜色影响的特性成为智能感应设备中的热门方案。ST的VL53L0X作为代表性传感器内部虽固化了出厂校准但外置外壳或玻璃带来的串扰信号会让近距离读数明显漂移。本文从光子飞行时间与SPAD接收原理切入介绍在标准89C52上通过软件模拟I2C实现单次与连续测距的寄存器级操作重点解析XTalk校准和偏移校准的落地方案包括EEPROM保存标定数据、三点线性插值修正以及免浮点滑动滤波。面向倒车雷达、电子尺、智能垃圾桶等51单片机课程设计场景提供一套兼顾精度校准与工程调试的完整实践思路。无论你刚接触VL53L0X还是正在优化现有测距程序都能从中找到解决读数漂移、距离跳变和故障定位的有效方法。1. 带 51 单片机的 VL53L0X 测距程序为什么“校准”比“读取”更值得看做 51 单片机课程设计的人拿到 VL53L0X 之后第一反应往往是去搜“VL53L0X 51 单片机程序源码”然后复制一段 I2C 代码烧进去发现距离确实能出来但换个外壳或者把模块从洞洞板挪到亚克力面板后面读数就漂了十几毫米甚至几十毫米。这不是驱动写错了而是漏掉了标题里排在读取前面的两个字校准。VL53L0X 是 ST 的 ToF 激光测距芯片芯片内部出厂前已经做过 SPAD 管理和参考校准上电就能测但它对传感器前面的光学窗口非常敏感加玻璃、加外壳、甚至模块表面沾了灰都会让一部分发射光直接反射回接收器形成串扰信号导致近距离读数明显偏近。所以一份真正能用的 C 源码必须把校准流程和距离读取流程放在一起。这篇文章不依赖你下载过那个 zip 包而是把这类项目里最常见的方案讲透VL53L0X 的 ToF 测距原理、51 单片机上的软件 I2C 驱动、单次测量和连续测量的寄存器操作以及 XTalk 校准、偏移校准在标准 89C52 上要怎么落地。正在做倒车雷达、电子尺、智能感应垃圾桶或者想把手头普中开发板利用起来的读者可以参考这里的完整思路。2. VL53L0X 的 ToF 测距原理与 51 单片机的最小接入方案2.1 从光子飞行时间到 13bit 距离值VL53L0X 内部发生了什么VL53L0X 使用 940nm VCSEL 激光器发射红外光子光子遇到目标后反射回来被芯片内部的 SPAD 单光子雪崩二极管阵列接收。芯片测量的是光从发射到接收的往返飞行时间再乘上光速除以 2就是距离这就是 ToF 和超声波测距本质上的区别超声波靠声速ToF 靠光速所以它可以做到毫米级分辨率还不受目标颜色和纹理的直接影响。芯片内部把测量结果打包成一个 13bit 的数值范围是 0 到 8191单位是毫米。默认测距模式下有效量程是 40mm 到 2000mm超过 2m 之后信号强度下降很快想测更远需要切换到长距离模式并且调大测量时间预算。读取距离时实际上是从结果寄存器里取两个字节再按掩码拼出 13bit 的原始值。这个芯片比你想象中“聪明”的地方在于它内部已经做了一层信号处理和温度补偿SPAD 的设置、参考校准值都存储在片内 NVM 里上电后由固件自动加载。这就是为什么很多人不写初始化代码直接触发单次测量也能读出距离。但请注意NVM 里存的是芯片自身的光学校准不包含你安装外壳、玻璃、滤光片带来的影响这就是后文要单独讲校准的原因。2.2 51 最小系统的引脚分配XSHUT、SDA、SCL 与电平匹配VL53L0X 模块通常引出 6 个引脚我一般用STC89C52 时按下面这张表接线。这样一个最小系统只需要 5 条飞线就能把传感器挂到 51 的 IO 口上。VL53L0X 引脚51 单片机引脚说明VCC5V模块带稳压多数 GY-VL53L0X 模块板载 3.3V LDO可以直接吃 5VGNDGND共地必须接SDAP2.0软件 I2C 数据线外接 10kΩ 上拉到 3.3VSCLP2.1软件 I2C 时钟线外接 10kΩ 上拉到 3.3VXSHUTP2.2硬件复位脚低电平复位拉高开始工作GPIO1可不接中断输出脚需要低功耗唤醒时才用电平匹配是 51 接 3.3V 传感器最容易踩的坑。STC89C52 的 IO 口在准双向模式下输出高电平的驱动能力其实很弱主要靠外部上拉把电平抬起来。我一般会在 SDA 和 SCL 上各接一个 10kΩ 电阻到 3.3V让高电平由 3.3V 决定低电平由 51 内部的下拉管拉低这样两边都安全。如果你买的模块板载上拉电阻已经存在需要确认上拉电压否则可能在 51 输出高电平时被 5V 灌进传感器长期使用会损坏 VL53L0X 的 I2C 接口。XSHUT 引脚上电后需要拉高否则芯片一直处于复位状态。模块在 5V 供电时XSHUT 可以直接由 51 的推挽输出驱动但如果你用的是 3.3V 独立供电最好通过一个 MOS 管或三极管做电平转换。做 Proteus 仿真时I2C 上拉电阻和延时参数和真实芯片差别很大仿真通过不代表硬件没问题这一点后面第 3 章的排错部分还会提到。2.3 软件模拟 I2C时序参数与 51 的 IO 配置STC89C52 没有硬件 I2C 外设所以只能靠 GPIO 用软件模拟。VL53L0X 的 I2C 从机地址是 0x297bit 地址换算成 8bit 写地址是 0x52读地址是 0x53。模拟 I2C 最关键的是保证时序稳定不要追求高速100kHz 标准模式完全够用因为每次测距本身要花几十毫秒I2C 通信的时间占比很低。下面这段是 51 上最基础的软件 I2C 驱动我用_nop_()做短延时在 11.0592MHz 晶振下实测 SCL 频率大约在 80kHz 到 100kHz 之间sbit SDA P2^0; sbit SCL P2^1; // 每一个时钟沿之间插入4个空操作指令 void I2C_Delay(void) { _nop_(); _nop_(); _nop_(); _nop_(); } void I2C_Start(void) { SDA 1; SCL 1; I2C_Delay(); SDA 0; I2C_Delay(); // SDA先拉低START条件 SCL 0; I2C_Delay(); // 拉低SCL准备传数据 } void I2C_Stop(void) { SDA 0; SCL 1; I2C_Delay(); SDA 1; I2C_Delay(); // SCL高时SDA从低到高STOP条件 } bit I2C_WriteByte(unsigned char dat) { unsigned char i; bit ack; for (i 0; i 8; i) { SDA (dat 0x80) ? 1 : 0; // 高位先出 dat 1; SCL 1; I2C_Delay(); SCL 0; I2C_Delay(); } SDA 1; // 释放数据线等待从机应答 SCL 1; I2C_Delay(); ack SDA; // 读ACK位0表示从机应答 SCL 0; I2C_Delay(); return ack; } unsigned char I2C_ReadByte(void) { unsigned char i, dat 0; SDA 1; // 读之前释放总线 for (i 0; i 8; i) { dat 1; SCL 1; I2C_Delay(); if (SDA) dat | 0x01; // 在SCL高电平期间读SDA SCL 0; I2C_Delay(); } return dat; }这段代码的关键点是SDA 必须在 SCL 低电平期间变化高电平期间保持稳定START 条件是 SCL 高时 SDA 拉低STOP 条件是 SCL 高时 SDA 拉高。_nop_()的作用是让总线信号有时间建立和保持如果你把晶振换到 24MHz可以把I2C_Delay里的_nop_()数量略微增加保证 SCL 频率不高于 400kHz 就行。51 的 IO 口在准双向模式下不需要额外配置寄存器直接使用。如果你用 STC15 或者 STC8 系列记得把引脚模式设置成准双向口否则推挽模式下直接驱动 3.3V I2C 总线会有电平冲突风险。3. 用 51 单片机读出 VL53L0X 距离单次测量的寄存器级代码3.1 初始化的两条路上电默认状态与精简配置序列VL53L0X 上电后内部固件会从 NVM 加载出厂校准数据默认配置下就可以执行单次测距。很多 51 开发者的第一版代码只写了一个函数向 0x00 写 0x01然后读结果。这在裸模块上确实能跑通但如果你想切换测量模式、调整测量时间预算或者想彻底确保芯片不在异常状态就需要一个精简初始化过程。我一般会先做两件事硬件复位和器件 ID 校验。硬件复位通过 XSHUT 引脚拉低再拉高实现之后读寄存器 0xC0正常值应该是 0xEE表示 I2C 通信链路和芯片本身都正常。下面是精简初始化代码sbit XSHUT P2^2; unsigned char VL53L0X_Init(void) { unsigned char id; XSHUT 0; // 硬件复位 Delay1ms(10); XSHUT 1; Delay1ms(10); id VL53L0X_ReadReg(0xC0); // 读取Model ID if (id ! 0xEE) return 0; // 返回0表示失败 VL53L0X_WriteReg(0x00, 0x00); // 确保SYSRANGE_START处于空闲 return 1; }这段代码只做最小初始化。完整驱动里的配置序列还有寄存器页切换、SPAD 设置、GPIO 方向配置等加起来往往有几十行标准 89C52 的 8KB ROM 勉强能塞下但可维护性很差。我的经验是对于固定场景的单次测距不要盲目照搬 ST 官方长初始化序列先跑通再按需求加配置。只有在需要连续测量、调节测量时间预算、使用高精度模式时才需要去动那些页面切换寄存器。3.2 触发单次测量并读取 13bit 距离的完整函数VL53L0X 的单次测距流程是向 0x00SYSRANGE_START写 0x01 启动测量然后等待芯片内部完成测量最后从结果寄存器 0x0B 开始连续读取若干个字节。注意在启动后要等待两件事0x00 的 bit0 被清零表示启动命令已被接受0x0B 的 bit0 被置 1表示数据就绪。下面这个函数是距离读取程序的核心unsigned short VL53L0X_ReadDistance(void) { unsigned char buf[3]; unsigned short dist; unsigned int timeout; // 触发单次测量 VL53L0X_WriteReg(0x00, 0x01); // 等待启动位被清零最多等100ms timeout 0; while (VL53L0X_ReadReg(0x00) 0x01) { if (timeout 100) return 0xFFFF; Delay1ms(1); } // 等待数据就绪标志最多等200ms timeout 0; while ((VL53L0X_ReadReg(0x0B) 0x01) 0) { if (timeout 200) return 0xFFFF; Delay1ms(1); } // 从0x0B连续读3字节状态、距离高字节、距离低字节 VL53L0X_ReadMulti(0x0B, buf, 3); // 0x0B的高4位是RangeStatus非0表示测量异常 if (buf[0] 0x78) return 0xFFFF; // 距离是13bit高5位在buf[1]的低5位低8位在buf[2] dist ((unsigned short)(buf[1] 0x1F) 8) | buf[2]; return dist; }代码里两个超时保护特别重要。VL53L0X 正常测量时间是 30ms 左右但如果你接错线或者传感器被挡住导致内部信号超时芯片可能一直不置位就绪标志没有超时保护的话 51 就会死循环卡死。0xFFFF 作为哨兵值调用方通过判断它来区分正常距离和错误状态。buf[0] 0x78是检查结果状态寄存器的高 4 位0x78 二进制是 0111 1000覆盖了 bit3 到 bit6这 4 位就是 RangeStatus。如果它非零说明本次测量有错误具体错误码后面表格会细讲。3.3 距离数据不可信时的 RangeStatus 错误码检查RangeStatus 错误码是 VL53L0X 开发里最容易被忽略的寄存器位。很多人只看距离值发现距离为 0 或者突然变 10000mm就怀疑传感器坏了其实读一下状态码就能定位问题。下面是常见错误码和对应处理建议RangeStatus含义常见原因与处理0正常无6硬件 VCSEL 故障模块损坏或者供电不足检查 VCC7VCSEL 安全故障发射功率异常供电不稳定或芯片过热12没有信号目标太远、反射率太低、视场角内无目标13信号率过低目标反射率低尝试使用白色目标7 以外溢出目标过近或强反射距离低于 40mm判断错误时不要只认 0 和非 0。比如 12 表示没信号可能是你正对着黑色吸光布料或者在户外环境光太强导致信噪比不足。遇到这些情况硬件上的解决办法是调整安装角度和距离软件上可以增加测量时间预算来提高信号积分时间。3.4 连续测量模式与测量时间预算的调整单次测量适合低功耗场景每次测完芯片自动回到待机。如果你要做实时测距比如倒车雷达需要连续输出距离可以用连续测量模式。向 0x00 写 0x02 进入连续测量之后数据不断刷新每次读完结果后需要向 0x00 写 0x01 清除中断否则就绪标志不会更新。调整测量时间预算在 0x40 和 0x41 寄存器单位是毫秒默认是 33ms 左右。增大时间预算可以提高测距稳定性尤其是低反射率目标减少预算可以加快刷新率但距离抖动会变大。在 51 上做连续测量时我建议把预算调到 50ms 到 100ms刷新率仍然有 10Hz足够大多数课程设计使用。4. VL53L0X 的两种校准路径芯片级 XTalk 校准与软件补偿4.1 为什么加上外壳和玻璃之后近距离读数会无端偏近VL53L0X 的发射器和接收器封装在同一个模块里发射光锥和接收视场在小角度上会有重叠。模块正面如果装了玻璃罩、亚克力板或者外壳开孔位置有反射面一部分发射光会在这些表面上直接反射回接收器形成一条“伪回波”。这条伪回波叠加在真实目标的回波上相当于给真实信号加了一个直流偏置结果是距离读数比实际距离小尤其在 100mm 以内的近距离非常明显。这个现象在技术文档里叫 XTalk串扰。它不是芯片本身的偏差而是外部光学环境造成的。所以判断什么时候需要校准很简单模块是否加了外壳或者防护镜片换过安装位置模块表面有没有被半透明贴纸覆盖。这三条只要中一条就应该做一次校准否则距离读取程序的精度就无从谈起。4.2 芯片级校准的标准流程85% 灰卡、50mm 和 100mmST 官方对 VL53L0X 校准定义了两种XTalk 校准和偏移校准。XTalk 校准要在距传感器 50mm 处放一块反射率 85% 的灰卡或白色纸板芯片测出串扰信号强度计算出校准系数偏移校准则是把目标放在 100mm 处芯片测出实际距离与真实距离的偏差记录为偏移量。两种校准最终写入芯片内部的数据区后续测距会自动扣除。这两个距离值不是随便定的。50mm 是串扰影响最显著的近距点在此距离下测量伪回波的信噪比足够高100mm 是普通测距应用里最常用的中间量程参考点偏移校准之后在量程中段表现最平直。实际操作时如果你的应用主要在远距离可以把参考距离拉远到 300mm 或 500mm但纸板反射率仍然要保证高且均匀。芯片级校准通常依赖 ST 官方 API。官方 API 需要约 30KB ROM 和 2.5KB RAM标准 STC89C52 根本编译不下所以常见的落地姿势有两种一种是先把 VL53L0X 接到 STM32 或 Arduino 上跑一次官方校准工具把校准值读出来写成常量表再烧进 51 程序另一种是直接购买已经校准过并固化好数据的模块。你的 51 程序只需要加载这些校准数据再通过 I2C 写回芯片即可。4.3 在标准 89C52 上做软件校准偏移记录 三点线性插值既然标准 89C52 跑不下官方 API那就绕开它做软件校准。这个方法在课程设计里非常实用把 VL53L0X 当成一个“非线性传感器”用外部 ADC 三点校准的思想在量程内标几个点然后通过线性插值修正输出。先做偏移校准。把目标固定在 100mm 处连测 5 次取平均计算出偏差存到外部 EEPROM例如 AT24C02里#define CAL_TARGET_MM 100 void Sensor_OffsetCalibrate(void) { unsigned char i; unsigned short raw; unsigned long sum 0; signed int offset; // 连续测5次取平均 for (i 0; i 5; i) { raw VL53L0X_ReadDistance(); if (raw 0xFFFF) return; // 测量失败直接放弃 sum raw; Delay1ms(20); } raw (unsigned short)(sum / 5); offset (signed int)CAL_TARGET_MM - (signed int)raw; // 偏移量写入AT24C02的0x00和0x01地址 EEPROM_Write(0x00, (unsigned char)(offset 0xFF)); EEPROM_Write(0x01, (unsigned char)((offset 8) 0xFF)); }偏移校准解决的是系统固定偏差但 VL53L0X 的非线性在中远距离会逐渐显现尤其是目标表面反射率不均匀时。更好的做法是用三点标定分别取 10cm、50cm、100cm 三个参考点记录“真实距离”和“校准前读数”的映射表然后用线性插值修正任意距离。typedef struct { unsigned int real_mm; // 真实距离 unsigned int raw_mm; // 校准前读取值 } CalPoint; // 三点标定表在产线上按下按键时自动生成 CalPoint cal_table[3] {{0, 0}, {0, 0}, {0, 0}}; unsigned int Cal_Linear(unsigned int raw_mm, CalPoint *table, unsigned char n) { unsigned char i; signed long k, b; // 在标定点之间做一次线性插值 for (i 1; i n; i) { if (raw_mm table[i].raw_mm) { // 斜率k保留3位小数避免浮点运算 k (signed long)(table[i].real_mm - table[i-1].real_mm) * 1000 / (signed long)(table[i].raw_mm - table[i-1].raw_mm); b (signed long)table[i-1].real_mm - k * (signed long)table[i-1].raw_mm / 1000; return (unsigned int)((k * (signed long)raw_mm) / 1000 b); } } return raw_mm; }Cal_Linear里用long运算而不是浮点数是因为 51 的浮点库要额外引入 3KB 以上代码。乘以 1000 保留三位小数精度最后再除回来误差可以控制在 0.1% 以内。标定时注意每个点至少测量 10 次取中位值因为 VL53L0X 单次读数有 ±3mm 左右的噪声直接插值会把噪声也标进去。4.4 校准数据的保存位置EEPROM、常量表与内部 NVM 的取舍软件校准得到的偏移量和三个标定点需要决定存在哪里。我列了三种方式按实际项目需求选择保存方式优点缺点适用场景外部 EEPROMAT24C02可反复校准不需要改代码占 I2C 总线需要单独驱动产线上每台设备单独校准C 源码常量表简单直接不占额外硬件换一台设备就得重新编译烧录外壳和安装方式固定的样机写回 VL53L0X 内部 NVM芯片自动补偿应用层代码最干净有擦写次数限制失败可能损坏芯片有官方 API 环境时的量产方案课程设计和样机阶段推荐前两种。标定数据存储在 AT24C02 里51 上电时读出来填充cal_table测试人员可以随时重新校准。注意偏移量是有符号数EEPROM 写入时用补码保存读出来直接强转signed int不要用无符号类型否则 -30 会变成 65000距离修正就完全错了。5. 距离读取程序的精度整定目标反射率、噪声滤波与常见故障排查5.1 12° 视场角、目标反射率和环境光对读数的实际影响VL53L0X 的接收视场角大约是 12°发射激光不是一条线而是一个锥形光斑。所以它测的不是“一个点”的距离而是视场角内所有反射信号的综合结果。目标物表面如果有一半是白色一半是黑色读数会偏向白色那一侧的距离。实际使用时尽量让激光光斑完全落在目标物体上不要把墙角、床边等背景物体扫进视场。目标反射率对测量影响巨大。白纸反射率约 85%测距效果最好灰色卡纸约 40%也能稳定测量黑色布料或者磨砂深色塑料反射率可能只有 5%这种情况下信号率极低芯片会报 RangeStatus13。如果你必须测深色物体有两个办法一是把测量时间预算调大例如从 33ms 调到 100ms二是在目标上贴一小块白色反光贴代价是测距最近点可能变成贴纸位置而不是目标表面。环境光的影响主要体现在阳光下。940nm 红外波段在阳光下也有很强的背景辐射VL53L0X 虽然内部有环境光抑制但强光直射传感器窗口时噪声基底抬高测距抖动明显变大。室外使用建议在传感器外面加一个深色滤光片只让 940nm 附近的光线通过。5.2 51 上不加 float 的滑动窗口滤波距离读取程序在实际运行时单次测量结果的抖动通常在 ±3mm 左右近距离高反射目标会好一些。51 上最常见的优化手段是滑动窗口均值滤波。下面是一个在 data 区分配缓冲区的实现#define FILTER_N 5 unsigned int Distance_Filter(unsigned int new_val) { static unsigned int buf[FILTER_N]; static unsigned char cnt 0; unsigned char i; unsigned long sum 0; buf[cnt] new_val; // 覆盖最旧的点 cnt (cnt 1) % FILTER_N; // 环形队列 for (i 0; i FILTER_N; i) { sum buf[i]; } return (unsigned int)(sum / FILTER_N); }窗口大小选 5 比较均衡。取 3 时滤波效果不明显取 10 以上虽然更平滑但连续测量时输出会滞后运动目标跟不住。如果你做的是倒车雷达或者机器人避障建议用 5做静态尺寸测量可以用 8 或 10。这个滤波有一个问题当距离发生大跳变时均值滤波会拉出好几帧的“斜坡”。比如目标突然从 500mm 移到 50mm输出会从 500 一步步滑到 50中间每个值都是真的但不是当前真实距离。对运动目标更适合的做法是用中值滤波取 5 个值排序后取中间值。中值滤波在 51 上的 RAM 占用是 10 字节加上排序代码完全能承受。5.3 故障排查表I2C 读不到、距离恒 0、距离乱跳把实际开发中踩过的坑整理成一张排查表能省不少时间故障现象可能原因排查和处理I2C 一直收到 NACKSDA/SCL 接反或上拉电压不对用万用表量 SDA/SCL 静态电压应该接近 3.3V距离恒为 0xFFFF超时返回哨兵值芯片没启动检查 XSHUT 是否拉高0xC0 是否读到 0xEE距离固定不变传感器前被遮挡或目标静止且滤波窗口太长去掉滤波读原始值确认是否为真实静止目标距离跳跃几百毫米视场角内混入背景物体或目标反射率突变缩小目标区域检查激光光斑是否落在目标边缘近距离读数偏小没做 XTalk 校准按第 4 章流程重新校准亮度高时报错 12户外强光干扰加滤光片或增大测量时间预算另外给一个调试建议用逻辑分析仪抓 I2C 波形重点看 ACK 位。VL53L0X 的 ACK 异常通常不是芯片坏了而是 SCL 频率过高导致芯片来不及响应。把 I2C 时钟降到 50kHz 再试很多诡异问题都会消失。6. 把校准和距离读取做成可重复的产线流程6.1 按键触发校准状态机样机阶段可以用在代码里改常量表的方式标定但到了批量组装阶段必须让作业员或者产线工装一键完成校准。我在项目里用过一个很简单的状态机板子留一个按键和一个 LED长按按键 3 秒进入校准模式LED 慢闪表示等待放置目标蜂鸣器响一声表示当前点校准完成。先校准 10cm 点再依次校准 50cm 和 100cm 点。作业员只需要按提示摆放纸板并按一次按键程序自动完成 10 次测量、去极值平均、更新cal_table、写入 EEPROM。这套流程不需要连电脑也不需要串口工具产线培训成本很低。51 的定时器中断用来做按键消抖和 LED 闪烁不占用 I2C 总线校准过程本身很稳定。6.2 用串口打印校准前后的数据曲线调试时建议把校准前后的数据都打印出来直观对比。51 上通过串口 1 发送波特率 9600 或 115200下面是发送逻辑void Debug_PrintResult(unsigned short raw, unsigned short corrected) { unsigned char status 0; // raw0xFFFF 表示读取失败直接打印错误标记 if (raw 0xFFFF) { UART_SendString(ERR\r\n); return; } UART_SendString(raw); UART_SendInt(raw); UART_SendString(, corr); UART_SendInt(corrected); UART_SendString(\r\n); }注意校准前的 raw 值要保留不要一上来就用修正后的值做判断。打印一组数据后你就能看到偏移校准只改固定偏差三点插值能在全量程内把曲线掰直。如果你的上位机支持串口绘图直接把两个值画成曲线标定点之间的线性度一目了然。6.3 一个 10 秒纸板斜移标定法最后分享一个我已经用习惯了的快速验证技巧取一张 A4 白纸双手平端从传感器正前方 50mm 处开始以大约 100mm/s 的速度匀速向后移动同时观察串口输出的 corr 值。正常情况是 50mm 到 1000mm 之间单调递增并且每个 10mm 间隔至少有 8mm 的读数变化。如果某一小段读数突然不动或者跳变说明那段距离上目标反射信号有问题常见原因是纸板移动过程中发生了倾斜导致反射光斑移出接收视场。保持纸板平面垂直于激光光轴再用同样的方法测一次。这个方法的优点是不需要买标准灰卡只需要一张白纸和一个直尺就能在 10 秒内判断校准是否到位比看误差均值直观得多。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门