STM32与Proteus环境下DS18B20温度传感器与数码管仿真实验指南

1. 实验准备

  • 硬件方面
  • 了解 STM32 单片机的基本原理和使用方法,本实验可选用常见的 STM32F103 系列。
  • 熟悉 DS18B20 温度传感器的工作原理和通信协议(单总线协议)。
  • 数码管可选用共阴极或共阳极数码管,用于显示温度值。
  • 软件方面
  • 安装 Keil MDK 开发环境,用于编写和编译 STM32 的程序代码。
  • 安装 Proteus 仿真软件,用于搭建电路并进行仿真。
  • 2. Proteus 电路搭建

    1. 打开 Proteus 软件:新建一个工程,在元件库中搜索并添加以下元件:
    2. STM32F103R6:作为主控芯片。
    3. DS18B20:温度传感器。
    4. 7SEG-MPX4-CC:4 位共阴极数码管。
    5. 电阻、电容等辅助元件。
    6. 连接电路
    7. DS18B20 连接:将 DS18B20 的 VDD 引脚连接到 3.3V 电源,GND 引脚接地,DQ 引脚连接到 STM32 的一个 GPIO 引脚(例如 PA0)。
    8. 数码管连接:将数码管的段选引脚(a – g、dp)连接到 STM32 的一组 GPIO 引脚(例如 PB0 – PB7),位选引脚(COM1 – COM4)连接到另一组 GPIO 引脚(例如 PC0 – PC3)。
    9. 电源和地:将 STM32 的 VDD 和 VSS 引脚分别连接到 3.3V 电源和地。

    3. Keil MDK 代码编写

    以下是一个

    #include "stm32f10x.h"
    #include <stdio.h>
    
    // 定义 DS18B20 引脚
    #define DS18B20_PORT GPIOA
    #define DS18B20_PIN GPIO_Pin_0
    
    // 定义数码管段选和位选端口
    #define SEG_PORT GPIOB
    #define DIG_PORT GPIOC
    
    // 共阴极数码管段码表
    const u8 SEG_CODE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
    
    // 延时函数
    void Delay(__IO uint32_t nCount) {
        for (; nCount != 0; nCount--);
    }
    
    // DS18B20 初始化
    u8 DS18B20_Init(void) {
        u8 presence = 0;
        GPIO_InitTypeDef GPIO_InitStructure;
    
        // 配置 DS18B20 引脚为推挽输出
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
    
        // 拉低总线 480 - 960us
        GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN);
        Delay(500);
    
        // 释放总线
        GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
        Delay(60);
    
        // 配置为浮空输入
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
    
        // 检测存在脉冲
        if (!GPIO_ReadInputDataBit(DS18B20_PORT, DS18B20_PIN)) {
            presence = 1;
        }
        Delay(480);
    
        return presence;
    }
    
    // 向 DS18B20 写一个字节
    void DS18B20_WriteByte(u8 dat) {
        u8 i;
        GPIO_InitTypeDef GPIO_InitStructure;
    
        // 配置为推挽输出
        GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
    
        for (i = 0; i < 8; i++) {
            GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN);
            Delay(2);
            if (dat & 0x01) {
                GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
            } else {
                GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN);
            }
            Delay(60);
            GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
            dat >>= 1;
        }
    }
    
    // 从 DS18B20 读一个字节
    u8 DS18B20_ReadByte(void) {
        u8 i, dat = 0;
        GPIO_InitTypeDef GPIO_InitStructure;
    
        for (i = 0; i < 8; i++) {
            // 配置为推挽输出
            GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
    
            GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN);
            Delay(2);
            GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
    
            // 配置为浮空输入
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
            GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
    
            if (GPIO_ReadInputDataBit(DS18B20_PORT, DS18B20_PIN)) {
                dat |= (0x01 << i);
            }
            Delay(60);
        }
        return dat;
    }
    
    // 读取 DS18B20 温度值
    float DS18B20_ReadTemp(void) {
        u8 LSB, MSB;
        short temp;
        float temperature;
    
        if (DS18B20_Init()) {
            DS18B20_WriteByte(0xCC); // 跳过 ROM 操作
            DS18B20_WriteByte(0x44); // 启动温度转换
            Delay(750000); // 等待转换完成
    
            DS18B20_Init();
            DS18B20_WriteByte(0xCC); // 跳过 ROM 操作
            DS18B20_WriteByte(0xBE); // 读取温度寄存器
    
            LSB = DS18B20_ReadByte();
            MSB = DS18B20_ReadByte();
    
            temp = (MSB << 8) | LSB;
            temperature = (float)temp / 16.0;
        } else {
            temperature = -1;
        }
        return temperature;
    }
    
    // 数码管显示函数
    void DisplayTemp(float temp) {
        u8 digit[4];
        u16 temp_int = (u16)(temp * 10);
    
        digit[0] = temp_int / 1000;
        digit[1] = (temp_int % 1000) / 100;
        digit[2] = (temp_int % 100) / 10;
        digit[3] = temp_int % 10;
    
        // 位选和段选
        for (int i = 0; i < 4; i++) {
            GPIO_ResetBits(DIG_PORT, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
            GPIO_SetBits(DIG_PORT, GPIO_Pin_0 << i);
            GPIO_Write(SEG_PORT, SEG_CODE[digit[i]]);
            Delay(1000);
        }
    }
    
    int main(void) {
        float temperature;
        GPIO_InitTypeDef GPIO_InitStructure;
    
        // 使能 GPIOB 和 GPIOC 时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
    
        // 配置数码管段选引脚为推挽输出
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(SEG_PORT, &GPIO_InitStructure);
    
        // 配置数码管位选引脚为推挽输出
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
        GPIO_Init(DIG_PORT, &GPIO_InitStructure);
    
        while (1) {
            temperature = DS18B20_ReadTemp();
            DisplayTemp(temperature);
        }
    }

    简单的示例代码,用于读取 DS18B20 的温度数据并显示在数码管上:

    4. 代码编译

    4. 代码编译和仿真

    编译代码:在 Keil MDK 中,将上述代码保存为 .c 文件,进行编译,确保代码没有错误。

    1. 生成 hex 文件:在 Keil MDK 的项目选项中,配置生成 .hex 文件。
    2. 加载 hex 文件:在 Proteus 中,双击 STM32 芯片,在弹出的对话框中选择生成的 .hex 文件。
    3. 开始仿真:点击 Proteus 中的运行按钮,开始仿真。此时,数码管应该会显示 DS18B20 读取到的温度值。

    5. 注意事项

  • 延时函数:在实际应用中,需要根据具体的系统时钟频率调整延时函数的参数,以确保 DS18B20 的通信正常。
  • 数码管驱动:数码管的驱动方式可以根据实际情况进行调整,例如使用动态扫描或静态显示。
  • 错误处理:在代码中添加适当的错误处理机制,以提高系统的稳定性。
  • 作者:年*D-清仁

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32与Proteus环境下DS18B20温度传感器与数码管仿真实验指南

    发表回复