引言
在嵌入式系統中,通信總線是連接 CPU 與外設的橋梁。從 I2C、SPI 到 UART,每種總線都有其獨特的應用場景。而本文要介紹的1-Wire 一線式總線,以其極簡的硬件設計和獨特的通信協議,在溫度采集、身份識別等領域大放異彩。本文將從原理入手,結合 STM32 與 DS18B20 溫度傳感器的實戰案例,帶您深入理解一線式總線的奧秘。
一、一線式總線的核心原理
1. 定義與特性
一線式串行總線,顧名思義,只需一根數據線即可實現 CPU 與外設的通信(需上拉電阻,默認高電平)。與 I2C、SPI 等多線總線不同,它的特點是:
-
單數據線:數據傳輸與時鐘同步都依賴這根線。
-
串行通信:一位一位地傳輸數據,而非并行。
-
總線結構:支持多個從設備掛接在同一數據線上(需通過 ROM 尋址)。
2. 時鐘機制:無時鐘線如何同步?
一線式總線沒有獨立的時鐘信號線,它通過嚴格的時序控制實現數據同步:
-
主設備(MCU) 通過精確控制數據線的高低電平持續時間,定義時鐘周期。
-
從設備(如 DS18B20)根據主設備的時序要求,在特定時間窗口內采樣或發送數據。
這種設計雖然增加了軟件實現的復雜度,但極大簡化了硬件連接。
二、DS18B20 溫度傳感器實戰:硬件設計
1. 硬件連接
以 STM32F103 與 DS18B20 為例,硬件連接如下:
-
數據線(DQ):連接 STM32 的 PG11 引腳(需 4.7KΩ 上拉電阻)。
-
電源(VDD):接 3.3V 或 5V(支持寄生電源模式,本文使用外部供電)。
-
地(GND):共地。
2. GPIO 初始化代碼
// 定義DS18B20連接引腳 #define DS18B20_PORT ? GPIOG #define DS18B20_PIN ? ? GPIO_Pin_11 #define DS18B20_IO_OUT DS18B20_PORT->ODR #define DS18B20_IO_IN ? DS18B20_PORT->IDR ? void DS18B20_Init(void) {// 1. 打開GPIOG時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);// 2. 配置PG11為推挽輸出,50MHzGPIO_InitTypeDef GPIO_Config;GPIO_Config.GPIO_Pin ? = DS18B20_PIN;GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Config.GPIO_Mode ?= GPIO_Mode_Out_PP;GPIO_Init(DS18B20_PORT, &GPIO_Config); }
三、一線式總線通信協議詳解
1. 通信三部曲
由廠家提供的芯片手冊可知要想獲取溫度值,訪問 DS18B20 需遵循固定順序:
-
初始化復位:類似 I2C 的 START 信號,檢測設備是否在線。
-
發送 ROM 命令:識別總線上的特定設備(如讀取唯一 ID 或跳過 ID 直接訪問)。
-
發送功能命令:執行具體操作(如溫度轉換、讀取寄存器)。
2. 底層時序實現
(1)初始化復位信號
// 初始化復位 void DS18B20_Reset(void) {u8 tempTime = 0;// 1. 拉低總線 >=480usDS18B20_OUT();DS18B20_IO_OUT = 0;delay_us(500);// 2. 釋放總線(拉高)15~60usDS18B20_IO_OUT = 1;delay_us(30);// 3. 等待DS18B20應答(拉低60~240us)DS18B20_IN();while (DS18B20_IO_IN && tempTime < 240) {tempTime++;delay_us(1);}if (tempTime >= 240) {printf("DS18B20 Reset Failed\n");} else {printf("DS18B20 Reset Success\n");tempTime = 0;}// 4. 總線恢復高電平delay_us(200); }
(2)數據讀寫操作
// 發送單字節 void DS18B20_Write_Byte(u8 data) {u8 i;DS18B20_OUT();for (i = 0; i < 8; i++) {if (data & 0x01) { ?// 寫1// 拉低 >1usDS18B20_IO_OUT = 0;delay_us(2);// 拉高 >45usDS18B20_IO_OUT = 1;delay_us(60);} else { ?// 寫0// 拉低60~120usDS18B20_IO_OUT = 0;delay_us(60);// 拉高 >1usDS18B20_IO_OUT = 1;delay_us(2);}data >>= 1;} } ? // 讀取單字節 u8 DS18B20_Read_Byte(void) {u8 i, data = 0;for (i = 0; i < 8; i++) {// 1. 拉低 >1usDS18B20_OUT();DS18B20_IO_OUT = 0;delay_us(2);// 2. 釋放總線,準備讀取DS18B20_IN();delay_us(8); ?// 等待DS18B20輸出數據// 3. 讀取數據data |= DS18B20_IO_IN << i;delay_us(50); ?// 完成讀時隙}return data; }
四、DS18B20 溫度采集實戰
1. ROM 命令與功能命令
DS18B20 支持多種 ROM 命令,常見的有:
-
SKIP ROM(0xCC):跳過 ROM 匹配,適用于單設備場景。
-
MATCH ROM(0x55):匹配特定設備的 64 位 ROM ID,適用于多設備場景。
功能命令則包括:
-
CONVERT T(0x44):啟動溫度轉換。
-
READ SCRATCHPAD(0xBE):讀取溫度寄存器數據。
2. 溫度采集代碼實現
(1)單設備場景(SKIP ROM)
// 獲取溫度值(單設備) float DS18B20_GetTemperature(void) {u8 temp_lsb, temp_msb;u16 temp;float value;// 1. 初始化 -> SKIP ROM -> 啟動溫度轉換DS18B20_Reset();DS18B20_Write_Byte(0xCC); ?// SKIP ROMDS18B20_Write_Byte(0x44); ?// CONVERT Tdelay_ms(800); ?// 等待轉換完成(最大750ms)// 2. 初始化 -> SKIP ROM -> 讀取溫度寄存器DS18B20_Reset();DS18B20_Write_Byte(0xCC); ?// SKIP ROMDS18B20_Write_Byte(0xBE); ?// READ SCRATCHPAD// 3. 讀取溫度數據(低8位和高8位)temp_lsb = DS18B20_Read_Byte();temp_msb = DS18B20_Read_Byte();temp = (temp_msb << 8) | temp_lsb;// 4. 溫度值轉換(分辨率默認為12位)if ((temp & 0xF800) == 0xF800) { ?// 負數temp = (~temp) + 1;value = temp * (-0.0625);} else { ?// 正數value = temp * 0.0625;}return value; }
(2)多設備場景(MATCH ROM)
u8 rom[8]; ?// 存儲DS18B20的64位ROM ID ? // 讀取ROM值 void DS18B20_ReadRom(void) {u8 i;DS18B20_Reset();DS18B20_Write_Byte(0x33); ?// READ ROMfor (i = 0; i < 8; i++) {rom[i] = DS18B20_Read_Byte();printf("%02X ", rom[i]);}printf("\n"); } ? // 匹配指定ROM的設備 void DS18B20_MatchRom(void) {u8 i;DS18B20_Reset();DS18B20_Write_Byte(0x55); ?// MATCH ROMfor (i = 0; i < 8; i++) {DS18B20_Write_Byte(rom[i]);} } ? // 獲取指定設備的溫度(多設備場景) float DS18B20_GetTemperature(void) {// 與單設備類似,但將SKIP ROM替換為MATCH ROM// ... }
五、常見問題與優化建議
1. 通信穩定性問題
-
上拉電阻:務必使用 4.7KΩ 上拉電阻,確保總線在空閑時為高電平。
-
延時精度:一線式總線對時序要求極高,建議使用精確的微秒級延時函數。
-
線路長度:數據線過長會導致信號衰減,建議控制在 2 米以內(或增加驅動電路)。
2. 多設備尋址技巧
-
ROM 搜索算法:通過
SEARCH ROM(0xF0)
命令遍歷總線上所有設備的 ROM ID。 -
寄生電源模式:DS18B20 可通過數據線獲取電源,但可能影響穩定性,建議優先使用外部供電。
3. 代碼優化方向
-
超時處理:在關鍵通信環節添加超時檢測,避免程序卡死。
-
CRC 校驗:DS18B20 的 ROM 和數據寄存器包含 CRC 校驗值,可提高數據可靠性。
六、總結
一線式總線以其極簡的硬件設計和獨特的通信機制,為嵌入式系統提供了一種低成本、易擴展的解決方案。通過本文的實戰案例,我們掌握了 DS18B20 溫度傳感器的基本原理和編程方法,理解了一線式總線的通信協議與實現技巧。
在實際應用中,一線式總線不僅適用于溫度采集,還可用于濕度、壓力等多種傳感器的連接。掌握這一技術,將為您的嵌入式開發工具箱增添一件有力武器!