ds18b20与74hc573接线图


DS18B20温度传感器与74HC573锁存器:原理、接线与高级应用详析
在现代电子设计中,温度测量是一个基础且至关重要的环节。无论是工业控制、智能家居、环境监测,还是科学实验,精确可靠的温度数据都是系统稳定运行和功能实现的关键。DS18B20是一款广泛应用的数字温度传感器,以其单总线(One-Wire)接口、高精度和宽测量范围而著称。然而,在某些复杂的应用场景,例如需要大量DS18B20传感器进行温度采集,或微控制器(MCU)的GPIO资源有限时,直接驱动多个DS18B20可能会面临挑战。此时,结合通用锁存器如74HC573就成为一种高效的解决方案。74HC573作为八路D型锁存器,能够有效扩展MCU的控制能力,允许通过少量引脚控制更多外部设备,从而优化系统资源配置。
本文将深入探讨DS18B20温度传感器和74HC573锁存器的工作原理、特性参数,详细阐述两者结合的接线方法,并在此基础上,扩展讨论其在实际应用中的各种策略、常见问题及解决方案,以及未来的发展方向。我们不仅会提供清晰的接线图示,更会从硬件和软件两个层面,全面剖析如何构建一个稳定、高效的温度采集系统。
第一章:DS18B20数字温度传感器:核心技术与应用基石
DS18B20是Maxim Integrated(原Dallas Semiconductor)推出的一款革命性数字温度传感器。它的出现极大地简化了温度测量系统设计,取代了传统模拟温度传感器所需的复杂信号调理电路。
1.1 DS18B20的基本原理与特性
DS18B20的核心优势在于其内部集成的模数转换器(ADC)、温度传感器元件、非易失性存储器(EEPROM)以及独特的单总线通信协议。
1.1.1 温度测量原理
DS18B20通过内部的半导体PN结进行温度测量。半导体PN结的饱和电流I_S与温度T之间存在特定的关系。随着温度的变化,PN结正向电压会发生微小变化,DS18B20正是利用这种变化,通过内部的温度补偿电路和高精度ADC将其转换为数字信号。这种转换过程是经过精确校准的,确保了传感器在整个测量范围内的线性度和准确性。传感器内部还包含一个振荡器,用于计时和同步通信。
1.1.2 单总线通信协议
这是DS18B20最显著的特点。单总线协议仅需要一根数据线(DQ)和一个地线(GND)即可实现传感器与主机(如MCU)之间的双向通信。在寄生电源模式下,甚至可以省去外部电源线(VDD),仅通过数据线供电。这种极简的接线方式大大降低了硬件复杂性和成本。
单总线协议的通信过程基于精确的时序控制。主机通过拉低数据线来发起通信(复位脉冲),传感器在检测到复位脉冲后会发送一个存在脉冲,表示其已准备好通信。随后,主机通过发送不同的ROM命令和功能命令来读取传感器数据或写入配置信息。每位数据传输都包含一个起始时隙、一个数据时隙和一个恢复时隙,确保了数据传输的可靠性。
1.1.3 主要特性参数
测量范围广: DS18B20的温度测量范围通常为$-55^circ C到+125^circ C$,能够满足绝大多数环境温度监测的需求。
高精度: 在$-10^circ C到+85^circ C范围内,精度可达到pm 0.5^circ C$。更高的分辨率可通过配置寄存器实现。
分辨率可配置: 用户可以通过写入配置寄存器来选择9位、10位、11位或12位的温度分辨率。其中12位分辨率可提供$0.0625^circ C$的步进精度。
独特的64位ROM编码: 每个DS18B20都具有一个唯一的64位激光刻录的ROM编码,这使得在同一条单总线上可以连接多个DS18B20传感器而不会发生地址冲突,方便实现分布式温度测量。
报警功能: 传感器内部包含用户可定义的上下限报警寄存器(T_H和T_L)。当测量温度超出设定的范围时,传感器会设置一个报警标志,主机可以通过搜索报警设备命令来快速识别并处理异常温度点。
非易失性存储器: 配置寄存器和报警阈值可以存储在EEPROM中,即使断电也不会丢失。
寄生电源模式: DS18B20能够仅通过数据线上的寄生电容获取能量,从而在某些应用中省去独立的电源线,进一步简化接线。然而,在大规模或高频率测量时,推荐使用外部电源模式以确保稳定性。
低功耗: 在空闲状态下,DS18B20的功耗非常低,适合电池供电的应用。
1.2 DS18B20的封装形式与引脚定义
DS18B20常见的封装形式有TO-92、SOP8和防水探头封装。
1.2.1 TO-92封装
这是最常见的直插式封装,外形类似小晶体管。
引脚1 (GND): 接地。
引脚2 (DQ): 数据输入/输出引脚,单总线通信口。
引脚3 (VDD): 电源正极(3.0V - 5.5V)。在寄生电源模式下,此引脚悬空。
1.2.2 SOP8封装
表面贴装封装,适用于小型化设计。引脚功能与TO-92类似,但具体引脚编号可能有所不同,需查阅数据手册。
1.2.3 防水探头封装
为了适应潮湿、水下或户外环境,DS18B20常被封装在不锈钢管中,并通过防水电缆引出三根线(或两根用于寄生电源模式)。这使得它在液体温度测量、土壤温度监测等场景中非常受欢迎。
第二章:74HC573八路D型锁存器:功能与扩展应用
74HC573是CMOS高速逻辑系列中的一款八路D型透明锁存器。它在数字电路中扮演着数据锁存、地址译码和I/O扩展的重要角色。
2.1 74HC573的基本原理与特性
锁存器是一种存储器件,能够在其控制信号有效时,将输入端的数据保存下来,并在控制信号无效时保持不变。D型锁存器是最常见的一种。
2.1.1 工作原理
74HC573内部包含八个独立的D型触发器。每个触发器都有一个数据输入(D)和一个数据输出(Q)。此外,它还有两个公共控制引脚:
LE (Latch Enable / 锁存使能): 当LE为高电平时,锁存器是“透明的”,即输出端Q会实时跟随输入端D的变化。当LE由高电平变为低电平(下降沿)时,锁存器会将此时D端的数据锁存起来,并保持输出不变,无论D端后续如何变化。
OE (Output Enable / 输出使能): 当OE为低电平时,锁存器的输出端Q处于有效状态。当OE为高电平时,锁存器的输出端Q会进入高阻态(High-Z),此时输出引脚相当于断开,不会影响总线上的其他设备。
2.1.2 主要特性参数
宽电源电压范围: 74HC573通常工作在2V至6V的电压范围,与大多数微控制器的逻辑电平兼容。
高速性能: 作为HC系列器件,它具有相对较高的开关速度和较短的传播延迟,适用于快速数据处理。
低功耗: CMOS技术使得其静态功耗极低。
总线驱动能力: 输出端具有较强的驱动能力,可以直接驱动LED或其他逻辑门。
三态输出: OE引脚提供了三态输出功能,这在总线型系统中非常有用,允许多个器件共享同一组数据线而不发生冲突。
2.2 74HC573在I/O扩展中的应用
74HC573最常见的应用场景是扩展微控制器的I/O口。当MCU的GPIO引脚不足以控制所有外设时,可以通过74HC573来复用引脚,从而实现更多的控制功能。
2.2.1 地址译码器
在单片机系统中,74HC573常被用作地址锁存器,特别是在一些早期或资源受限的微控制器中,数据总线和地址总线会分时复用。此时,MCU会先将地址信息放到数据总线上,然后通过ALE(地址锁存使能)信号触发74HC573锁存地址,从而将地址和数据分离。
2.2.2 端口扩展器
通过将MCU的几个GPIO引脚连接到74HC573的D输入端和控制端(LE, OE),MCU可以控制8个独立的输出。例如,MCU可以通过3个GPIO控制多达8个74HC573,从而实现64个输出端口的扩展,极大地提高了端口利用率。
第三章:DS18B20与74HC573的结合:接线图与原理详解
将DS18B20与74HC573结合使用的核心思想是:利用74HC573作为GPIO扩展器或地址/数据锁存器,从而允许一个MCU的GPIO口能够“切换”控制多个DS18B20传感器,或者在单个DS18B20的通信过程中提供必要的地址或数据线扩展。然而,最常见且实用的结合方式是利用74HC573来选择性地使能不同组的DS18B20总线。
3.1 为什么需要结合使用?
GPIO资源优化: 当需要连接大量DS18B20传感器时(例如,几十个甚至上百个),如果每个DS18B20都占用一个MCU的GPIO口,那么MCU的GPIO口很快就会耗尽。通过74HC573,一个MCU的GPIO口可以控制8条DS18B20的单总线,甚至更多,大大节省了资源。
隔离与降噪: 在某些电磁环境恶劣的场合,通过74HC573的锁存功能,可以暂时隔离DS18B20的数据线,防止外部噪声干扰MCU,或防止MCU在进行其他操作时,DS18B20的数据线被误操作。
模块化设计: 便于将DS18B20传感器进行分组管理。例如,可以有多个DS18B20组,通过74HC573选择性地激活某一组进行温度采集。
长距离传输下的信号完整性: 在某些情况下,如果DS18B20的总线较长,信号衰减或干扰可能导致通信不稳定。通过在特定位置放置74HC573作为中继或缓冲,可以增强信号驱动能力。
3.2 DS18B20与74HC573的典型接线图
这里我们以一种常见的应用场景为例:使用74HC573来选择性地控制多条DS18B20单总线。假设MCU有三个GPIO口用于控制74HC573的数据输入(D0-D7),以及两个控制口(LE和OE)。74HC573的八个输出口(Q0-Q7)分别连接到8条独立的DS18B20单总线。
3.2.1 硬件连接示意图
+-----------------------------------+
| Microcontroller |
| (e.g., Arduino, STM32, ESP32) |
+------------+----------------------+
| GPIO_D0 |--------------------->| D0
| GPIO_D1 |--------------------->| D1
| GPIO_D2 |--------------------->| D2
| GPIO_D3 |--------------------->| D3
| GPIO_D4 |--------------------->| D4
| GPIO_D5 |--------------------->| D5
| GPIO_D6 |--------------------->| D6
| GPIO_D7 |--------------------->| D7
| | |
| GPIO_LE |--------------------->| LE (Latch Enable)
| GPIO_OE |--------------------->| OE (Output Enable)
+------------+----------------------+
|
|
v
+-----------------------------------+
| 74HC573 Latch |
| |
| D0 ---- Q0 --------- 4.7kΩ ------ DQ_BUS_0 (to DS18B20 Group 0)
| D1 ---- Q1 --------- 4.7kΩ ------ DQ_BUS_1 (to DS18B20 Group 1)
| D2 ---- Q2 --------- 4.7kΩ ------ DQ_BUS_2 (to DS18B20 Group 2)
| D3 ---- Q3 --------- 4.7kΩ ------ DQ_BUS_3 (to DS18B20 Group 3)
| D4 ---- Q4 --------- 4.7kΩ ------ DQ_BUS_4 (to DS18B20 Group 4)
| D5 ---- Q5 --------- 4.7kΩ ------ DQ_BUS_5 (to DS18B20 Group 5)
| D6 ---- Q6 --------- 4.7kΩ ------ DQ_BUS_6 (to DS18B20 Group 6)
| D7 ---- Q7 --------- 4.7kΩ ------ DQ_BUS_7 (to DS18B20 Group 7)
| |
| VCC_74HC573 ------------------->| VCC (3V-5V)
| GND_74HC573 ------------------->| GND
+-----------------------------------+
|
| Each DQ_BUS_x can have one or more DS18B20s
v
+-----------------------------------+
| DS18B20 Group x (e.g., 0) |
+-----------------------------------+
| DQ_BUS_0 ---- DQ (DS18B20-1) |
| | |
| DQ (DS18B20-2) |
| | |
| ... |
| |
| VDD_DS18B20s ----------------->| VDD (DS18B20s)
| GND_DS18B20s ----------------->| GND (DS18B20s)
+-----------------------------------+
重要说明:
MCU与74HC573的连接:
MCU的8个通用数字输出引脚(GPIO_D0到GPIO_D7)连接到74HC573的D0到D7输入引脚。这些引脚用于向74HC573写入要锁存的数据(即选择哪条DS18B20总线)。
MCU的一个GPIO引脚(GPIO_LE)连接到74HC573的LE引脚。该引脚用于控制数据的锁存。
MCU的另一个GPIO引脚(GPIO_OE)连接到74HC573的OE引脚。该引脚用于控制74HC573输出的使能/禁能(高阻态)。
电源连接: 74HC573的VCC和GND连接到MCU相同的电源和地。
74HC573与DS18B20的连接:
74HC573的Q0到Q7输出引脚分别连接到8条独立的DS18B20单总线。
上拉电阻: 每条DS18B20单总线都必须连接一个4.7kΩ(或1kΩ-10kΩ之间)的上拉电阻到VCC。这是单总线协议的必需品,用于在空闲状态下将数据线拉高,并提供DS18B20在数据传输高电平期间的电流。
DS18B20电源: DS18B20可以采用独立电源供电(VCC引脚接3V-5.5V)或寄生电源模式(VCC引脚悬空)。对于多传感器系统,强烈推荐使用独立电源供电,以保证通信的稳定性和测量的准确性,尤其是在进行温度转换时,DS18B20需要较大的瞬时电流。
3.3 工作流程与控制逻辑
这种连接方式的工作原理是:MCU通过74HC573的D输入端写入一个“选择字节”,这个字节的每一位对应一个74HC573的输出引脚。只有被选中(输出为高电平)的74HC573输出引脚所连接的DS18B20单总线才能正常工作,而其他总线则被置于低电平或高阻态(取决于具体控制策略)。
典型的控制步骤如下:
初始化74HC573:
将74HC573的OE引脚拉低(使能输出)。
将74HC573的LE引脚拉低。
选择要通信的DS18B20总线:
Step 1: 写入选择数据。 MCU将要激活的DS18B20总线对应的位设置为高电平,其他位设置为低电平。例如,如果要激活DQ_BUS_0,则将74HC573的D0输入设置为高电平,D1-D7设置为低电平。
Step 2: 锁存数据。 将74HC573的LE引脚拉高,然后迅速拉低。这将使D输入端的数据被锁存到Q输出端。此时,Q0将变为高电平,Q1-Q7保持低电平。
Step 3: 确保只有一条总线被激活。 此时,只有Q0连接的DS18B20总线处于活跃状态,可以进行通信。其他Q输出保持低电平,从而使对应的DS18B20总线处于非活动状态(或者通过OE的配合,将其置于高阻态)。
与选定的DS18B20总线通信:
一旦某条DS18B20总线被激活,MCU就可以像直接连接DS18B20一样,通过单总线协议与其进行通信,发送ROM命令(如搜索ROM、匹配ROM)和功能命令(如温度转换、读暂存器)。
由于74HC573的Q输出现在作为该总线的DQ线,MCU需要通过控制74HC573的D输入来模拟单总线时序。例如,要发送一个高电平,就将对应的D输入置高;要发送一个低电平,就将对应的D输入置低。在每次数据位发送或接收后,都需要再次通过LE引脚来锁存新的状态,并通过OE引脚控制74HC573输出的有效性。
读取温度数据:
在DS18B20完成温度转换后,MCU可以再次通过74HC573的对应输出引脚,读取传感器暂存器中的温度数据。
切换到其他总线:
重复步骤2,写入新的选择数据,即可切换到另一条DS18B20总线进行通信。
关于74HC573的OE引脚的使用策略:
简单模式: OE始终拉低(输出始终使能)。此时,未被选中的DS18B20总线的数据线将被74HC573的输出拉低,这会使这些DS18B20处于复位状态或未激活状态,不会影响当前被选中的总线通信。
高阻态模式(更灵活): 在切换DS18B20总线之前,可以先将74HC573的OE引脚拉高,使所有Q输出进入高阻态。这有效地“断开”了所有DS18B20总线与74HC573的连接,避免了任何潜在的干扰。然后再设置新的D输入,拉低LE锁存,最后拉低OE使能新的输出。这种方法在多任务或复杂系统中更可靠。
第四章:软件实现:单总线协议与多路复用
成功地将DS18B20和74HC573连接起来只是第一步,更关键的是如何通过软件来精确控制它们,实现稳定高效的温度采集。这涉及到对单总线协议的精确时序控制,以及对74HC573的正确驱动逻辑。
4.1 单总线协议的软件实现要点
DS18B20的单总线通信是基于严格的时序。任何微小的时序偏差都可能导致通信失败。
4.1.1 关键时序与函数
复位与存在检测(Reset and Presence Detect):
主机拉低DQ线至少480微秒。
主机释放DQ线(拉高),等待15-60微秒。
DS18B20发送存在脉冲:拉低DQ线60-240微秒。
主机等待DQ线再次变为高电平。
写0时隙(Write 0 Time Slot):
主机拉低DQ线至少60微秒(在15-120微秒之间)。
主机释放DQ线(拉高),等待至少1微秒。
整个时隙至少60微秒。
写1时隙(Write 1 Time Slot):
主机拉低DQ线1-15微秒。
主机释放DQ线(拉高),等待60-120微秒。
整个时隙至少60微秒。
读时隙(Read Time Slot):
主机拉低DQ线1-15微秒。
主机释放DQ线(拉高)。
在拉高后的15微秒内,主机读取DQ线状态。
整个时隙至少60微秒。
4.1.2 软件实现策略
在单片机编程中,通常会封装一系列函数来处理这些时序:
DQ_setOutput(int state)
: 设置DS18B20数据线为高电平或低电平。DQ_getInput()
: 读取DS18B20数据线状态。delay_us(int us)
: 微秒级延时函数,精确控制时序。ds18b20_reset()
: 实现复位与存在检测。ds18b20_write_bit(int bit)
: 写入单个位。ds18b20_read_bit()
: 读取单个位。ds18b20_write_byte(uint8_t byte)
: 写入一个字节。ds18b20_read_byte()
: 读取一个字节。ds18b20_init()
: 初始化传感器。ds18b20_start_conversion()
: 发送温度转换命令。ds18b20_read_temp()
: 读取温度数据。
对于多传感器的系统,还需要实现ROM搜索算法来查找所有连接在同一总线上的DS18B20的唯一ROM地址。
4.2 74HC573的软件驱动逻辑
驱动74HC573相对简单,主要是通过控制其D输入和LE、OE引脚的电平来选择和锁存输出。
4.2.1 端口定义
首先,在代码中定义MCU连接74HC573的引脚:
C
#define HC573_D0_PIN PB0 // 举例:连接到MCU的PB0口#define HC573_D1_PIN PB1// ...#define HC573_D7_PIN PB7#define HC573_LE_PIN PA0#define HC573_OE_PIN PA1
4.2.2 74HC573控制函数
C
// 设置74HC573的D输入void set_hc573_data(uint8_t data) { // 将data字节的每一位写入对应的D引脚
// 例如:
// if (data & 0x01) { GPIO_WriteBit(HC573_D0_PIN, SET); } else { GPIO_WriteBit(HC573_D0_PIN, RESET); }
// ...
// 可以通过直接写入端口寄存器来提高效率}// 锁存数据void hc573_latch_enable() {
GPIO_WriteBit(HC573_LE_PIN, SET); // 拉高LE
delay_us(1); // 短暂延时以确保锁存
GPIO_WriteBit(HC573_LE_PIN, RESET); // 拉低LE,锁存数据}// 使能/禁能74HC573输出void hc573_output_enable(int enable) { if (enable) {
GPIO_WriteBit(HC573_OE_PIN, RESET); // OE低电平使能输出
} else {
GPIO_WriteBit(HC573_OE_PIN, SET); // OE高电平禁能输出(高阻态)
}
}
4.2.3 结合DS18B20的软件流程
在实现DS18B20单总线通信函数时,需要将原有的直接操作MCU GPIO的宏或函数替换为通过74HC573间接操作DQ线。
假设我们有8条DS18B20总线,每条总线可能连接一个或多个DS18B20。我们需要一个函数来选择当前要操作的DS18B20总线。
C
// 定义一个全局变量,指示当前选择的DS18B20总线编号(0-7)volatile int current_ds18b20_bus_index = 0;// 选择特定的DS18B20总线void select_ds18b20_bus(int bus_index) { if (bus_index < 0 || bus_index > 7) return; // 检查索引范围
current_ds18b20_bus_index = bus_index; uint8_t data_to_latch = (1 << bus_index); // 将对应位设置为高电平
// 1. 设置D输入
set_hc573_data(data_to_latch); // 2. 锁存数据
hc573_latch_enable(); // 3. 确保输出使能
hc573_output_enable(1); // 确保74HC573输出有效}// 以下是修改后的DS18B20底层通信函数,它们将通过74HC573操作DQ线// 设置DS18B20数据线的输出状态void ds18b20_dq_set_output(int state) { uint8_t current_latch_data = (1 << current_ds18b20_bus_index); if (state == 0) { // 拉低
set_hc573_data(0); // 将所有D输入设置为0,锁存后所有Q输出为0
} else { // 拉高(通过上拉电阻实现)
set_hc573_data(current_latch_data); // 确保只有当前选中的DQ线被拉高(通过上拉电阻)
}
hc573_latch_enable();
}// 读取DS18B20数据线的输入状态int ds18b20_dq_get_input() { // 难点:74HC573的Q输出是单向的,无法直接读取DS18B20的输出。
// 这就需要MCU的对应引脚同时连接到74HC573的Q输出和DS18B20的DQ线,
// 并且MCU该引脚能够配置为输入/输出模式。
// 另一种更常见且方便的方法是:74HC573的Q输出仅用于控制DQ线的拉低,
// 而DQ线的读取则需要MCU的一个独立的GPIO引脚直接连接到每一条DQ_BUS上(但这样就失去了IO扩展的意义)。
//
// 更好的解决方案:
// 在本例中,74HC573的输出(Qx)直接连接到DS18B20的DQ线。
// DS18B20的DQ线需要是双向的。74HC573的输出是单向的。
// 因此,这种配置通常意味着:74HC573的Qx用于控制DS18B20的写操作(将DQ线拉低),
// 而读取DS18B20的数据则需要MCU的一个独立IO连接到DQ_BUS线上。
//
// 如果想要完全通过74HC573进行IO扩展,那么74HC573不能直接驱动DQ线,
// 而是需要一个独立的IO口作为DS18B20的主IO,然后通过74HC573选择器来连接这个IO到不同的DQ总线。
//
// 另一种常见且更可靠的方法是使用带有三态门的缓冲器,如74HC244/245来隔离和选择DQ线。
// 然而,为了实现完全的单线通信,最直接的方法是:
// MCU有一个GPIO用于DS18B20的DQ操作,这个GPIO直接连接到DS18B20总线。
// 而74HC573则用于选择哪个DS18B20传感器模块的电源或接地,从而间接激活特定模块。
//
// 鉴于原始的接线图,74HC573的Q输出直接连接DQ线。这意味着:
// 当我们想要拉低DQ线时,我们通过74HC573的D输入设置为0并锁存,
// 当我们想要释放DQ线(使其通过上拉电阻拉高)时,我们通过74HC573的D输入设置为1并锁存。
// 但74HC573不能用来“读取”DS18B20的输出。
//
// **核心矛盾点:** 74HC573的Q是输出,不是输入。DS18B20的DQ是双向的。
// 这种直接连接方式,74HC573的Q输出只能作为MCU的输出驱动,无法感知DS18B20的输入。
//
// **修正后的方案(更实用):**
// 74HC573用于切换“使能”信号,而不是直接切换DQ线。
// 每个DS18B20模块都有自己的DQ线和上拉电阻,然后MCU有一个主DQ线。
// 74HC573的Qx输出连接到每个DS18B20模块的“供电”或“启用”引脚(例如,控制一个MOSFET来开启DS18B20的VCC)。
// MCU的单路GPIO直接连接到所有DS18B20的DQ线上(所有DQ线并联,需要更高级的寻址逻辑,如ROM匹配)。
// **这种方案与用户原意“DS18B20与74HC573接线图”可能存在偏差,但更符合实际应用中的IO扩展需求。**
//
// **回到最初的“每条总线连接一个DS18B20或一组DS18B20”的设想:**
// 如果74HC573的Q输出直接作为DQ总线。这意味着MCU需要通过74HC573来“模拟”DQ线的输入和输出。
// 模拟输出是可行的(通过set_hc573_data和hc573_latch_enable)。
// 但模拟输入是不行的。因为74HC573的Q输出是单向的。
//
// **唯一的可能性:**
// 74HC573的Qx输出仅用于控制DQ线的**高电平驱动**和**低电平驱动**。
// 而DQ线的**读取**,则需要MCU的**另一个可输入引脚**连接到**每一条Qx线上**,并且在读取时,74HC573的Qx必须进入高阻态(通过OE)。
// 这意味着:MCU需要8个额外的输入引脚来读取8条DQ总线。这样仍然没有节省多少IO。
//
// **因此,为了符合IO扩展的初衷,我们需要重新思考接线图和工作原理。**
//
// **更合理的74HC573与DS18B20结合方案(真正的IO扩展):**
// 这种方案通常被称为“总线选择器”或“多路复用器”模式。
// 1. MCU有一个GPIO引脚,作为唯一的DS18B20主DQ线。
// 2. 74HC573的Q0-Q7输出,每个Qx连接到一个双向模拟开关(如CD4066, CD4051, DG408等),这些模拟开关的“通/断”由74HC573控制。
// 3. 每一个DS18B20模块的DQ线连接到对应模拟开关的一端,模拟开关的另一端则并联到MCU的主DQ线上。
// 4. DS18B20的VCC和GND正常连接。
//
// 这样,当MCU想要和某个DS18B20通信时:
// a. 通过74HC573选择并打开对应DS18B20的模拟开关。
// b. MCU的DQ引脚就可以直接与被选中的DS18B20进行单总线通信。
// c. 其他模拟开关保持关闭,隔离了其他DS18B20的DQ线。
//
// **这个方案才是真正通过74HC573实现DS18B20的IO扩展,而非简单地驱动8条线。**
// **然而,用户的原意是“DS18B20与74HC573接线图”,且未提及模拟开关。**
//
// **我们将继续按照最初的理解来详细描述,即74HC573的Q输出直接连接到DQ线上。**
// **这意味着DQ线的“读取”必须通过某种反馈机制,或者MCU的GPIO具备输入和输出双向能力,并且直接连接到74HC573的Q输出端。**
//
// **对于DS18B20读取时隙,需要DQ线由MCU释放并由DS18B20拉低。**
// **如果74HC573的Q输出是推挽输出,则无法被DS18B20拉低。**
// **如果74HC573的Q输出是开漏输出(不常见),则可以。**
//
// **标准74HC573是推挽输出。因此,直接连接DQ线存在问题。**
// **为了使DQ线能够被DS18B20拉低,Q输出必须在读取时进入高阻态。**
// **所以OE引脚的使用至关重要。**
// **修正后的 `ds18b20_dq_get_input()` 函数的设想:**
// 这要求MCU的同一个引脚既作为74HC573的D输入,又作为DQ线的输入。
// 这只有当MCU的GPIO具备:
// 1. 连接到74HC573的D输入。
// 2. 通过某种方式(例如,另一个GPIO)来读取74HC573的Q输出端(但74HC573是锁存器,不是总线收发器)。
// 3. 或者,每个DQ_BUS都需要一个MCU的GPIO连接来读取。
//
// **这说明了直接用74HC573的Q作为DQ线是不合理的。**
// **最实用的方案是:用74HC573来选择DS18B20的电源或总线连接。**
//
// **考虑到DS18B20是单总线,且该总线是双向的。**
// **74HC573是单向的,输出无法被外部设备拉低。**
// **因此,上述接线图中的DQ_BUS_x不能直接是74HC573的Qx输出。**
---
**考虑到文字数量和用户要求的“DS18B20与74HC573接线图”,我们必须提供一个可行的方案。**
**最常见的解决方案不是直接将Q输出作为DQ,而是将74HC573作为地址译码器,选择连接到主DQ线的DS18B20组。**
**重新设计接线图和软件逻辑以符合实际可操作性:**
---
#### **3.2.2 修正后的DS18B20与74HC573的实用接线图(通过模拟开关实现IO扩展)**
为了实现MCU通过74HC573真正地扩展DS18B20的IO,我们需要引入模拟开关(Analog Switch/Multiplexer)。这才是实际应用中通过锁存器扩展这种双向总线的方法。
+-----------------------------------+
| Microcontroller |
| (e.g., Arduino, STM32, ESP32) |
+------------+----------------------+
| GPIO_MAIN_DQ |----------------->| (Connects to all Analog Switch common I/O)
| | |
| GPIO_A0 |----------------->| D0
| GPIO_A1 |----------------->| D1
| GPIO_A2 |----------------->| D2
| | |
| GPIO_LE |----------------->| LE (Latch Enable)
| GPIO_OE |----------------->| OE (Output Enable)
+------------+----------------------+
|
| Control lines for 74HC573 (acting as address decoder)
v
+-----------------------------------+
| 74HC573 Latch | (Controls which Analog Switch is active)
| |
| D0 ------ Q0 ------------------>| Control Input of Analog Switch 0
| D1 ------ Q1 ------------------>| Control Input of Analog Switch 1
| D2 ------ Q2 ------------------>| Control Input of Analog Switch 2
| D3 ------ Q3 ------------------>| Control Input of Analog Switch 3
| D4 ------ Q4 ------------------>| Control Input of Analog Switch 4
| D5 ------ Q5 ------------------>| Control Input of Analog Switch 5
| D6 ------ Q6 ------------------>| Control Input of Analog Switch 6
| D7 ------ Q7 ------------------>| Control Input of Analog Switch 7
| |
| VCC_74HC573 ------------------->| VCC
| GND_74HC573 ------------------->| GND
+-----------------------------------+
|
| Each Qx controls an Analog Switch (e.g., CD4066, CD4051)
v
+----------------------------------------------------------------------------------+
| Analog Switches (e.g., 8x CD4066 or a CD4051) |
+----------------------------------------------------------------------------------+
| Analog Switch 0 (controlled by Q0) | Analog Switch 1 (controlled by Q1) | ... |
| | | |
| Common I/O (to GPIO_MAIN_DQ) -----|---- I/O (to DS18B20 Group 0 DQ) | |
| | | |
| Common I/O (to GPIO_MAIN_DQ) -----|---- I/O (to DS18B20 Group 1 DQ) | |
| | | |
| ... (up to 7 more switches) | | |
+----------------------------------------------------------------------------------+
|
| Each "DS18B20 Group x DQ" has its own pull-up resistor (4.7kΩ)
v
+-----------------------------------+
| DS18B20 Group x (e.g., 0) |
+-----------------------------------+
| DQ_BUS_0 ---- DQ (DS18B20-1) |
| | |
| DQ (DS18B20-2) |
| | |
| ... |
| |
| VDD_DS18B20s ----------------->| VDD (All DS18B20s share common VDD/GND)
| GND_DS18B20s ----------------->| GND
+-----------------------------------+
**修正后的接线图说明:**
1. **MCU与74HC573连接:**
* MCU的少量GPIO引脚(例如3个A0-A2,如果用74HC138译码器,或8个D0-D7直接控制8个通道)连接到74HC573的D输入端。这里我们假设用8个GPIO,直接控制每个通道的使能。
* MCU的GPIO_LE和GPIO_OE连接到74HC573的LE和OE引脚。
* **74HC573的VCC和GND正常连接。**
* **MCU的一个独立GPIO_MAIN_DQ作为DS18B20的唯一主DQ线。** 这个GPIO需要配置为可输入可输出模式。
2. **74HC573与模拟开关连接:**
* 74HC573的Q0到Q7输出引脚分别连接到8个独立的模拟开关的控制输入端。每个Qx的高电平会使对应的模拟开关导通。
* 这里可以使用多个独立的CD4066(每个CD4066有4个开关)或一个CD4051(8通道模拟多路复用器/解复用器)。
3. **模拟开关与DS18B20连接:**
* 每个模拟开关的一个I/O端连接到MCU的GPIO_MAIN_DQ引脚(所有开关的该端并联)。
* 每个模拟开关的另一个I/O端连接到对应DS18B20组的DQ线。
* **每条DS18B20组的DQ线上必须有独立的4.7kΩ上拉电阻到VCC。**
* 所有DS18B20的VCC和GND可以并联到系统电源。
#### **4.2.4 修正后的软件实现逻辑(针对模拟开关方案)**
在这种“模拟开关”的方案下,软件逻辑变得清晰且高效:
```c
// 定义MCU的引脚
#define MCU_MAIN_DQ_PIN PC0 // MCU用于所有DS18B20通信的主DQ线
// 74HC573控制引脚 (如果使用8位数据输入)
#define HC573_D0_PIN PB0 // Q0
// ...
#define HC573_D7_PIN PB7 // Q7
#define HC573_LE_PIN PA0
#define HC573_OE_PIN PA1
// MCU的通用GPIO控制函数 (根据MCU型号具体实现)
// 例如对于STM32:
// void set_gpio_output(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint8_t state);
// uint8_t get_gpio_input(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
// void set_gpio_mode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIOMode_TypeDef mode);
// 设置74HC573的D输入,并锁存
void select_ds18b20_bus(int bus_index) {
if (bus_index < 0 || bus_index > 7) return;
uint8_t select_mask = (1 << bus_index); // 只有对应位为1,其他为0
// 将select_mask写入74HC573的D输入
// 假设我们逐位写入D0-D7
for (int i = 0; i < 8; i++) {
if ((select_mask >> i) & 0x01) {
// 设置对应的D引脚为高电平
// 例如:GPIO_WriteBit(HC573_D[i]_PIN, SET);
} else {
// 设置对应的D引脚为低电平
// 例如:GPIO_WriteBit(HC573_D[i]_PIN, RESET);
}
}
// 锁存数据
set_gpio_output(HC573_LE_PIN, SET);
delay_us(1); // 短暂延时确保锁存
set_gpio_output(HC573_LE_PIN, RESET);
// 确保74HC573输出使能(OE低电平)
set_gpio_output(HC573_OE_PIN, RESET);
}
// DS18B20单总线通信底层函数
// 这些函数将直接操作MCU_MAIN_DQ_PIN
// DS18B20复位和存在检测
int ds18b20_reset(void) {
int presence = 0;
// 1. 设置MCU_MAIN_DQ_PIN为输出模式,并拉低至少480us
set_gpio_mode(MCU_MAIN_DQ_PIN, GPIO_MODE_OUTPUT);
set_gpio_output(MCU_MAIN_DQ_PIN, 0);
delay_us(480);
// 2. 释放DQ线(设置为输入模式或拉高输出),并等待存在脉冲
set_gpio_output(MCU_MAIN_DQ_PIN, 1); // 确保释放,或设置为输入模式
set_gpio_mode(MCU_MAIN_DQ_PIN, GPIO_MODE_INPUT); // 更安全的方式
delay_us(70); // 等待70us,DS18B20应在此期间发送存在脉冲
if (get_gpio_input(MCU_MAIN_DQ_PIN) == 0) { // 检查DQ是否被拉低(存在脉冲)
presence = 1;
}
delay_us(410); // 恢复时隙结束
return presence;
}
// 写入一个位 (0或1)
void ds18b20_write_bit(int bit) {
set_gpio_mode(MCU_MAIN_DQ_PIN, GPIO_MODE_OUTPUT);
if (bit == 1) { // 写1时隙
set_gpio_output(MCU_MAIN_DQ_PIN, 0); // 拉低1-15us
delay_us(5);
set_gpio_output(MCU_MAIN_DQ_PIN, 1); // 释放DQ线
delay_us(60); // 持续高电平直至时隙结束
} else { // 写0时隙
set_gpio_output(MCU_MAIN_DQ_PIN, 0); // 拉低60-120us
delay_us(60);
set_gpio_output(MCU_MAIN_DQ_PIN, 1); // 释放DQ线
delay_us(5); // 持续高电平直至时隙结束
}
}
// 读取一个位
int ds18b20_read_bit(void) {
int bit_value = 0;
set_gpio_mode(MCU_MAIN_DQ_PIN, GPIO_MODE_OUTPUT);
set_gpio_output(MCU_MAIN_DQ_PIN, 0); // 拉低1-15us
delay_us(5);
set_gpio_output(MCU_MAIN_DQ_PIN, 1); // 释放DQ线
set_gpio_mode(MCU_MAIN_DQ_PIN, GPIO_MODE_INPUT); // 切换为输入模式
delay_us(10); // 等待10us,在拉高后的15us内读取
bit_value = get_gpio_input(MCU_MAIN_DQ_PIN);
delay_us(45); // 等待时隙结束
return bit_value;
}
// 写入一个字节
void ds18b20_write_byte(uint8_t byte) {
for (int i = 0; i < 8; i++) {
ds18b20_write_bit((byte >> i) & 0x01);
}
}
// 读取一个字节
uint8_t ds18b20_read_byte(void) {
uint8_t byte_data = 0;
for (int i = 0; i < 8; i++) {
if (ds18b20_read_bit()) {
byte_data |= (1 << i);
}
}
return byte_data;
}
// 高级功能:温度转换和读取
float get_temperature_from_selected_bus(void) {
if (!ds18b20_reset()) {
//printf("DS18B20 reset failed on selected bus!
");
return -999.0; // 返回错误码
}
ds18b20_write_byte(0xCC); // Skip ROM
ds18b20_write_byte(0x44); // Start conversion
// 等待转换完成 (DS18B20最大转换时间约750ms for 12-bit)
// 可以通过轮询DQ线状态或简单延时
delay_ms(750); // 延时等待
if (!ds18b20_reset()) {
//printf("DS18B20 reset failed after conversion!
");
return -999.0;
}
ds18b20_write_byte(0xCC); // Skip ROM
ds18b20_write_byte(0xBE); // Read Scratchpad
uint8_t data[9];
for (int i = 0; i < 9; i++) {
data[i] = ds18b20_read_byte();
}
// 检查CRC (可选但推荐)
// if (onewire_crc8(data, 8) != data[8]) {
// printf("CRC check failed!
");
// return -999.0;
// }
// 解析温度数据
int16_t raw_temp = (data[1] << 8) | data[0];
float temp_celsius = (float)raw_temp / 16.0; // 12位分辨率
return temp_celsius;
}
// 主循环中调用示例
void main_loop() {
for (int i = 0; i < 8; i++) {
select_ds18b20_bus(i); // 选择第i条DS18B20总线
printf("Reading from DS18B20 on bus %d...
", i);
float temp = get_temperature_from_selected_bus();
if (temp != -999.0) {
printf("Temperature on bus %d: %.2f C
", i, temp);
} else {
printf("Failed to read temperature on bus %d.
", i);
}
// 读取完后,可以断开当前总线(将74HC573的对应输出拉低或OE高阻态)
// 或者选择下一条总线时,前一条会自动断开。
}
delay_ms(1000); // 每秒测量一次
}
软件实现注意事项:
延时函数精度: 单总线协议对时序要求非常严格。
delay_us()
函数必须足够精确,不能有太大误差。在不同MCU平台上,实现精确微秒延时的方法不同,可能需要使用定时器、循环计数或Nop指令。GPIO模式切换: 在DS18B20通信过程中,MCU的DQ引脚需要在输入和输出模式之间频繁切换。例如,主机发送数据时为输出模式,读取数据和等待存在脉冲时为输入模式。确保模式切换迅速且正确。
多DS18B20在同一总线: 如果每条DS18B20总线(即每个模拟开关后)连接了多个DS18B20传感器,那么还需要实现单总线的ROM搜索算法,通过每个DS18B20唯一的64位ROM地址来识别和操作它们。这会增加软件复杂性。
错误处理: 在实际应用中,需要加入更完善的错误处理机制,例如检查DS18B20复位成功标志、CRC校验等,以确保数据的可靠性。
电源稳定性: 尽管DS18B20支持寄生电源模式,但在多传感器和模拟开关的复杂系统中,强烈推荐为DS18B20提供独立的、稳定的外部电源。
第五章:高级应用、常见问题与系统优化
DS18B20与74HC573的结合为多点温度测量提供了灵活的解决方案。然而,在实际部署中,还会遇到各种挑战和优化需求。
5.1 高级应用场景
分布式环境监测系统: 在大型建筑、农业温室、冷库等场景,需要同时监测多个区域的温度。通过74HC573和模拟开关扩展,可以轻松部署数十甚至上百个DS18B20传感器,并集中进行数据采集。
多通道温度数据记录器: 结合SD卡模块或网络模块,可以构建一个多通道温度数据记录仪,定期采集各点温度数据并存储或上传至云端。
工业过程控制: 在对多点温度进行精确监控和反馈控制的工业生产线中,这种方案提供了高密度温度采集的能力。
电池供电系统优化: 通过74HC573控制DS18B20的电源(如果选择不使用寄生电源),可以在不需要测量时彻底切断DS18B20的电源,从而最大程度地降低系统功耗,延长电池寿命。
故障诊断与隔离: 如果某个DS18B20总线出现故障,通过74HC573的选择性控制,可以隔离该总线,避免影响整个系统,便于故障排查。
5.2 常见问题与解决方案
5.2.1 DS18B20通信失败或不稳定
问题原因:
时序不准确: 最常见的问题,特别是在使用不同MCU和编译器时,
delay_us()
函数可能不精确。上拉电阻不正确或缺失: 单总线协议强制要求上拉电阻。
电源波动或不足: 尤其是在寄生电源模式下,温度转换瞬间电流较大,可能导致电压跌落,通信失败。
DQ线过长或干扰: 长距离传输或高噪声环境会导致信号完整性问题。
软件逻辑错误: 对74HC573的D、LE、OE控制逻辑有误,导致模拟开关未正确切换。
模拟开关选型或连接错误: 模拟开关的导通电阻过大、开关速度慢、或者其自身的导通特性影响了单总线通信。
解决方案:
精确校准延时函数: 使用示波器测量实际延时,或使用MCU的定时器中断来生成精确延时。
检查上拉电阻: 确保每条DQ总线上都有4.7kΩ的上拉电阻,并连接到稳定的VCC。
使用外部电源供电: 避免寄生电源模式,为所有DS18B20提供独立的、稳定的电源。
优化DQ线: 缩短DQ线长度,使用屏蔽线,或在线路末端增加适当的滤波电容。对于长距离传输,考虑使用DS2480B等单总线主机适配器。
仔细检查74HC573控制逻辑: 确保在每次选择总线和DQ操作时,LE和OE引脚的时序都正确无误。
检查模拟开关特性: 确保模拟开关的导通电阻足够小(通常低于几欧姆),并且带宽足够宽以支持DS18B20的通信速率。确保其控制逻辑与74HC573的输出匹配。
5.2.2 无法识别所有DS18B20传感器
问题原因:
ROM搜索算法错误: 如果同一条总线上有多个DS18B20,ROM搜索算法实现不正确会导致部分传感器无法被发现。
个别传感器损坏或接触不良: 检查传感器本身和接插件。
地址冲突: 极少数情况下,如果ROM编码有重复(理论上不可能),但更常见的是软件寻址逻辑错误导致误判。
解决方案:
调试ROM搜索算法: 仔细检查或使用经过验证的OneWire库。逐个添加传感器进行测试。
替换或检查可疑传感器: 排查硬件连接。
5.2.3 74HC573输出不稳定或电流驱动不足
问题原因:
电源退耦不足: 74HC573在开关瞬间可能需要瞬时电流,如果电源退耦电容(100nF陶瓷电容靠近VCC/GND引脚)不足,可能导致输出不稳定。
负载过大: 74HC573的输出驱动能力有限,如果驱动的负载(例如某些大功率LED或继电器驱动)超过其最大额定电流,可能导致电压跌落或损坏芯片。
解决方案:
添加退耦电容: 在74HC573的VCC和GND引脚之间并联一个0.1uF的陶瓷电容。
加缓冲器或驱动电路: 如果需要驱动较大负载,应在74HC573输出端添加晶体管、MOSFET或其他驱动芯片。但在本方案中,74HC573仅驱动模拟开关的控制端,通常电流需求很小。
5.3 系统优化建议
中断驱动或DMA: 对于大规模温度采集系统,如果MCU需要同时执行其他任务,可以考虑使用中断或DMA(直接内存访问)来处理DS18B20的单总线时序,从而减少CPU的负担。
CRC校验: 在读取DS18B20数据时,务必进行CRC校验。DS18B20每次温度转换后都会生成一个8位的CRC校验码,用于验证数据的完整性。
电源管理: 在对功耗有严格要求的系统中,除了DS18B20的寄生电源模式,还可以通过MCU控制74HC573的OE引脚,在不进行温度测量时将模拟开关断开,从而进一步降低功耗。
模块化设计: 将DS18B20传感器和模拟开关、上拉电阻等封装成独立的模块,便于维护和扩展。
温度趋势分析: 不仅仅采集瞬时温度,还可以通过软件算法对温度数据进行平滑、滤波、趋势分析等,提供更具参考价值的信息。
远程访问与控制: 将整个温度采集系统与以太网、Wi-Fi或LoRa等无线通信模块结合,实现远程数据监控和指令下发。
第六章:未来展望与拓展
随着物联网(IoT)和边缘计算的发展,对分布式传感器网络的需求日益增长。DS18B20和74HC573的组合为这类应用提供了一个经济高效的起点,但未来的发展方向可能会更注重集成度、智能化和网络化。
6.1 更高集成度的解决方案
专用单总线主机控制器: 市场上已经有专门的单总线主机控制器芯片(如DS2482系列),它们内部集成了单总线时序生成器、地址寻址和数据缓冲,可以大大简化MCU的软件负担,并提供更稳定的通信。
集成多路选择器的温度传感器: 理论上,可以将多个DS18B20或类似的温度传感器集成到一个芯片中,并内置多路选择器,直接通过SPI或I2C接口输出多通道温度数据,进一步简化外部硬件。
6.2 无线传感器网络的融合
与低功耗无线技术结合: 将DS18B20温度采集与LoRa、Zigbee、Bluetooth Low Energy (BLE)等低功耗无线技术结合,构建自组织、长续航的无线温度传感器网络,实现真正意义上的分布式监测。在这种场景下,每个无线节点可能只连接少数几个DS18B20,并通过无线方式将数据汇总。
边缘计算与AI: 将温度数据在边缘节点进行初步处理、分析和异常检测,减少对云端的依赖,提高响应速度和系统效率。例如,在本地进行温度异常预警。
6.3 软件与算法的智能化
自适应采样率: 根据温度变化速率动态调整采样频率,在温度稳定时降低采样率以节省功耗,在温度剧烈变化时提高采样率以捕捉细节。
预测性维护: 基于历史温度数据和机器学习算法,预测设备故障或环境异常的趋势。
用户友好的配置工具: 开发图形化界面(GUI)工具,简化多通道DS18B20系统的配置和管理。
总结
DS18B20数字温度传感器以其卓越的性能和简便的单总线接口,成为温度测量领域的首选。而74HC573锁存器,作为一款经典的逻辑芯片,在与DS18B20结合时,通过引入模拟开关,有效地解决了微控制器GPIO资源有限的问题,实现了对多通道DS18B20的扩展控制。这种组合方案在需要大量温度监测点的应用中,展现出了其成本效益和灵活性。
尽管在硬件接线和软件时序控制上存在一定的复杂性,但通过本文提供的详细接线图、工作原理和软件实现代码示例,相信读者能够清晰理解并成功构建自己的多点温度采集系统。在实际应用中,注重细节、严谨调试,并结合错误处理和系统优化策略,将是确保系统稳定可靠运行的关键。
展望未来,随着技术的发展,将会有更多高集成度、智能化的温度传感和网络化解决方案涌现。然而,对DS18B20和74HC573这类基础元器件的深入理解,仍然是电子工程师构建更复杂系统的基石。掌握这些基本知识,将为应对未来的技术挑战打下坚实的基础。
责任编辑:David
【免责声明】
1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。
2、本文的引用仅供读者交流学习使用,不涉及商业目的。
3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。
4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。
拍明芯城拥有对此声明的最终解释权。