☰
STM32多点数温度采集:I2C与RS485混合测温系统设计
2026/10/22 1:04:35 网站建设 项目流程

去年我在一个通风系统的控制柜联调现场吃了亏:柜内温度表现得一切正常,控制逻辑也正常,可远端机房某片区域的空气温度早就越过告警线了。问题反馈回来之后我才意识到,整个系统只盯着控制柜附近的单点温度,根本没把“远端空间”作为一个温度输入源纳入监测。回来之后我重新搭了一套方案:本地温度用一颗 I2C 数字温度传感器 PJ85718DM 直接挂在主控板上,远程温度通过 RS485 总线按 Modbus RTU 协议轮询,主控换成 STM32F767BI。这套方案既能做嵌入式设备自身的板卡温度保护,也能覆盖 HVAC 环境里的多点温度采集与联动控制。

这套系统适合谁参考?如果你正在做空调控制器、冷水机组控制面板、机房列间空调联动、或者工业设备的机柜温度监控,并且发现“单点测温”根本没办法满足现场需求,那下面的内容对你有用。我会把硬件接口、软件流程、通信协议、显示和记录,以及调试中踩过的坑全部列出来,尽量做到拿来就能用。

1. 这套测温系统到底要解决什么问题

1.1 本地温度与远程温度,不是多装两个温度计

“本地温度”和“远程温度”在嵌入式与 HVAC 场景里分别指的是完全不同的物理位置,数据用途也不同。

本地温度在嵌入式系统里通常指主控板安装位置的空气温度,或者某个功率器件附近的板级温度。它的作用是保护设备自身:防止机柜过热导致电源降额、处理器降频、电解电容加快老化等。我见过不少客户把温控探头放在电源模块旁边,结果读数比真实室温高出七八度还在拼命报警,这就是测温点没选对。

远程温度在 HVAC 场景里指的是被控空间或者风管、水管的温度。比如一个风机盘管控制器,要感知的不只是控制盒里的温度,还包括室内温度、回风温度、盘管供回水温度。这些测温点往往离主控板有几米到几十米,不可能用一根 I2C 线拉过去,必须走总线或者无线。

所以“本地 + 远程”从来不是两个温度计这么简单,而是两类数据、两种物理接入方式、两种处理逻辑。本地数据要求响应快、精度稳、直接参与板卡保护;远程数据要求抗干扰、可寻址、支持多点轮询。

1.2 从需求层次看:采集、告警、联动

我在设计这套系统时把需求拆成了三个层次:

第一层是采集。至少要把本地温度、若干远程温度读回来,实时刷新。只读回来远远不够,数据要有标识、有时间戳,得知道自己读的是哪个传感器、什么时间读的。

第二层是告警。越限之后要能触发声音、界面高亮、远程状态位。这里的关键是告警值必须可配置,而且要有回差,否则温度在阈值附近抖动时继电器会哐哐乱跳。

第三层是联动。温度数据最终要去控制执行机构:风扇、加热器、电磁阀、压缩启停信号。联动逻辑不写在仪表里,而在主控里,所以主控的算力得有富余,协议栈、显示、记录都能同时跑。

这三点决定了器件选型:PJ85718DM 负责把温度变成数字信号,STM32F767BI 负责把所有温度数据组织起来并执行联动。下面详细说选型逻辑。

2. 硬件选型与接口设计

2.1 PJ85718DM:12 位 I2C 温度传感器怎么接

PJ85718DM 是一颗典型的 I2C 接口数字温度传感器,工作电压 2.7V 到 5.5V,测量范围 -40℃ 到 +125℃,典型精度约 ±0.5℃。它的 ADC 分辨率是 12 位,温度数据寄存器里每个 LSB 对应 0.0625℃,也就是说读回一个原始值之后要换算成带符号数。

从外部看,它一般有 SDA、SCL、A0/A1/A2 地址引脚、告警输出引脚 ALERT,以及电源和地。七个可能的 I2C 从机地址由 A0/A1/A2 的电平决定,常见地址是 0x48 到 0x4F。我在原理图上把三个地址引脚固定接法,默认地址设 0x48,这样最简单,避免软件里跳地址。如果你要一片主板放多颗传感器,地址引脚必须用跳线留出来,方便现场改地址。

硬件接线有几点要注意:

  • SDA、SCL 都要外接上拉电阻,典型值 4.7kΩ。STM32F767BI 的 I2C 引脚如果配置成开漏模式,内部上拉通常偏弱,外部不加上拉会导致偶发性的读错数据。
  • 建议在传感器电源引脚放一个 100nF 陶瓷电容,紧贴器件放置,能明显减少电源毛刺对 ADC 的干扰。
  • ALERT 引脚可以接到 MCU 的 EXTI 输入,用于超温快速中断,但实际项目中我更推荐主控轮询读数,在软件里做阈值判断,而不是依赖硬件中断。原因是硬件中断在远程温度场景下没有用,远程数据本来就走总线轮询,统一逻辑反而好维护。

STM32 这边的连接很简单:PJ85718DM 的 SCL 接 I2C1_SCL,SDA 接 I2C1_SDA。我习惯用引脚复用功能,比如 PB6/PB7,CubeMX 里把 I2C1 开到 400kHz。实测 400kHz 完全没有问题,但如果你线比较长或者传感器散落在主板上比较远,降到 100kHz 更稳。

2.2 STM32F767BI:主控的资源为什么够用

STM32F767BI 里 B 代表 208 引脚封装,I 代表工业级温度范围。这颗 MCU 的核心是 Cortex-M7,主频最高 216MHz,Flash 2MB,RAM 512KB。它在 F7 系列里属于高配,最吸引人的是三点:

  • 带硬件单精度浮点,温度计算、曲线显示、滤波都不用为浮点性能发愁。
  • 自带 LTDC 液晶控制器,可以直接驱动 RGB 接口 TFT 屏,不用外挂串口屏或者单片机屏驱动芯片。
  • FMC 外部存储器接口可以挂 SDRAM,用于扩展帧缓冲。

RAM 512KB 看起来很大,但 800×480 分辨率的 RGB565 屏幕一帧就需要 768KB,内部 RAM 根本装不下。所以我的板子上通过 FMC 外扩了一颗 32MB SDRAM,LTDC 从 SDRAM 读取显存,CPU 也可以快速向显存写数据。抽屉柜式控制面板上要显示温度曲线,这个配置非常合适。

主控的外设分配大致如下:

外设用途
I2C1本地 PJ85718DM
USART3 + SP3485RS485 总线,轮询远程节点
FMC + SDRAM作为 LTDC 帧缓冲
LTDC驱动 7 寸 RGB TFT 屏
SDMMC1通过 FATFS 写温度记录 CSV
两个 GPIO控制继电器和蜂鸣器
IWDG防止通信异常卡死

这套资源分配没有用到以太网和 CAN,并不是它们没用,而是 HVAC 现场最普及、最好维护的就是 RS485,后续如果接上位机或者云平台,再增加一个 W5500 或者直接启用 F767 自带的以太网 MAC 都可以。

2.3 远程温度通道:为什么选 RS485 而不是拉长 I2C

远程温度节点分布在几十米外,很多人第一反应是“I2C 拉长不就行了”。I2C 总线理论上有容抗限制,长线分布电容大了以后,上升沿变缓,通信必挂。就算用线缆缩短距离,电磁干扰环境下也抗不住。模拟量方案(PT100 + 4-20mA)虽然抗干扰,但每路都要占用 ADC 和走线,多点测温成本高。

RS485 是暖通现场最扎实的选择。它是差分信号,A、B 两线传输,抗共模干扰能力强,传输距离在波特率不高时可以到几百上千米。半双工总线结构允许挂接多个从机节点,每个远程采集节点分配一个站号,主控按 Modbus RTU 轮询就行。

我的远程节点分两种做法。如果你买现成的 Modbus 温度模块,直接挂在 RS485 总线上,读保持寄存器即可,省事。如果你自己打板,每个远程节点可以做得很简:一颗小封装 MCU、一颗 PJ85718DM、一颗 SP3485,加一个隔离电源模块。MCU 负责读传感器、换算温度值、回应 Modbus 请求。温度值按 0.01℃ 为单位放进寄存器,比如 25.00℃ 就存 2500,避免浮点传输。

主控侧的 RS485 接口要注意方向和隔离。方向控制引脚直接连到 STM32F767BI 的 GPIO,发送前拉高,发完拉低。收发器的 RO 和 DI 引脚上建议串 100Ω 电阻再进 MCU,防止总线异常时把芯片打坏。通信距离超过 300 米或者节点有强电回路的,必须用带隔离的 RS485 模块,否则雷击或地电位漂移很容易干掉一串设备。

2.4 测温位置的布局坑

这个坑我在第一版板子上踩得很痛:PJ85718DM 贴着 DC-DC 电源模块放,距离不到 5mm,软件里怎么改滤波都压不平读数,因为温度本身就是高的。传感器测的是 PCB 局部温度,不是环境温度,这是物理规律,不是软件能修的。

实践结论:本地传感器要放在通风路径上,远离 DCDC、功率 MOS、继电器等发热源。如果空间受限实在避不开,至少让 PCB 铜皮热阻大一点,比如传感器底下不要铺大面积铜皮,做挖空处理。对 HVAC 面板来说,把本地温度传感器放在出风口位置最合理,因为那里气流能代表控制器实际工作环境。

远程节点同样有这个坑,但表现得更隐蔽。有些人把温度模块贴在风管铁皮上,读数接近铁皮温度,隔着一层保温棉,和真正的空气温度差好几度。远程测温探头的安装原则是:探头伸入气流中心,探头周围要有足够通风,不要让设备外壳加热探头,也不要让阳光直射。

3. 软件实现:从寄存器到温度值

3.1 I2C 读取 PJ85718DM 的完整流程

PJ85718DM 的寄存器布局和很多同类型 I2C 温度传感器一致:温度寄存器在 0x00,配置寄存器在 0x01,下限阈值在 0x02,上限阈值在 0x03。读取温度时我直接用 STM32 的 HAL 库函数:

uint8_t buf[2]; HAL_StatusTypeDef ret; ret = HAL_I2C_Mem_Read(&hi2c1, dev_addr << 1, 0x00, I2C_MEMADD_SIZE_8BIT, buf, 2, 100); if (ret != HAL_OK) { // 重读一次,连续两次失败则标记传感器离线 } int16_t raw = (int16_t)((buf[0] << 8) | buf[1]); float temp = (float)(raw >> 4) * 0.0625f;

这里的关键是dev_addr << 1。PJ85718DM 从机地址是 7 位形式(比如 0x48),STM32 HAL 库要求在 7 位地址左移一位变成 8 位地址,很多新手在这里翻车:忘了左移,或者左移之后又补了读写位。我在工程里专门做了个宏定义,不容易错。

温度数据格式是 12 位有符号数,低 4 位无用。raw >> 4相当于把数据右对齐,再乘 0.0625。注意这一步必须用有符号变量,否则零下温度会变成很大的正数。我见过有人把 0℃ 以下读数写成三百多度,就是因为这个低级错误。

读回数据之后别急着直接用,我做了两层处理:

第一层:连续读三次取中值,剔除明显毛刺。I2C 在工业环境下偶尔会出现一个字节被跳变,中值滤波是开销小、效果好的一种方式。

第二层:滑动平均。每 500ms 读一次,保留最近五次的平均值,用于显示和告警判断。中值滤波负责去掉尖刺,滑动平均负责平滑缓慢波动,两层叠加,界面上的温度数值不会抖得人眼发花。

3.2 用 Modbus RTU 轮询远程节点

远程节点通信我用 Modbus RTU 主机模式,波特率 9600,8N1,这是暖通设备默认到不能再默认的配置。好处是传感器的寄存器可以通过一个完全公开的协议读取,第三方上位机、触摸屏、组态软件都能直接对接。

查询一帧要读取节点 1 的保持寄存器 0x0000:

01 03 00 00 00 01 CRC_L CRC_H

响应帧通常是:

01 03 02 09 C4 CRC_L CRC_H

09 C4 就是 2500,表示 25.00℃。这里我用 0.01℃ 分辨率替代浮点数传输,省掉协议里处理 float 的麻烦。工程上,浮点格式每个 Modbus 厂商定义还不一样,用整数加约定分辨率是通用做法。

CRC16 校验算法必须自己实现,很多组态库里有,但嵌入式里还是自己写最干净:

uint16_t crc16_modbus(uint8_t *buf, uint16_t len) { uint16_t crc = 0xFFFF; while (len--) { crc ^= *buf++; for (uint8_t i = 0; i < 8; i++) { if (crc & 0x0001) crc = (crc >> 1) ^ 0xA001; else crc = (crc >> 1); } } return crc; }

发送时字节序是 CRC 低字节在前,高字节在后,这个顺序很多工具生成的 CRC 是高字节在前,直接对接会一直报“响应超时”。我在联调某厂商温度模块时吃过这个亏,第一次抓波形才发现是 CRC 字节序在捣乱。

地址分配上把远程节点规划为 1 到 N,不要用 0,0 在 Modbus 里是广播地址,只能写不能读。总线上的节点地址要唯一,最好通过拨码开关硬件配置,避免去现场拆机改程序。

3.3 通信异常重试与温度融合

RS485 是半双工物理层,不存在同时收发的可能,所以主控的程序要设计一个严格的时间片。每次发完查询帧后,等待响应的时间至少 100ms,超时则认为该节点离线。不要一超时就停掉整条总线的轮询,否则一个节点掉线,后面的节点全被堵死。

我用的轮询状态机简化流程:

  1. 维护一个节点列表,依次发送查询帧。
  2. 发送完成后启动超时定时器,把串口切换到接收状态。
  3. 收到正确响应帧、CRC 无误后,解析温度并刷新缓存。
  4. 连续 3 次超时,标记该节点离线,界面显示“离线”,但继续轮询这个节点,给它恢复机会。
  5. 全部节点轮询一遍后,更新一次显示和告警逻辑。

三种节点数量的典型轮询周期:

节点数量每节点发送字节数9600bps 下理论耗时实际轮询周期
18 字节约 10ms300ms
48 字节约 40ms500ms
168 字节约 160ms1s

实际周期要比理论耗时大得多,因为要留够从机处理延时和收发保护间隔,宁可轮询慢一点,也不能把总线占满。

本地温度和远程温度最后要统一成一套数据结构。我的做法是定义了一个温度通道数组,每个通道包含温度值、更新时间戳、告警阈值、在线状态。本地 PJ85718DM 是编号 0 的通道,远程温度依次排下去。显示、告警、联动全部遍历这个数组,不用针对单点传感器写逻辑。

4. 人机界面、告警输出与数据记录

4.1 用 LTDC 驱动 TFT 屏显示温度趋势

STM32F767BI 的 LTDC 可以直接输出 RGB 数据到 7 寸屏。CubeMX 里配置时序参数是第一步:像素时钟、行同步、前后沿这些必须和屏幕手册逐一对上。800×480 屏幕的像素时钟一般取 30MHz 上下,我生成工程后一开屏就是花屏,最后用示波器一格格调像素时钟才解决,问题就是时钟频率偏高。

帧缓冲放在外扩 SDRAM 里,LCD 层的起始地址设为 SDRAM 基地址,屏显示期间 CPU 照常运行。温度曲线绘制我走得很简单:每个温度通道画一条颜色线,X 轴是最近 240 个点,Y 轴根据量程自动缩放。数据更新时把数组整体左移一格,然后调用矩形填充函数重画屏幕。这套方案刷一屏大概几十毫秒,完全够用,没必要为了 60 帧动画开销引入 RTOS 显卡加速。

界面上除了曲线,还要把每个通道的当前温度大字显示出来,数值颜色区分正常/告警。远程节点离线时,数据显示“--”,曲线断开,而不是乱画上一次的值。这里要特别注意:很多人会在离线时把上一次数值继续画,结果曲线在接口断了之后变成一条直线,误导操作人员判断现场状态。

4.2 越限告警与继电器滞回

告警不能只做一次比较。比如设定室内温度高于 30℃ 时开启制冷,温度在 29.9℃ 和 30.1℃ 之间反复波动,继电器会非常频繁地吸合和断开,机械寿命刷刷往下掉,还会引起系统振荡。解决方法是滞回控制:

  • 温度高于 30℃:继电器吸合,制冷启动。
  • 温度回落到 28℃:继电器断开,制冷停止。
  • 中间区间 28℃~30℃:保持当前状态。

代码逻辑:

typedef struct { float on_threshold; float off_threshold; uint8_t output_state; } Hysteresis_t; void update_hysteresis(Hysteresis_t *hys, float temp) { if (hys->output_state == 0) { if (temp >= hys->on_threshold) hys->output_state = 1; } else { if (temp <= hys->off_threshold) hys->output_state = 0; } HAL_GPIO_WritePin(RELAY_PIN, hys->output_state); }

告警输出也要按通道分别配置。本地温度过高告警属于“设备保护”,动作是切断重要负载或者强制全速风扇;远程温度越限属于“环境控制”,动作是启停空调设备。这两种动作优先级要分开,我在工程里做了一个简化的优先级表:设备保护告警直接拉高硬件告警引脚,声音提示最强;环境控制告警只在界面提示,不打断设备运行。如果所有告警都混在一个蜂鸣器和一个颜色里,现场人员根本没法分清是控制器要烧了还是房间热了。

4.3 SD 卡 CSV 记录与掉电保护

温度数据不记录下来,调试时很难复盘。我在 SD 卡里按天保存 CSV 文件,文件名格式TEMP_20250214.CSV,内容列包括时间戳、本地温度、远程通道 1 温度、远程通道 2 温度、告警状态。一分钟记录一条,一天 1440 行,一个文件才几十 KB,SD 容量完全不是问题。

FATFS 文件系统挂载后,我用f_printf追加写入。这里有个坑:每次直接写入 CSV 的开销并不大,但频繁创建新文件会导致 FAT 表操作变慢,尤其断电后经常损坏文件。我的做法是系统上电时打开一次文件,之后在内存里累积记录,每 10 条批量 flush 一次。这样掉电最多丢最近十几秒的数据,不会整文件丢失。

时间戳通过 RTC 提供。F767 的 RTC 需要外部 32.768kHz 晶振和一个备份电池。别省这个,没有 RTC 的记录文件是没有灵魂的,事后拿着温度曲线却不知道是什么时间段记录的数据,等于白记。

5. 现场调试与踩坑记录

5.1 I2C 总找不到设备的排查

第一版板子回来后,PJ85718DM 的 I2C 地址怎么扫描都扫不到,示波器看 SCL 有波形,但 ACK 永远出不来。排查链路如下:

一是确认地址是否左移正确。代码里用了(0x48 << 1),示波器抓波形时第一个字节应该是 0x90 然后再加读位,如果我写错成 0x48 当 8 位地址,那数据线上出来的就是 0x24,传感器根本不会应答。

二是确认上拉电阻是否焊接。缺少上拉的 SDA/SCL 波形上升沿会非常缓慢,甚至电平抬不到高电平。很多白板板子看起来原理图没错,但贴片电阻漏贴。

三是确认 PJ85718DM 的电源引脚是否有电。这个看起来白痴的问题真的发生过,电源轨是后加的,被跳线帽切成两段,传感器那一路根本没通。

给出一个快速的工程排查手段:用直接寄存器读写函数,在 while(1) 里循环发 I2C 扫描命令。先把地址从 0x08 扫到 0x77,凡是有 ACK 的地址全部打印出来。扫描成功后跑原流程,基本上一分钟定位问题。

5.2 温度长期偏高 0.3℃ 的自热问题

有一块主板本地温度总是比同环境的工业温度计高 0.3℃~0.4℃,刚开始以为是传感器精度问题,查手册精度 ±0.5℃,觉得在范围内就不用管。后来把同样型号的板子放到风道里,差值变成 0.8℃,这才意识到问题不是传感器本身,而是自热。

PJ85718DM 这类芯片的功耗虽然以微安计,但芯片自身和周边铜皮、走线仍然会有一点温升,尤其当你把它放在 PCB 的背风侧,板上的热量散不掉时,误差很稳定地存在。处理办法有两种:

  • 硬件上:传感器焊盘周围做隔热处理,减少铜皮把主板的温度传导给它。
  • 软件上:校准补偿,零度冰浴确定偏移量,再在某个恒温点确定斜率,最后加一个温度补偿公式。

对于 HVAC 应用,0.5℃ 以内的误差通常可接受,但要注意一点:这个误差是稳定的话,在控制逻辑里通过测量值修正很容易修正,怕的是误差随负载电流忽大忽小变化,那样就别执着软件补偿了,先改硬件散热。

5.3 RS485 偶发乱帧的一次完整排查

现场遇到一个很奇怪的现象:两台远程节点的温度模块,单独接任何一台都很稳,两台一起挂在总线上之后,每过十几分钟就有一帧报 CRC 错误。当时在现场用了整个下午排查。

第一步:接示波器看总线波形。RS485 空闲时 A 对 B 的电压应该在 1.5V 到 5V 之间。看波形发现,两台的模块电源不是同一个系统供电,A 模块地线上的噪声比较大,衰减到接收端之后信号裕量不足。

第二步:检查接线端子。某厂商的模块端子标注里,A 和 B 的定义与其他家恰好相反,虽然接线时随意接也能通信,但总线上两个模块的 A/B 定义不一致时,逻辑电平方向就乱了。这个只能靠核对每个模块的说明书,不能想当然。

第三步:处理共地。RS485 虽然差分信号理论上传输不依赖地,但在长线情况下两端的电源地必须有良好参考,否则共模电压超过收发器范围就会乱帧。我的解决方案是在总线上增加一芯信号地线,所有节点的地连在一起,并加装一个隔离 RS485 模块。

最后把终端电阻加上:总线首端和末端各一个 120Ω 终端电阻。短距离测试不接也能通,距离拉长后总线反射会让波形畸变,低概率出现乱帧。这三个动作做完,整个系统稳定跑了一周,CRC 错误率降到零。

5.4 温度校准方法

传感器出厂精度并不是你系统最终精度。传感器、ADC 参考、PCB 布局、外壳热阻都会叠加误差。校准我从简单到复杂做了三层:

第一层是冰点校准。把传感器探头用密封袋包好,放进冰水混合物的保温杯里,冰水比例大约 1:1,搅拌后等待 10 分钟,读数应该接近 0℃。记录和设定值的差值,就是零点偏移。

第二层是单点高温校准。利用恒温槽或者至少是工业恒温箱,设定到 50℃ 或者 60℃,再用一支经过计量校准的铂电阻温度计做参考,读出系统显示值和参考值的差值,结合冰点值,算出两点直线修正系数。

第三层是软件补偿。修正公式就是:修正温度 = 测量温度 × 斜率修正系数 + 零点补偿。把系数存到片内 Flash 里,出厂和现场复校时更新。

现场如果没有恒温槽,可以用沸水法做 100℃ 粗校,但要注意海拔对沸点的影响,当地大气压不同,沸点会偏离 100℃,精度要求不高时够用。

6. 实测数据与扩展设想

6.1 某项目现场 24 小时的温度记录

最后放一组某现场调试运行 24 小时的实际数据摘录。这套系统当时挂了本地传感器和三路远程温度节点,控制对象是一台循环风机,远程温度高时启动,低于设定值停止。

时间段本地温度远程1远程2远程3风机状态
00:0023.224.523.822.9停止
04:0022.824.023.122.5停止
08:0024.125.825.224.3启动
12:0026.929.628.427.5启动
16:0026.128.227.126.0停止
20:0024.425.924.823.9停止

可以看到本地温度贴近现场机柜,远程 1 最靠近热源,反应最灵敏。风机启动后靠远程 1 的温度回落信号实现循环控制,这个逻辑非常可靠。数据同时落到了 SD 卡,事后画出来的曲线和现场记录完全吻合。

这套数据也证明了不同位置温度的剧烈差异:最热时本地和远程 1 的差距有 2.7℃,单点测温不可行的结论直接被数据推翻。

6.2 后面还可以怎么扩展

这套基础架构本身扩展性不差:要把远程节点从 4 个扩到 32 个,只需要在轮询列表里增加节点地址;要把 485 总线改成 CAN,F767BI 自带的 FDCAN 直接能用;要把数据上报到上位机,F767 的以太网 MAC 加一颗 PHY 芯片就可以。

我自己最想做的改进是把远程温度节点往无线方向迁一层。RS485 拉线在旧厂房改造时实在不方便,暖通行业里越来越多的无线传感器节点(比如基于 433M 或 BLE 的工业节点)开始普及。但无线方案需要处理电池供电、低功耗休眠、无线通信频度这三者的平衡,这是下一版的事。至少在现在已经完成的这套 PJ85718DM + STM32F767BI 系统上,本地与远程温度终于在一个主控里被统一管理,想保护的地方有保护,想控制的区域有反馈,这就是测温系统该有的完成度。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询