
搞过HVAC控制器或者机房环境监测设备的朋友应该都有这个体会温度测点看着简单真正布起线来全是坑。以前用NTC模拟量采集线拉到二三十米读数就飘得没法看还要做冷端补偿、查分压表、逐点校准现场工程师能调一整天。最近做一个空调箱监控项目要把本地机柜温度、送风风道温度和几十米外机房的环境温度汇总到一块主控板上统一处理我改用 PJ85718DM 数字温度传感器配 PIC32MX675F256L 做采集主控整个调试过程顺了不少。这篇就把完整的方案架构、关键代码和现场踩坑记录整理出来给做嵌入式测温和HVAC控制的朋友一个可直接参考的模板。这套方案的定位很明确本地测点用数字传感器直接挂在主控引脚上远程测点通过 RS-485 总线回传所有温度数据在 PIC32MX675F256L 里做滤波、校准、显示、上报一套代码同时兼顾本地和远程。适合做空调箱控制器、冷库监控、数据机房动环板卡这类项目的开发人员也适合刚接触 PIC32 平台想找一个完整外设例程的入门者。1. 为什么这套方案能同时管好本地和远程温度1.1 HVAC场景里的测点困境供热通风与空气调节领域的温度监测难的不是读一个温度而是在恶劣电磁环境和远距离布线下稳定读多个温度。空调箱旁边就是接触器、压缩机、变频器一启动就是几十安培的电流变化模拟量信号线在这种环境下特别容易被干扰。实测下来用长线走 NTC 分压信号线缆超过十米示波器上就能看到明显的工频干扰和尖刺脉冲ADC 采样值跳几十个字是常事。另一个麻烦是校准。模拟传感器每个都有个体差异同一批 NTC常温下阻值能差百分之几你想做到±0.5℃的精度就得一个一个标定把修正系数写进 EEPROM产线效率低得让人头疼。数字温度传感器把敏感元件、ADC、线性校正全封装在芯片内部出厂前已经校准过单片机只需要按协议把温度字读出来根本不用关心放大器和 ADC 的标定问题这对批量生产意味着省掉一大块人工成本。还有一点HVAC 项目对断电恢复和稳定运行要求高。模拟量采集一旦电源纹波变大读数就跟着波动很容易误触发报警数字量传感器只要通信时序稳定读数一般不会突然跳变逻辑上也好处理得多。1.2 整体架构与数据流这个项目的硬件分两个部分。主控制器用 PIC32MX675F256L板上直接焊接两路 PJ85718DM 测本地温度一路放在主控盒子里测机柜内环境温度另一路用三芯屏蔽线引出贴在空调箱送风风道外面测送风温度长度不超过三米单总线协议能扛住。远程测点放在几十米外的弱电机房那里也有一块小板同样用 PJ85718DM 采集机房环境温度小板上的 MCU 通过 RS-485 把温度值传给主控。为什么远程不直接用单总线长线因为 PJ85718DM 这类单总线器件虽然能在两三米内稳定工作拉到几十米后线缆分布电容会让时序变形遇上现场变频器干扰通信失败率急剧上升。RS-485 是差分传输共模抑制能力强工业现场传输几百米都没问题而且 HVAC 行业的上位机和楼宇自控系统普遍支持 Modbus RTU 协议主控通过 RS-485 除了收远程测点数据还能顺便把温度值上报给集中监控平台一举两得。数据流是这样的远程小板每 500ms 读一次 PJ85718DM把温度值按照 0.1℃ 为单位的整数存到寄存器里主控作为 Modbus 主站每隔 1 秒轮询一次远程从站读出温度后再和本地两路温度一起做滤波和显示。温度超过设定阈值时主控驱动继电器输出报警信号。整个过程全部由 PIC32MX675F256L 的 UART、定时器、GPIO 完成不需要外加协议转换芯片。2. 硬件选型与接线细节2.1 传感器端的取舍数字输出比模拟输出省心在哪PJ85718DM 是一颗单总线接口的数字温度传感器典型的测量范围覆盖 -55℃ 到 125℃在 -10℃ 到 85℃ 这个 HVAC 最常见的区间里精度标称 ±0.5℃分辨率可以通过配置寄存器选择 9 到 12 位。这个精度水平用在空调箱送回风温度监测、机房环境温度告警场景下绰绰有余。选这颗料还有个现实考虑单总线只需要一根数据线主控这边省引脚。PIC32MX675F256L 虽然引脚不少但一个项目里要接 LCD、按键、RS-485、继电器驱动、DI 输入引脚资源并不宽裕。一个传感器占一个 GPIO两路本地加上远程总共才占三个引脚比 I2C 还要省事因为每个 I2C 设备还要分配地址。接线上有几个容易被忽略的细节。单总线数据引脚必须接上拉电阻阻值选 4.7kΩ 比较稳妥如果线缆略长或者线上挂的设备多可以降到 2.2kΩ。数据线走线尽量避开继电器输出和电源线特别是高压侧实在躲不开就加屏蔽层屏蔽层单端接地。供电方面 PJ85718DM 支持 3.0V 到 5.5V这个项目里主控是 3.3V 供电传感器直接挂 3.3V 就行数据线和 MCU 引脚电平天然匹配省了电平转换电路。2.2 主控端的底气PIC32MX675F256L 的外设够不够用PIC32MX675F256L 是 MIPS M4K 内核的 32 位 MCU主频最高 80MHzFlash 256KBRAM 64KB。放在 HVAC 控制器这个场景里性能是明显过剩的但过剩恰恰是好处跑 Modbus 协议栈、移动平均滤波、LCD 刷新全部毫无压力剩余资源还可以做日志存储和故障记录。外设配置我看了一下是够用的。它带六个 UART一个做 RS-485 与远程从站通信一个做调试日志输出还有富余带两个 I2C 和一个 SPI接 LCD 和 EEPROM 没问题带 CAN 2.0B 控制器如果业主方要求改成 CANopen 总线硬件不用动只改软件协议就行支持 DMA后续想把温度数据批量搬运到内存做分析可以省掉 CPU 中断开销。选型时对比过其他平台最后定 PIC32MX675F256L 主要是看重两点。一是它的 UART 带有硬件流控引脚映射RS-485 的收发方向切换可以直接用通用 GPIO 控制时序做得很干净二是这个芯片的参考手册和库函数比较完整寄存器配置清晰裸机开发时不用猜初始化顺序。唯一要适应的就是 MIPS 内核的中断模型和 ARM 不太一样刚开始会有个学习曲线后面我会专门讲一下这里面的坑。2.3 本地与远程节点的接线设计主控板供电采用 HVAC 项目里最常见的 24V 直流输入经过 DC-DC 降压到 5V再经 LDO 降到 3.3V 给 MCU 和传感器供电。RS-485 收发器建议选带限流保护的型号A、B 引脚对地各加一个 TVS 管因为现场总线上可能接入其他设备免不了遇到共模电压异常的情况。总线末端最远端从站并接一个 120Ω 终端电阻主控端一般不接以免和多个从站组成复杂拓扑时阻抗不匹配。本地两路 PJ85718DM 的 DQ 引脚分别接主控的 RD0、RD1每路各配一个 4.7kΩ 上拉到 3.3V。传感器到主控的线缆用双绞线或者屏蔽线屏蔽层在主控端单点接地另一端悬空这样现场变频器高速开关产生的高频干扰能被屏蔽层导走。远程从站小板也做得很简单一颗小体积 MCU我直接用同系列的 PIC32MX675F256L方便复用代码、一颗 PJ85718DM、一颗 RS-485 收发器、一个隔离电源模块。从站电源从现场 24V 取电用 DC-DC 隔离出来避免地回路导致 RS-485 通信异常。这个隔离设计看着多花二十块钱但能在现场省掉大量排查通信问题的工时非常值。3. 软件实现从读温度到上报远程数据3.1 工程框架与初始化流程开发环境用 MPLAB X IDE 加 XC32 编译器调试器用 ICD4。工程结构上我习惯裸机编程不用 Harmony 框架因为项目逻辑不复杂裸机更容易控制每一行代码的执行时机出了问题也容易定位。系统启动后按下面的顺序初始化关闭看门狗 → 配置时钟 → 初始化 GPIO → 配置定时器 → 初始化 UART → 初始化 LCD → 开中断 → 主循环。时钟配置是第一步也是最容易出问题的。使用外部 8MHz 晶振通过 PIC32MX675F256L 内部的 PLL 倍频到 80MHz外设总线时钟PBCLK分频为 40MHz。设备配置位写成下面这样#pragma config FNOSC PRIPLL #pragma config POSCMOD HS #pragma config FPLLIDIV DIV_2 #pragma config FPLLMUL MUL_20 #pragma config FPLLODIV DIV_1 #pragma config FPBDIV DIV_2 #pragma config FWDTEN OFF #pragma config JTAGEN OFF外部晶振 8MHz 先经过 PLL 输入分频除到 4MHz20 倍频到 80MHz输出分频 1得到 80MHz 系统主频再经过外设分频 2得到 40MHz 外设时钟。UART 波特率生成器和定时器全都基于 40MHz 计算。主循环的结构很直白while (1) { local_temp[0] read_temp_sensor(0); local_temp[1] read_temp_sensor(1); remote_temp read_modbus_remote_temp(); filtered[0] temp_filter(local_temp[0], 0); filtered[1] temp_filter(local_temp[1], 1); filtered[2] temp_filter(remote_temp, 2); lcd_display(filtered); relay_check(filtered); ClrWdt(); }主循环里有一句 ClrWdt() 非常重要。如果传感器在总线上没响应读温度函数的阻塞等待时间会拖长不喂狗的话系统就被无故复位了喂狗太早也不行必须在主循环末尾喂保证一个周期内所有操作都完成了。3.2 传感器驱动与数据校验PJ85718DM 的单总线时序和常见的数字温度传感器方案基本一致。整个驱动可以拆成四个函数复位脉冲、写字节、读字节、读温度。核心时序用延迟函数自己控制不依赖硬件定时器。先看引脚配置。DQ 引脚设置为开漏输出外部 4.7kΩ 上拉保证静态高电平。读数据的时候把引脚切到输入模式采电平写数据的时候切到输出模式拉低或拉高这个切换必须在时序要求的纳秒级时间内完成PIC32 的 IO 操作够快实测不会丢时序。#define DQ_TRIS TRISD #define DQ_LAT LATD static inline void dq_output_mode(void) { DQ_TRIS ~(1 0); } static inline void dq_input_mode(void) { DQ_TRIS | (1 0); } static inline void dq_low(void) { DQ_LAT ~(1 0); dq_output_mode(); } static inline void dq_high(void) { DQ_LAT | (1 0); dq_output_mode(); } static inline uint8_t dq_read(void) { dq_input_mode(); return (PORTD 0) 1; }复位时序必须严格按照 480μs 低电平、释放、等待从设备拉低 60μs 来写。实际调试时如果示波器看不到从设备的存在脉冲优先怀疑的就是低电平时间不够长或者引脚配置不是开漏输出。我习惯把复位写成带超时的函数避免从设备没接时主控死等uint8_t pj_reset(void) { uint32_t timeout 0; dq_low(); delay_us(500); dq_high(); delay_us(30); if (dq_read() 0) { while (dq_read() 0) { if (timeout 200) return 0; delay_us(1); } return 1; } return 0; }读温度的函数流程是复位 → 发送跳过 ROM 命令 0xCC → 发送启动温度转换命令 0x44 → 等待转换完成12 位分辨率需要约 750ms→ 复位 → 发送 0xCC → 发送读暂存器命令 0xBE → 连续读 16 个字节低 8 位温度、高 8 位温度、配置字节和 CRC 校验位。温度值拼接成 int16_t 后右移 4 位就是实际温度的整数部分小数部分看低 4 位0.0625 摄氏度为一个 LSB。CRC 校验不能省。总线现场干扰会导致数据错误不校验的话可能在屏幕上显示一个完全错误的高温值触发误报警。PJ85718DM 的 CRC 多项式是 X^8X^5X^41也就是常见的单总线 CRC 算法我直接用了查表法速度足够uint8_t crc8(uint8_t *data, uint16_t len) { uint8_t crc 0; for (uint16_t i 0; i len; i) { crc ^ data[i]; for (uint8_t j 0; j 8; j) { if (crc 0x80) crc (crc 1) ^ 0x31; else crc 1; } } return crc; }校验失败时直接丢弃这一次的读数保留上一次的有效值。连续失败超过 5 次才判定传感器链路异常并报警这就不会因为偶发的干扰导致系统误动作。3.3 滤波与本地显示现场的温度波动分两类一类是真实的环境温度变化比如空调箱送风温度随压缩机启停周期性起伏这类变化是正常的不需要滤掉另一类是瞬态干扰造成的采样毛刺比如变频器启动瞬间传感器电源被拉低读数突然跳高 8 度这一类必须滤掉。我用了异常值剔除 移动平均两级滤波。先判断本次采样值和历史平均值的偏差如果超过 5℃直接判定为无效采样不参与平均有效值才进入一个长度为 8 的环形缓冲区每来一个新值就计算缓冲区平均值作为输出。这个算法在风机启停、压缩机吸合的条件下温度输出波动能控制在 ±0.3℃以内。#define TEMP_BUF_N 8 float temp_filter(float raw_value, uint8_t ch) { static float buf[3][TEMP_BUF_N]; static uint8_t idx[3] {0, 0, 0}; static uint8_t filled[3] {0, 0, 0}; float sum 0; for (uint8_t i 0; i TEMP_BUF_N; i) { sum buf[ch][i]; } float avg filled[ch] ? sum / TEMP_BUF_N : raw_value; if (fabsf(raw_value - avg) 5.0f) { return avg; } buf[ch][idx[ch]] raw_value; idx[ch] (idx[ch] 1) % TEMP_BUF_N; if (!filled[ch]) filled[ch]; return avg; }注意这个滤波函数里有个细节环形缓冲区初始状态全零直接平均会把第一个有效读数拉低。所以我用一个 filled 标志位来区分缓冲区还没有填满和已经填满两种状态。实测中如果在第一次上电时不做这个处理温度显示会在启动后两秒内出现一个明显的低谷看着像故障实际上是滤波逻辑的 bug。显示部分用的是 I2C 接口的 1602 字符模组。第一行显示本地两路温度第二行显示远程温度和通信状态。LCD 刷新频率控制在一秒一次太频繁会导致字符闪烁而且在现场看温度本来就只需要一秒量级的刷新率。3.4 远程上报UART转RS-485与Modbus RTU实现远程从站通信基于 Modbus RTU 协议主控作为主站远程小板作为从站功能码用 0x04 读输入寄存器。为什么不用 0x03 读保持寄存器因为温度是只读量逻辑上用输入寄存器更规范而且有的上位机系统会自动轮询 0x04用同一个功能码可以减少上层配置工作。UART 初始化配置为 9600、8、N、19600 波特率在 RS-485 现场总线上的传输距离和抗干扰性平衡得比较好。系统主频 80MHz、外设时钟 40MHzUART1 波特率寄存器计算如下U1BRG (40000000 / (16 * 9600)) - 1;算出来等于 259.4取整为 259实际波特率约 9615bps误差约 0.16%远在 Modbus RTU 允许的 ±2% 范围内通信非常稳定。如果改用 19200U1BRG 计算值是 129.2取整误差会稍大一点但也够用。Modbus 主站的轮询写成状态机不搞阻塞等待。发送完请求帧之后把 UART 接收中断打开同时启动一个 100ms 超时定时器收到完整响应帧或者超时后再回到空闲状态准备下一轮轮询。这样即使从站断电主控也不会卡在某个 while 循环里等数据看门狗不会乱复位。发送一帧轮询请求的代码展开就是这样uint8_t modbus_request_frame[8] { 0x01, // 从站地址 0x04, // 功能码读输入寄存器 0x00, 0x00, // 起始寄存器地址 0x00, 0x01, // 寄存器数量 0x00, 0x00 // CRC16 占位 };CRC16 计算函数是 Modbus 标准多项式 0xA001初始值 0xFFFF。需要注意发送时 CRC 的低字节在前、高字节在后很多人第一次写都栽在这个字节序上uint16_t modbus_crc16(uint8_t *buf, uint16_t len) { uint16_t crc 0xFFFF; for (uint16_t i 0; i len; i) { crc ^ buf[i]; for (uint8_t j 0; j 8; j) { if (crc 0x0001) crc (crc 1) ^ 0xA001; else crc 1; } } return crc; }从站响应帧是 7 个字节从站地址、功能码、字节数、16 位温度值的高字节和低字节、CRC16 低字节和 CRC16 高字节。温度值用有符号整数表示单位 0.1℃例如读取到 0x00C8 就是 20.0℃。收到帧后先做 CRC 校验再做地址和功能码校验全部通过后把温度值存入全局变量。还有个工程师容易忽略的点RS-485 收发器的收发方向切换必须严格卡住时序。主控发送完最后一个字节、进入接收模式前要留 500μs 左右的延时让总线上最后一个字节完整发出。如果切换太快最后一个字节可能被截断从站根本收不到完整帧。4. 工程实操记录从开板到跑数4.1 开发环境与烧录工具开发环境我直接用的 MPLAB X IDE版本支持 PIC32MX 系列即可编译器用 XC32。工程建好后第一步不是写应用代码而是先用一个空工程把时钟配置跑通确认系统主频稳定在 80MHz。用 ICD4 调试器连接目标板在调试窗口看系统时钟寄存器的实际值同时用一个 GPIO 输出一个方波接示波器测频率就能确认 PLL 配置是否正确。烧录时注意 PIC32 的上电时序。如果目标板上的 MCLR 引脚接了外部复位电容首次烧录可能因为电容充电太慢导致 ICD4 连不上。遇到这种情况把复位电容暂时拆掉烧录成功后再焊回去。这是我在几个项目里踩过不止一次的坑。4.2 上电调试的先后顺序给板子上电之前先量电源对地阻抗确认没有短路。上电后第一步不写任何应用代码只点一颗 LED确认最小系统能跑。然后用示波器看 8MHz 晶振波形晶振起振正常再配置 PLL。PLL 配置有问题时系统主频不对UART 波特率全是乱的就像收音机没调准台然后看什么都觉得是通信代码的问题实际上根源是时钟。传感器调试单独做。先用逻辑分析仪抓单总线波形检查复位脉冲、存在脉冲、读时序的时间参数。PJ85718DM 这类单总线传感器的时序都是微秒级的用逻辑分析仪比示波器直观一个采样率 24MHz 左右的逻辑分析仪就够用。波形抓对了再写代码把温度值打印到调试串口。远程通信调试时先不接远程从站主控发轮询帧用 RS-485 转 USB 工具在总线上抓包确认主站发出的 Modbus 帧 CRC 是否正确、地址是否匹配。之后再接从站用同样的工具确认响应帧格式。这种逐级排查的方法看起来慢实际上比一次把全部设备接上再瞎猜快得多。4.3 温度校准与精度修正PJ85718DM 出厂前已经校准过但系统级精度还会受传感器安装位置和热阻影响。比如传感器贴在风道管壁外侧测的是管壁温度和管内空气温度必然有偏差传感器放在主控盒子角落和机柜中心温度也有梯度差。所以系统装好后要做一次整体校准。校准方法我用的是两点法。第一点把传感器探头和精密测温仪的探头绑在一起放进冰水混合物中等读数稳定后记录偏差记做偏移量。第二点把探头放到恒温箱设定 45℃HVAC 夏季送风温度上限附近稳定后记录读数。两点之间做线性修正把修正公式写进固件display_temp (raw_temp * slope) offset;其中斜率根据两点实测值计算偏移量等于测量值减去标准值的差。实测下来经过两点校准后系统在 10℃ 到 40℃ 区间的误差可以控制在 ±0.2℃ 以内远高于 HVAC 控制的要求。还有个小技巧校准系数要保存到外部 EEPROM 或 Flash 数据区不要写死在代码里。现场安装位置变了热阻变了只需要在小键盘上输入新的修正值不用重新编译固件。这个细节在量产和后期运维阶段能省大量时间。5. 常见问题与排查技巧5.1 传感器读数为全F或错误值的处理PJ85718DM 读回 0xFFFF 或者 0x7FFF绝大多数情况不是传感器坏了而是时序不对或者总线状态不对。我用逻辑分析仪排查时发现最常见的原因是复位后的存在脉冲检测逻辑写错了释放总线后应当在 30μs 到 60μs 之间检测从设备拉低的信号如果这个窗口没抓住后面所有时序都白搭。其次检查上拉电阻。忘记焊接上拉电阻时总线一直处于低电平复位后从设备根本没有供电逻辑自然返回错误。用万用表量 DQ 引脚对地电压正常待机状态下应该为高电平。如果量到 0V先查上拉电阻而不是查代码。还有一种情况是用了错误的引脚映射。PIC32 的引脚多功能复用容易被其他外设抢占。排查时建议先只初始化 GPIO不初始化其他外设看传感器能不能读通读通了再打开其他外设这样可以快速定位是不是引脚冲突。5.2 温度读数跳变的真正原因滤波函数已经处理了大部分毛刺但偶尔还是会有跳变。用示波器抓传感器供电脚的波形发现变频器启动瞬间3.3V 电源上叠加了一个几十毫伏的跌落。传感器的模拟电路对电源变化是敏感的电源瞬时跌落会导致内部 ADC 转换结果异常。解决分两头硬件上在传感器供电引脚就近加 10μF 钽电容和 0.1μF 陶瓷电容并联使用低频高频干扰一起滤软件上把滤波窗口从 8 个点提升到 16 个点同时把异常值判定阈值从 5℃ 收紧到 3℃。改完之后连续跑一个星期没有出现误报警。这里有一个矛盾点要提醒滤波窗口太长真实温度变化会被拉平太短毛刺滤不掉。HVAC 的温度变化本身就是慢变量一分钟能变 1 度就算快了所以窗口拉长到 16 个点完全不影响系统响应这是 HVAC 场景对滤波算法友好的地方。5.3 RS-485通信异常的排查现场 RS-485 通信不稳定先看接线拓扑。高速率长距离的总线要求从设备手拉手菊花链连接不能星型。现场经常有电工师傅图省事把每台设备的 A、B 线并在一起接到主控看起来连通了实际上信号反射严重通信误码率居高不下。第二查终端电阻。总线上只应该在最远端加一个 120Ω 终端电阻如果在主控端和从站端都加了总线负载变重驱动能力不够反而通信距离变短。之前一个项目就是两端都接了 120Ω通信距离从一百多米缩短到十几米去掉主控端那个电阻后问题马上消失。第三查地电位。RS-485 虽然不需要共地也能跑但对共模电压有上限超过 -7V 到 12V 范围就会损坏收发器。两个设备分别用两个开关电源供电地之间电位差大的时候稳定运行全靠隔离。远程从站板用了隔离电源模块之后再也没有因为地环路问题导致收发器烧毁。5.4 看门狗误复位的解决主控开了看门狗但现场频繁复位。抓日志发现每次都发生在轮询远程从站超时的时候。原因是我最初把 Modbus 轮询写成了阻塞式发送帧后用一个 while 循环等待响应从站掉电时这个循环要等 3 秒超时主循环里的喂狗语句执行不到看门狗就复位了。后来改成状态机加定时器的方式每次进入状态机的处理函数不超过 1ms即使从站完全无响应主循环也能正常运行并喂狗。同时给传感器读取也加了超时计数PJ85718DM 总线上的任何等待都不超过 100μs 无条件退出。这样看门狗只负责检测真正的主循环饿死场景不再被异常外设阻塞误伤。6. 这个项目还能怎么扩展把主题之外的一些扩展思路也分享一下。如果现场要求把温度数据直接上传到云平台或工业物联网网关PIC32MX675F256L 有足够的资源挂一个以太网控制器或 SPI 接口的 Wi-Fi 模块在现有固件基础上增加一个 MQTT 任务并不复杂。如果总线上要挂多个远程从站Modbus 从站地址从 1 扩展到 247 就可以了主控固件只需把轮询地址表改成长度可配置的数组。如果要采集湿度、压力、风速这类信号我建议传感器的数字接口尽量统一。能找数字输出的就用数字输出的实在只能模拟量采集的再加独立的高精度 ADC避免把模拟信号线和数字通信线混在一起布线。这个原则在当前项目的 PCB 改版中起到了明确指导作用。最后想说的是这套方案的难度不高能稳定跑下来核心不在于某个算法有多玄妙而在于每个环节都把异常情况考虑周全了传感器总线超时怎么办、Modbus 从站失联怎么办、电源抖动怎么办、滤波缓冲区初始值怎么办。把这些边界条件都处理掉系统自然就稳定了。我在几个现场项目里实测下来PJ85718DM 加 PIC32MX675F256L 这个组合在 HVAC 温控和嵌入式环境监测场景里不管是性能、成本还是调试友好度都非常值得纳入备选方案。如果你正在选型不妨拿这个思路在自己板子上先跑一个最小原型感受一下数字温度传感器和 Modbus 总线配合的省心程度。