1-Wire 一线式总线:从原理到实战,玩转 DS18B20 温度采集

06-01 1068阅读

引言

在嵌入式系统中,通信总线是连接 CPU 与外设的桥梁。从 I2C、SPI 到 UART,每种总线都有其独特的应用场景。而本文要介绍的1-Wire 一线式总线,以其极简的硬件设计和独特的通信协议,在温度采集、身份识别等领域大放异彩。本文将从原理入手,结合 STM32 与 DS18B20 温度传感器的实战案例,带您深入理解一线式总线的奥秘。

一、一线式总线的核心原理

1. 定义与特性

一线式串行总线,顾名思义,只需一根数据线即可实现 CPU 与外设的通信(需上拉电阻,默认高电平)。与 I2C、SPI 等多线总线不同,它的特点是:

  • 单数据线:数据传输与时钟同步都依赖这根线。

  • 串行通信:一位一位地传输数据,而非并行。

  • 总线结构:支持多个从设备挂接在同一数据线上(需通过 ROM 寻址)。

    2. 时钟机制:无时钟线如何同步?

    一线式总线没有独立的时钟信号线,它通过严格的时序控制实现数据同步:

    • 主设备(MCU) 通过精确控制数据线的高低电平持续时间,定义时钟周期。

    • 从设备(如 DS18B20)根据主设备的时序要求,在特定时间窗口内采样或发送数据。

      这种设计虽然增加了软件实现的复杂度,但极大简化了硬件连接。

      1-Wire 一线式总线:从原理到实战,玩转 DS18B20 温度采集

      二、DS18B20 温度传感器实战:硬件设计

      1. 硬件连接

      以 STM32F103 与 DS18B20 为例,硬件连接如下:

      • 数据线(DQ):连接 STM32 的 PG11 引脚(需 4.7KΩ 上拉电阻)。

      • 电源(VDD):接 3.3V 或 5V(支持寄生电源模式,本文使用外部供电)。

      • 地(GND):共地。

        1-Wire 一线式总线:从原理到实战,玩转 DS18B20 温度采集

        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为推挽输出,50MHz
            GPIO_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 需遵循固定顺序:

        1-Wire 一线式总线:从原理到实战,玩转 DS18B20 温度采集

        1. 初始化复位:类似 I2C 的 START 信号,检测设备是否在线。

        2. 发送 ROM 命令:识别总线上的特定设备(如读取唯一 ID 或跳过 ID 直接访问)。

        3. 发送功能命令:执行具体操作(如温度转换、读取寄存器)。

        2. 底层时序实现

        (1)初始化复位信号

        1-Wire 一线式总线:从原理到实战,玩转 DS18B20 温度采集

        // 初始化复位
        void DS18B20_Reset(void) {
            u8 tempTime = 0;
            
            // 1. 拉低总线 >=480us
            DS18B20_OUT();
            DS18B20_IO_OUT = 0;
            delay_us(500);
            
            // 2. 释放总线(拉高)15~60us
            DS18B20_IO_OUT = 1;
            delay_us(30);
            
            // 3. 等待DS18B20应答(拉低60~240us)
            DS18B20_IN();
            while (DS18B20_IO_IN && tempTime = 240) {
                printf("DS18B20 Reset Failed\n");
            } else {
                printf("DS18B20 Reset Success\n");
                tempTime = 0;
            }
            
            // 4. 总线恢复高电平
            delay_us(200);
        }
        (2)数据读写操作

        1-Wire 一线式总线:从原理到实战,玩转 DS18B20 温度采集

        // 发送单字节
        void DS18B20_Write_Byte(u8 data) {
            u8 i;
            DS18B20_OUT();
            
            for (i = 0; i 1us
                    DS18B20_IO_OUT = 0;
                    delay_us(2);
                    // 拉高 >45us
                    DS18B20_IO_OUT = 1;
                    delay_us(60);
                } else {  // 写0
                    // 拉低60~120us
                    DS18B20_IO_OUT = 0;
                    delay_us(60);
                    // 拉高 >1us
                    DS18B20_IO_OUT = 1;
                    delay_us(2);
                }
                data >>= 1;
            }
        }
        ​
        // 读取单字节
        u8 DS18B20_Read_Byte(void) {
            u8 i, data = 0;
            
            for (i = 0; i 1us
                DS18B20_OUT();
                DS18B20_IO_OUT = 0;
                delay_us(2);
                
                // 2. 释放总线,准备读取
                DS18B20_IN();
                delay_us(8);  // 等待DS18B20输出数据
                
                // 3. 读取数据
                data |= DS18B20_IO_IN  SKIP ROM -> 启动温度转换
            DS18B20_Reset();
            DS18B20_Write_Byte(0xCC);  // SKIP ROM
            DS18B20_Write_Byte(0x44);  // CONVERT T
            delay_ms(800);  // 等待转换完成(最大750ms)
            
            // 2. 初始化 -> SKIP ROM -> 读取温度寄存器
            DS18B20_Reset();
            DS18B20_Write_Byte(0xCC);  // SKIP ROM
            DS18B20_Write_Byte(0xBE);  // READ SCRATCHPAD
            
            // 3. 读取温度数据(低8位和高8位)
            temp_lsb = DS18B20_Read_Byte();
            temp_msb = DS18B20_Read_Byte();
            temp = (temp_msb 
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码