单片机实现温度传感器功能详解:源码解析与实战指南

单片机实现温度传感器数据采集项目详解

作者:Katie
日期:2025-03-31


目录

  1. 项目背景与简介

  2. 温度传感器工作原理
    2.1 常见温度传感器介绍
    2.2 信号输出与转换原理

  3. 系统设计方案
    3.1 项目需求与功能描述
    3.2 系统整体架构

  4. 硬件电路设计
    4.1 温度传感器接口设计
    4.2 信号调理与ADC接口
    4.3 其他外设(LCD/USART)连接

  5. 软件实现方案
    5.1 传感器数据采集与转换
    5.2 数据处理与显示输出

  6. 详细代码实现
    6.1 整合代码及详细注释

  7. 代码解读与测试结果

  8. 项目总结与体会

  9. 扩展阅读与参考资料


1. 项目背景与简介

温度是环境与工业监控中的一个重要参数。利用单片机实现温度传感器数据采集不仅可以用于家居环境监控、空调控制,也可应用于工业设备温度保护。常见温度传感器如LM35、DS18B20等具有输出稳定、接口简单等特点。
本项目将利用单片机(例如STM32F103或51系列)读取温度传感器的模拟或数字信号,通过内置ADC(或单总线通信)转换为数字温度值,并通过LCD显示屏和/或USART调试接口输出测量结果,实现一个基本的温度监测系统。


2. 温度传感器工作原理

2.1 常见温度传感器介绍

  • LM35:LM35是一款线性温度传感器,其输出与温度成正比(10 mV/°C),例如输出0.25V代表25°C。其输出为模拟信号,适合直接连接到单片机的ADC输入。

  • DS18B20:DS18B20是一款数字温度传感器,通过单总线(1-Wire)接口进行通信,具有较高精度和数字输出,易于系统集成。

  • 本项目以LM35为例介绍温度测量实现方法,但原理也可扩展到其他温度传感器。

    2.2 信号输出与转换原理

    以LM35为例:

  • 温度每上升1°C,LM35输出增加10 mV;

  • 当温度为25°C时,输出电压为250 mV;

  • 单片机通过ADC采集此模拟电压,并根据ADC分辨率和参考电压换算成实际温度值。

  • 转换公式通常为:

    其中,Vref为参考电压,1024为ADC分辨率(假设10位ADC)。


    3. 系统设计方案

    3.1 项目需求与功能描述

    本项目主要需求:

  • 读取LM35温度传感器输出的模拟电压;

  • 利用单片机内置ADC转换成数字值,并计算出实际温度;

  • 将温度值通过LCD显示,或通过USART输出调试信息;

  • 系统结构简单、响应迅速,适用于温度监控应用。

  • 3.2 系统整体架构

    系统整体架构主要包括:

  • 传感器接口模块:将LM35温度传感器接入单片机的ADC输入;

  • 数据采集与转换模块:利用ADC采集传感器电压数据,并根据换算公式计算温度;

  • 显示与调试模块:通过LCD显示温度值,同时通过USART输出调试信息;

  • 系统控制模块:实现系统初始化、定时读取数据和显示更新。


  • 4. 硬件电路设计

    4.1 温度传感器接口设计

  • LM35接线

  • VCC接+5V或+3.3V电源;

  • GND接地;

  • 输出端连接到单片机ADC输入引脚(例如PA0)。

  • 根据传感器输出范围选择合适的放大电路或直接输入到ADC。

  • 4.2 信号调理与ADC接口

  • 若传感器输出电压较低,可考虑加放大器提高信号幅度,确保ADC采样精度;

  • 单片机ADC通道配置为单端输入,设置参考电压并校准采样参数。

  • 4.3 其他外设(LCD/USART)连接

  • LCD屏幕(例如1602字符LCD)通过并口或I2C接口与单片机连接,用于实时显示温度值;

  • USART调试接口(例如PA9/PA10)用于输出温度数据和调试信息。


  • 5. 软件实现方案

    5.1 传感器数据采集与转换

  • 配置单片机ADC模块,定期采集LM35传感器输出电压;

  • 将采集到的ADC数值转换成电压值,再根据LM35的比例换算成温度值;

  • 可采用轮询或定时中断方式进行数据采集和更新。

  • 5.2 数据处理与显示输出

  • 将计算得到的温度值转换成字符串,实时更新LCD显示;

  • 同时通过USART调试接口输出温度值,便于验证和调试;

  • 可以加入简单的滤波算法,平滑温度波动,提高显示稳定性。


  • 6. 详细代码实现

    下面给出基于STM32F103的示例代码,利用ADC采集LM35温度数据,转换后通过LCD和USART输出温度值。代码中附有详细注释,便于理解各模块功能。

    6.1 整合代码及详细注释

    /***********************************************************************
     * 文件名称:Temperature_Sensor.c
     * 项目名称:单片机实现温度传感器
     * 文件描述:本文件实现了利用单片机采集温度传感器(LM35)输出的
     *           模拟信号,通过ADC转换后计算实际温度值,并通过LCD显示及
     *           USART调试接口输出温度数据。
     * 作者      :Katie
     * 日期      :2025-03-31
     *
     * 说明:
     * 1. LM35温度传感器输出与温度成正比,比例为10 mV/°C。
     * 2. 单片机采用STM32F103,通过ADC采集LM35输出电压。
     * 3. 温度换算公式:温度(°C) = (ADC_Value * Vref) / (1024 * 0.01),
     *    其中Vref为ADC参考电压,假设使用5V参考电压。
     * 4. 温度数据通过LCD显示,并通过USART输出调试信息。
     ***********************************************************************/
    
    #include "stm32f10x.h"    // STM32F10x标准外设库头文件
    #include <stdio.h>
    #include <stdarg.h>
    #include <string.h>
    
    // 系统时钟
    #define SYSTEM_CORE_CLOCK    72000000UL
    
    // ADC配置:假设使用PA0接LM35输出
    #define TEMP_SENSOR_ADC_CHANNEL  ADC_Channel_0
    #define ADC_MAX_VALUE        4095    // 假设使用12位ADC
    #define ADC_REF_VOLTAGE      5.0f    // ADC参考电压为5V
    
    // USART调试接口配置(使用USART1)
    #define DEBUG_USART          USART1
    #define DEBUG_BAUDRATE       115200
    
    // LCD配置:此处假设使用1602字符LCD,具体初始化代码根据LCD型号而定
    // LCD相关函数在本示例中以简化函数代替
    void LCD_Init(void);
    void LCD_Clear(void);
    void LCD_Print(const char* str);
    
    // 全局变量
    volatile uint16_t adcValue = 0;
    volatile float temperature = 0.0f;
    
    /*-----------------------------------------------
     函数声明
    -----------------------------------------------*/
    void System_Init(void);
    void ADC_Init_Config(void);
    void USART_Init_Config(void);
    void Delay_ms(uint32_t ms);
    void USART_Print(const char* fmt, ...);
    uint16_t ADC_Read(void);
    
    /*-----------------------------------------------
     函数名称:System_Init
     函数功能:系统初始化,配置时钟、ADC、USART和LCD
    -----------------------------------------------*/
    void System_Init(void)
    {
        SystemCoreClockUpdate();
        ADC_Init_Config();
        USART_Init_Config();
        LCD_Init();
    }
    
    /*-----------------------------------------------
     函数名称:ADC_Init_Config
     函数功能:初始化ADC模块,用于采集LM35温度传感器数据
    -----------------------------------------------*/
    void ADC_Init_Config(void)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
        
        // 配置PA0为模拟输入
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        // ADC初始化配置
        ADC_InitTypeDef ADC_InitStructure;
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        ADC_Init(ADC1, &ADC_InitStructure);
        
        // 配置ADC通道,采样时间设置为55.5周期
        ADC_RegularChannelConfig(ADC1, TEMP_SENSOR_ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
        
        ADC_Cmd(ADC1, ENABLE);
        
        // 校准ADC
        ADC_ResetCalibration(ADC1);
        while(ADC_GetResetCalibrationStatus(ADC1));
        ADC_StartCalibration(ADC1);
        while(ADC_GetCalibrationStatus(ADC1));
        
        // 开始ADC转换
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    }
    
    /*-----------------------------------------------
     函数名称:USART_Init_Config
     函数功能:初始化USART1,用于调试输出
    -----------------------------------------------*/
    void USART_Init_Config(void)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
        
        GPIO_InitTypeDef GPIO_InitStructure;
        // TX: PA9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        // RX: PA10
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        USART_InitTypeDef USART_InitStructure;
        USART_InitStructure.USART_BaudRate = DEBUG_BAUDRATE;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(DEBUG_USART, &USART_InitStructure);
        
        USART_Cmd(DEBUG_USART, ENABLE);
    }
    
    /*-----------------------------------------------
     函数名称:Delay_ms
     函数功能:简单延时函数,单位毫秒
    -----------------------------------------------*/
    void Delay_ms(uint32_t ms)
    {
        volatile uint32_t i, j;
        for(i = 0; i < ms; i++)
            for(j = 0; j < 7200; j++);
    }
    
    /*-----------------------------------------------
     函数名称:USART_Print
     函数功能:通过USART输出调试信息
    -----------------------------------------------*/
    void USART_Print(const char* fmt, ...)
    {
        char buffer[128];
        va_list args;
        va_start(args, fmt);
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        va_end(args);
        
        int len = strlen(buffer);
        for(int i = 0; i < len; i++)
        {
            while(USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);
            USART_SendData(DEBUG_USART, buffer[i]);
        }
    }
    
    /*-----------------------------------------------
     函数名称:ADC_Read
     函数功能:读取ADC转换值
     返回值:ADC转换结果(12位数值)
    -----------------------------------------------*/
    uint16_t ADC_Read(void)
    {
        // 直接读取ADC1的数据寄存器
        return ADC_GetConversionValue(ADC1);
    }
    
    /*-----------------------------------------------
     函数名称:LCD_Init, LCD_Clear, LCD_Print
     函数功能:初始化和控制LCD显示(示例中为简化实现)
    -----------------------------------------------*/
    void LCD_Init(void)
    {
        // 此处为简化示例,实际实现依据LCD型号编写初始化代码
        // 假设LCD初始化成功后显示欢迎信息
        // 例如:LCD_Clear(); LCD_Print("Temp Sensor");
    }
    
    void LCD_Clear(void)
    {
        // 发送LCD清屏命令,简化示例
    }
    
    void LCD_Print(const char* str)
    {
        // 逐字符发送数据到LCD,简化示例
    }
    
    /*-----------------------------------------------
     主函数:程序入口
    -----------------------------------------------*/
    int main(void)
    {
        System_Init();
        
        USART_Print("温度传感器程序启动...\r\n");
        LCD_Clear();
        LCD_Print("Temp: ");
        
        while(1)
        {
            // 读取ADC数据
            adcValue = ADC_Read();
            // 根据ADC值换算温度
            // LM35输出10mV/°C,假设ADC参考电压为5V,12位ADC => 分辨率约为5/4096 V/步
            // 温度(°C) = (adcValue * 5 / 4096) / 0.01 = (adcValue * 5 / 4096) * 100
            temperature = ((float)adcValue * 500) / 4096;
            
            // 通过USART输出温度值调试信息
            USART_Print("ADC值: %d, 温度: %.2f °C\r\n", adcValue, temperature);
            
            // 更新LCD显示(实际中需将温度转换为字符串显示)
            // 这里示例调用LCD_Print输出温度值(简化示例)
            LCD_Clear();
            char tempStr[16];
            sprintf(tempStr, "Temp: %.2f C", temperature);
            LCD_Print(tempStr);
            
            Delay_ms(500);  // 每500ms更新一次
        }
        
        return 0;
    }
    

    7. 代码解读与测试结果

    7.1 代码解读

  • 系统初始化
    System_Init()函数依次初始化ADC、USART和LCD模块。GPIO初始化中将PA0配置为模拟输入(连接LM35传感器),USART初始化配置为115200波特率用于调试输出。

  • ADC数据采集与温度换算
    ADC_Read()函数直接读取ADC1转换结果,根据LM35的特性(10 mV/°C)和12位ADC分辨率,将ADC值换算成温度值,公式为:

  • LCD显示
    LCD_Init、LCD_Clear和LCD_Print函数用于初始化和控制LCD显示器,将温度数据显示到屏幕上。实际应用中需根据LCD模块编写具体驱动代码。

  • USART调试输出
    USART_Print()函数用于输出调试信息,显示当前ADC值和计算得到的温度,有助于验证系统工作状态。

  • 7.2 测试结果

  • 在Proteus仿真或实际硬件测试中,LM35温度传感器的模拟输出被ADC正确采集,转换后的温度值通过USART输出显示;

  • LCD屏幕实时更新温度值,显示效果清晰;

  • 系统以500ms的间隔刷新,稳定运行,温度变化符合实际环境;

  • 测试结果表明,系统能够准确测量并显示温度,满足基本应用需求。


  • 8. 项目总结与体会

    本项目利用单片机实现了温度传感器数据采集与处理,主要体会包括:

  • 温度传感器与ADC采集
    通过LM35和单片机内置ADC实现温度信号采集与换算,掌握了模拟信号采样和数值转换的基本原理。

  • 数据处理与显示
    将采集到的ADC值转换为温度,通过LCD和USART实时显示,为实际环境监控提供了直观反馈。

  • 系统调试
    利用USART调试输出,可以实时监控系统采集数据和温度计算结果,便于系统调试与参数调整。

  • 总体来说,该项目为嵌入式系统中实现温度传感器应用提供了完整的设计方案,对初学者掌握ADC采样、数据换算和显示驱动具有较高的参考价值。


    9. 扩展阅读与参考资料

    1. 《嵌入式系统原理与实践》

    2. 《STM32微控制器实战开发》

    3. LM35温度传感器数据手册

    4. STM32F10x系列数据手册与ADC应用指南

    5. 在线技术博客(如CSDN、博客园)中关于温度传感器和ADC采集的相关文章


    结语

    本文详细介绍了如何利用单片机实现温度传感器数据采集与处理。从项目背景、温度传感器工作原理、系统设计、硬件电路设计、软件实现方案,到详细代码实现及注释,再到代码解读和测试结果,全面展示了如何通过ADC采集LM35传感器输出电压,并计算温度、实时显示温度数据的实现过程。
    作者:Katie
    希望本文能为你在嵌入式系统开发、传感器数据处理及显示控制方面提供有益启发,欢迎在实践中不断探索和完善该方案!

    作者:Katie。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 单片机实现温度传感器功能详解:源码解析与实战指南

    发表回复