做嵌入式控制器或者HVAC温控面板的同行应该都有过这种纠结控制板装在铁皮箱子里既要盯着板子附近空气温度防止继电器粘连、电源过热又要知道几米外风道口或者水管壁的真实温度。以前我习惯挂两个独立传感器一个放板上一个甩到现场中间拉一长根四线线缆成本和布线都很狼狈。后来在某项目里改用PJ85718DM STM32L152ZD的组合一颗温度传感器芯片解决本地与远程双通道测温一颗自带LCD驱动的超低功耗MCU负责采集、显示和逻辑控制整块板子干净了很多。这套方案适合谁做嵌入式控制器的、做暖通空调温控面板的、做机柜环境监控和冷链设备的都可以参考。接下来我会从硬件选型开始讲把两颗芯片怎么搭、远程测温通道怎么接、I2C寄存器怎么操作、显示和低功耗怎么安排包括我实测过程中踩过的坑一次性说清楚。1. 为什么本地和远程温度监测会同时出现在一块主板上很多新手看到本地温度 远程温度这种描述第一反应是一个芯片怎么能同时测两个地方的温度。其实这在温控类产品里非常常见而且背后是两个完全不同的工程需求。1.1 本地温度的监测对象是板子自己本地温度说白了就是控制器自身的体温。继电器、开关电源、功率管、线性稳压器这些发热大户都挤在同一个小空间里嵌入式主板在密闭金属箱里一跑就是好几年环境温度可能远高于室温。这时候本地温度监测至少有三个作用开机自检温度异常通常意味着风机堵转、散热不良甚至元器件虚焊。寿命保护电解电容、液晶屏、锂电池最怕高温检测到超温后可以主动降额运行或者提前报警。补偿计算很多高精度ADC测量、电池电量计算都需要温度补偿没有本地温度后面这些算法都缺一条腿。具体到HVAC控制器里本地温度还能反映控制箱内环境是否正常。比如夏天配电箱晒在屋顶箱内温度能到60°C如果控制器不感知这个温度继电器绝缘材料老化速度会明显加快。1.2 远程温度监测的对象才是现场真正需要参与闭环控制的往往是几米甚至十几米外的盘管、风道、供水管、回水管或者房间空气。HVAC领域的远程测温方案大体有三种NTC热敏电阻便宜但非线性严重需要校准而且长线会引入误差线缆电阻不好补偿。独立数字传感器放到远端I2C或者单总线需要额外供电远端要一块PCB成本高。二极管测温传感器本体留在主板上只通过两根线引出到一个二极管或三极管PN结远端探头成本几乎可以忽略。PJ85718DM 这类芯片走的就是第三条路。芯片内部提供恒流源激励远程二极管通过测量PN结正向压降 (V_{BE}) 随温度变化的规律来计算温度同时用不同电流下的 (\Delta V_{BE}) 抵消二极管反向饱和电流的差异。远程探头用普通双绞线就能拉出去线材成本很低。需要提醒的是二极管测温距离不是无限远的。常见场景在1米到10米左右超过之后线缆电阻的影响会变大读数会整体偏低这个问题在文章第6部分我会详细讲。1.3 双通道监测带来的工程实惠用一个芯片替代两个传感器最直接的好处是BOM精简、PCB面积减小、驱动代码统一。但更重要的价值在于两路数据可以配合使用本地温度用于保护控制板超温就关加热负载或者降低PWM占空比。远程温度用于控制现场温度低于设定值就启动风机或打开阀门。我在调试阶段还发现一个用法——通过比较两路温度差来判断系统是否真的在工作。比如供暖工况下远程温度和本地温度应该有一个合理的梯度如果两路温度几乎一样那多半是探头没装好或者阀门没动作现场很容易发现。2. PJ85718DM 与 STM32L152ZD 这两颗料怎么搭才合理选型这件事不能只看某颗芯片的纸面参数要看两颗芯片配合起来能不能解决产品的主要矛盾。这个组合的核心逻辑是一颗带远程测温能力的传感器芯片加一颗自带显示控制器的超低功耗MCU。2.1 PJ85718DM 核心特性梳理先把我实际用得上的关键参数列出来。不同批次或封装可能略有差异具体以手头手册为准。项目参数说明数字接口I2C最高 400kHz标准两线制主从通信本地温度范围-40°C ~ 125°C覆盖绝大多数嵌入式场景远程测温方式外部二极管/三极管PN结两根线引出探头成本极低典型精度±1°C本地和远程均有校准手段温度分辨率12bit约0.0625°C/LSB读数平滑适合做控制供电电压3.0V ~ 3.6V与MCU共用3.3V电源报警输出开漏ALERT引脚可配置比较模式或中断模式这颗芯片最特别的地方就是传感器本体和远端探头分离。芯片放在主板上采集的是主板附近温度同时通过D/D-两个引脚去读远端二极管的温度。寄存器布局和市面上常见的双通道温度传感器比较接近工程上迁移起来很顺手。2.2 STM32L152ZD 为什么适合做温度监测主控STM32L152ZD 这颗料我用了不少次它在温控面板场景里的优势非常明显Cortex-M3 内核最高 32MHz跑传感器驱动、简单PID、显示刷新都绰绰有余不需要上M4。内置LCD控制器可以直接驱动段码液晶屏省掉外部LCD驱动芯片。温控面板最核心的交互就是显示温度和状态符号这个外设是决定性的。超低功耗Stop模式下RTC可以继续走时电流只有微安级适合7x24小时在线或者电池供电。外设齐全多路I2C、SPI、USART后面要挂RS485、LoRa模块都很方便。选型时我特意确认了一件事这颗MCU的I2C外设和LCD控制器能否同时工作。实际项目验证下来没有任何冲突LCD刷新由硬件自动完成CPU只在要更新内容时写显示RAM不占额外开销。2.3 什么情况下不该选这套组合任何方案都有边界提前想清楚反而能少走弯路如果只测一个本地温度显示三两位数字那8位MCU加一颗单总线传感器更便宜。如果要做彩色触摸屏界面STM32L1系列的性能就不够了需要换带RGB接口或MIPI的Cortex-M4/MPU平台。如果远程探头要放到100米外二极管方案要慎重优先考虑RS485分布式采集或无线传感节点。我在选型文档里把这些边界都写清楚了免得后面产品迭代时被问为什么当初不选更便宜的方案。3. 硬件连接传感器通道的布线、电阻匹配与抗干扰设计芯片选好了真正的坑从原理图开始。硬件设计如果偷懒软件再怎么写也救不回来尤其是远程那两根线。3.1 电源与最小系统PJ85718DM 和 STM32L152ZD 都工作在3.3V电源可以共用一组LDO输出。需要注意几点MCU的VDD和VDDA分开滤波VDDA引脚通常要串磁珠再接3.3V避免数字噪声耦合进模拟电路。传感器电源引脚旁边放一个100nF去耦电容有条件再加1μF保证I2C通信在转换瞬间电流变化时电压不跌落。传感器不要贴着电源芯片、继电器或功率电阻摆放否则本地温度读数会失真。我在样板阶段把传感器放在电源芯片旁边测过一次本地温度比实际环境高了接近8°C后来挪到PCB角落、靠近进风口位置才正常。3.2 I2C上拉电阻与电平匹配I2C的SDA和SCL都是开漏必须外接上拉电阻。3.3V系统里常见取值是4.7kΩ总线器件多或者走线超过10cm时建议降到2.2kΩ。我一般直接按2.2kΩ设计既满足400kHz的上升沿要求也不会造成太大灌电流。如果板上还有5V器件I2C电平需要转换不要试图用电阻分压凑合。I2C是双向开漏分压方式会在从机拉低时出问题最可靠的是加一颗双向电平转换芯片。这个坑我见过不止一次处理不好会间歇性死机。3.3 远程二极管通道的走线与匹配远程通道是这套方案里最需要花心思的部分。几个要点D和D-两条线要尽量并行、等长最好直接使用双绞线减少共模干扰。远离继电器控制线、电源线、PWM走线这些线路上的瞬态干扰会耦合进测温通道。远端探头推荐用小信号三极管的BC结短接比如常见的2N3904/2N3906PNP/NPN都可以具体看芯片手册要求。相比普通开关二极管小信号三极管结特性更稳定。线缆屏蔽层要单端接地不要两端都接否则会形成地环路。现场用普通双绞线就行没必要选大截面电缆截面大了反而热容大温度响应变慢。串联电阻是远程测温的主要误差来源。线缆每增加一些电阻读数就会偏低一些因为电阻分压吃掉了部分测量信号。好在很多芯片会提供串联电阻补偿寄存器按线缆电阻值写入补偿系数即可这个细节产品化时很重要。3.4 报警输出引脚接法PJ85718DM 的ALERT引脚是开漏输出需要接上拉电阻到3.3V然后连到MCU的一个外部中断引脚。超温时传感器自己会把引脚拉低MCU不轮询也能及时响应。上拉电阻取10kΩ就行这个引脚不需要很快的边沿关键是电平可靠。注意不要在ALERT脚上直接接继电器驱动它只能输出低电平信号不是功率输出。3.5 完整接线汇总下面是我这个项目里的实际接线清单供参考传感器引脚连接到说明VDD3.3V接100nF去耦电容GND地单点接地SDAMCU PB9开漏上拉到3.3VSCLMCU PB8开漏上拉到3.3VD远端二极管阳极双绞线引出D-远端二极管阴极双绞线引出ALERTMCU外部中断引脚开漏上拉10kΩ接完线之后先不要上电用万用表量一下D和D-之间的通断确保没有接反、没有短路。这一步能省掉后面大量排查时间。4. 软件实现I2C寄存器操作与温度数据转换的完整流程硬件焊好了接下来就是让芯片开口说话。温度传感器的软件其实不复杂但寄存器操作顺序和数据处理细节容易出问题。4.1 从零初始化I2CSTM32L152ZD 的I2C工作在400kHz主模式配置成开漏复用功能。这里用寄存器风格写一版方便理解底层逻辑实际用CubeMX生成的工程也是一回事void I2C1_Init(void) { // 使能GPIOB和I2C1时钟 RCC-AHBENR | RCC_AHBENR_GPIOBEN; RCC-APB1ENR | RCC_APB1ENR_I2C1EN; // PB8SCL, PB9SDA复用开漏模式 GPIOB-MODER ~(3UL 16 | 3UL 18); GPIOB-MODER | (2UL 16 | 2UL 18); GPIOB-OTYPER | (1UL 8 | 1UL 9); GPIOB-AFR[1] | (4UL 0) | (4UL 4); // AF4: I2C1 // 配置I2C时序此处为示意实际按系统时钟查表计算 I2C1-TIMINGR I2C_TIMINGR_400KHz; I2C1-CR1 I2C_CR1_PE; }有几个细节需要确认I2C引脚必须配置为开漏内部上拉不要依赖宁可不用也要外接上拉复用功能映射要看引脚手册不是所有PB8/PB9都能映射到I2C1的同一个AF编号。4.2 传感器寄存器配置流程读取温度之前需要先确认传感器处于连续转换模式并且分辨率设置正确。常见的寄存器布局是指针寄存器选择后续操作的目标然后通过读写数据寄存器完成配置。#define DEV_ADDR 0x48 // 以手册实际地址为准 #define REG_CONFIG 0x01 #define REG_TEMP_LOCAL 0x00 #define REG_TEMP_REMOTE 0x02 #define REG_THIGH 0x03 #define REG_TLOW 0x04 void PJ85718DM_Init(void) { uint8_t cfg 0x60; // 连续转换、12bit分辨率 WriteReg(DEV_ADDR, REG_CONFIG, cfg); delay_ms(100); // 等待首次转换完成 }初始化之后不要立刻读温度一定要等待一段时间让芯片完成首轮转换。不同芯片转换时间不同短的几十毫秒长的几百毫秒。这个等待如果省了首屏读数可能是一个随机值。4.3 读取温度并转换为实际数值温度数据一般以两个字节形式存放在寄存器里。以12bit分辨率为例把高字节和低字节拼接后右移4位得到一个有符号12位整数值乘以0.0625就是摄氏温度。int16_t ReadRawTemp(uint8_t reg) { uint8_t buf[2]; ReadRegs(DEV_ADDR, reg, buf, 2); int16_t raw ((int16_t)buf[0] 8) | buf[1]; return (int16_t)(raw 4); // 12bit有符号数 } float CalcTemp(int16_t raw) { return raw * 0.0625f; } // 用法 int16_t rawLocal ReadRawTemp(REG_TEMP_LOCAL); int16_t rawRemote ReadRawTemp(REG_TEMP_REMOTE); float localC CalcTemp(rawLocal); float remoteC CalcTemp(rawRemote);这里最容易犯的错是忘记右移4位。如果不右移读数会放大16倍显示出来就像胡言乱语。另一个坑是符号位扩展低温和零下温度时必须有符号扩展否则超过0°C的高位可能变成奇怪的正数。用右移而不是除法来处理带符号数这一点在C语言里要格外注意。4.4 报警阈值设置与中断处理温度监测如果只靠MCU轮询实时性永远受采样周期限制。利用传感器自带的报警比较功能把阈值判断下沉到硬件系统更可靠。void PJ85718DM_SetAlert(float highC, float lowC) { uint16_t highRaw (uint16_t)(highC / 0.0625f) 4; uint16_t lowRaw (uint16_t)(lowC / 0.0625f) 4; WriteReg16(DEV_ADDR, REG_THIGH, highRaw); WriteReg16(DEV_ADDR, REG_TLOW, lowRaw); }报警模式要分清两种场景比较模式温度超过阈值ALERT持续拉低直到温度回到滞回区间才恢复。适合驱动风机、加热器等执行机构。中断模式温度超过阈值ALERT拉低一次MCU读取状态寄存器后才清除。适合作为异常上报给上位机。MCU中断处理代码的基本逻辑是进入外部中断 - 读状态寄存器 - 判读是超上限还是低于下限 - 执行保护动作 - 清除中断标志。4.5 滤波与数据平滑传感器原始读数多少会有点噪声尤其远程通道走线比较长时读数末尾跳动1~2个数字量非常正常。软件上我习惯做滑动平均保留最近8次采样去掉一个最大值和一个最小值剩下6个取平均。这个办法在轻噪声场景里远比一阶低通滤波干净。一阶低通形式也可以但要注意系数float filtered 0; filtered filtered * 0.8f rawTemp * 0.2f;系数越大越平滑但响应越慢。控制环用的温度可以加大平滑系数报警判断则不要用太重的滤波否则超温都发生好几秒了报警还因为滤波滞后没触发。我的做法是控制温度和报警温度各用一路数据报警路径只用轻滤波或者原始值。5. 显示、存储与低功耗把温度数据真正用起来能读出温度只是第一步产品里还要考虑怎么显示、怎么记录、怎么省电。这部分做得细致现场的易用性差别很大。5.1 用STM32L152ZD内置LCD控制器直接驱动段码屏STM32L152ZD 内置LCD控制器可以直接驱动段码液晶省掉外部LCD驱动芯片。初始化LCD外设需要配置引脚和控制器参数显示时往LCD RAM写数据即可。void LCD_Init(void) { // 1. 配置LCD引脚为复用功能 // 2. 设置LCD_CR选择占空比和偏压 // 3. 设置LCD_FCR配置分频系数和闪烁功能 } void LCD_DisplayDigit(uint8_t pos, uint8_t value) { // 段码表0-9和特殊符号对应的段位组合 static const uint8_t seg[10] {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; LCD_RAM[pos] seg[value]; }段码屏的COM和SEG引脚与LCD RAM位之间不是线性对应的要对照屏厂手册做映射。我第一次接屏时没仔细看手册按直觉一条条排段码结果屏幕显示乱码后来老老实实画表半小时内就调通了。我的经验是把所有数字、小数点和特殊符号的段码组成一个查表数组更新显示时只调用一个函数这样软件逻辑和硬件映射完全隔离以后换屏只用改表。5.2 温度历史记录利用Flash做掉电保存温控设备通常要记录温度曲线用于事后分析和故障追溯。如果量不大MCU内部Flash就够了。关键点是别频繁整片擦写。Flash扇区擦除寿命有限如果温度每5分钟写一次每次擦一个扇区很快就把寿命耗完了。正确做法是以扇区为单位做环形缓冲数据攒满一个扇区才擦写一次。每5分钟存一个点一天288个点一个扇区能存很长时间。报警阈值、校准偏移这类关键参数单独放在另一个扇区和温度日志分开。如果设备要保留几个月的数据还是老老实实外挂SPI NOR Flash或者EEPROMMCU内部Flash只存配置参数。5.3 低功耗调度从Stop模式定时唤醒采样HVAC面板一般常供电低功耗不算核心需求。但如果产品是电池供电的温控器调度策略就是决定续航的大事了。我的做法是正常情况MCU进入Stop模式RTC定时唤醒。唤醒后启动I2C读取本地和远程温度刷新LCD检查报警。数据处理完后立即回到Stop模式。传感器功耗也要控制。如果传感器没有使能脚就把它的电源放在一个MOS管控制的电源域下采样时打开采样完关闭。注意传感器上电后需要稳定时间不能刚上电就立刻读先等转换完成再通信。实测下来一分钟采样周期配合采样后断电整机平均电流能做到非常低多数的功耗反倒是LCD和待机电源消耗。省电优化一定要以实际示波器测量为准不要拿芯片手册值估算。5.4 数据上抛与通信协议很多HVAC项目需要把温度数据送到网关或者楼宇自控系统。常用的通信方式是RS485加Modbus协议成本低、抗干扰强。STM32L152ZD的USART外接一个收发器即可。温度上抛我建议用定点数而不是浮点数比如把温度乘以100转成整数再发送可以避免浮点解析偏差也简化协议。上位机约定好温度除以100就是摄氏度就行。通信时还要带数据有效性校验比如CRC或者累加和防止线路干扰造成错误数据。6. 实测中踩过的问题与校准补偿经验这部分是我最想写的内容。理论计算和实际项目差距往往就藏在那些不起眼的细节里。下面几个问题都是我在开发中真实遇到的按排查链路写出来希望能帮大家少走弯路。6.1 远程温度读数整体偏低的排查链路现象远程通道比水银温度计偏低3°C左右本地通道读数正常。排查过程先确认远程二极管极性D接二极管阳极D-接阴极。接反后读数会异常或者直接不变化。检查二极管类型探头一定要用芯片手册推荐的类型最好是小信号三极管的BC结短接。普通开关二极管的结特性差异大系统偏差会很明显。测量线缆电阻用万用表量D和D-回路的整体电阻。线阻越大读数偏低越明显。每增加一些电阻温度误差就增加零点几到一度。查芯片的串联电阻补偿寄存器如果支持按实测线阻写入补偿值。这个补偿很有效但不能解决所有问题。软件偏移校准在转换结果上加上一个固定offset。这种方法只能补偿恒定偏差线阻随温度变化带来的误差补偿不了。这个排查顺序非常重要从硬件到软件逐个排除比直接调软件offset靠谱得多。我只调软件偏移当时确实把当前环境下的误差修好了但天冷了线缆电阻变化读数又偏了最后反过来查硬件才算根治。6.2 报警输出频繁抖动现象温度在阈值附近徘徊ALERT引脚反复拉低继电器频繁动作几分钟一次。原因有两个都可能导致滞回区间设得太小。控制回路里的温度天然有小幅波动阈值上下沿只有零点几度时报警逻辑就会在边界反复翻转。比较模式和高低阈值关系没搞清楚。有些芯片的高阈值对应的是超上限报警低阈值对应低于下限报警如果寄存器赋值反了状态机就会乱。解决方法是双管齐下// 设置滞回高阈值 2°C低阈值 -2°C PJ85718DM_SetAlert(controlSetpoint 2.0f, controlSetpoint - 2.0f);另外在软件侧给执行机构加防抖逻辑比如ALERT低电平要连续确认5次每次间隔1秒才真正切换继电器。这样即使传感器输出有一定抖动执行机构也不会频繁动作。6.3 I2C总线死锁远程走线较长时偶尔会遇到I2C读挂死的情况尤其是总线上挂多个器件时。排查下来常见原因是从机状态机跑飞SDA被从机拉死不释放。主机还在通信过程中掉了电或者复位导致STOP条件没发出去。走线环境干扰让从机误判到错误的起始条件。I2C协议本身没有超时机制一旦从机死锁主机只能自己恢复。我写了一个总线恢复函数手动给SCL产生9个时钟脉冲让从机状态机复位再发一个STOP条件void I2C_BusRecovery(void) { // 把SCL临时配置为普通GPIO输出 // 产生9个时钟脉冲 for (int i 0; i 9; i) { GPIO_SCL_HIGH(); delay_us(5); GPIO_SCL_LOW(); delay_us(5); } // 再发一个STOP条件SDA先低后高SCL保持高 GPIO_SDA_LOW(); GPIO_SCL_HIGH(); GPIO_SDA_HIGH(); delay_us(5); }这个方法救回了大多数I2C死锁。如果还是不行优先检查复位电路和电源纹波别只盯着通信协议。6.4 两路温度之间的相互校验这是一个非常实用的调试技巧当本地传感器和远程二极管处于同一个热环境时两路读数应当接近差1~2°C以内是正常的。如果差异特别大基本可以判断是远程通道的硬件问题。我把它做成了系统自检功能上电后自动比较两路温度如果差值超过设定范围就在LCD上显示故障码。这个功能在HVAC项目现场维护时特别有用——维护人员不用拿着测温枪逐个检查探头直接看面板就能知道是通道开路、接反还是线阻过大。6.5 批量生产时的校准如果产品对温度精度要求高单靠芯片出厂精度可能不够批量生产时需要考虑整机校准。我的流程是每台设备在恒温槽里做两点校准比如0°C和50°C。根据两点误差计算校准斜率和偏移量写入Flash。软件在每次读取后做线性校正float tempCalibrated tempRaw * gain offset;这里有一个容易忽略的细节校准时机要等整机通电稳定后再做最好是装上外壳、运行半小时以上。否则校的是冷态漂移状态装进现场壳子里后又偏了。我在产线上加了一步“上电老化半小时再校准”后精度良率提升明显。最后再分享一点个人体会。这套方案在我实际项目里最大的收益不是省了那一颗传感器芯片而是把“本地通道负责保护、远程通道负责控制”的逻辑固化了下来软件和硬件都简化了很多。如果你以后要做类似的温控设备建议先把这个问题想清楚本地温度用来干什么远程温度用来干什么两路之间需要什么关系然后再去接线和写代码会顺利很多。至于更进一步的扩展远程通道改成多路或者把数据推到云端都是在这套基础上继续加料的事。
阅读完成 · 觉得有帮助?