单片机:实现温度传感器(附带源码)

一、设计思路

  1. 选择传感器

    • LM35 是一种常用的模拟温度传感器,它的输出电压是线性变化的。对于每增加 1°C,输出电压增加 10 mV,适合通过 ADC 读取其输出并计算温度。
  2. 硬件连接

    • LM35 的输出引脚需要接到 STM32 的 ADC 输入引脚(如 PA0)。通过 ADC,STM32 可以读取该引脚的电压,并计算温度值。
    • LM35 的电源引脚需要连接到 5V,地线连接到 GND。
  3. 系统流程

    • 配置 STM32 的 ADC 模块来读取 LM35 的输出电压。
    • 根据读取的 ADC 值,利用公式计算出温度值。
    • 显示温度(通过串口输出,或通过 LCD 显示等)。
  4. 注意事项

    • LM35 的输出电压与温度成正比,因此需要使用 STM32 的 ADC 功能来获取模拟信号。
    • 由于 STM32 的 ADC 输出是数字值,需要进行适当的计算和转换,最终得出温度。

二、硬件连接

  1. LM35 引脚

    • VCC:连接到 5V 电源。
    • GND:连接到地。
    • Vout:输出模拟信号,连接到 STM32 的 ADC 输入引脚(如 PA0)。
  2. STM32 配置

    • PA0 连接到 LM35 的输出端,作为 ADC 输入。
    • 需要使用 STM32 的 ADC 模块读取 PA0 的电压。

三、实现步骤

  1. ADC 配置

    • 配置 STM32 的 ADC 模块读取模拟输入(PA0 引脚)。
    • 配置 ADC 的分辨率(通常 12 位),并启动 ADC 转换。
  2. 读取 ADC 数据

    • 在 ADC 转换完成后,读取 ADC 的结果。
    • 将 ADC 结果转换为实际的电压值。
  3. 温度计算

    • LM35 输出电压与温度成正比。每升高 1°C,输出电压增加 10 mV。通过计算公式:
    • 需要根据 STM32 ADC 的分辨率将 ADC 数据转换为电压,然后用上述公式计算温度。

四、代码实现

以下是一个简化的示例代码,展示如何读取 LM35 温度传感器的输出并计算温度值。

#include "stm32f10x.h"
#include <stdio.h>

// 温度传感器计算公式
#define VREF 3.3f    // 假设 STM32 的参考电压为 3.3V
#define ADC_RESOLUTION 4096  // 12 位 ADC 分辨率

// ADC 初始化函数
void ADC1_Init(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置 PA0 为模拟输入
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // ADC 配置
    ADC_InitTypeDef ADC_InitStruct;
    ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStruct.ADC_ScanConvMode = DISABLE;
    ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStruct.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStruct);
    
    // 配置 ADC1 的通道 0 (PA0)
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
    
    // 启动 ADC
    ADC_Cmd(ADC1, ENABLE);
    
    // 校准 ADC
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));
}

// 读取 ADC 值并计算温度
float Read_Temperature(void) {
    // 启动 ADC 转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    
    // 等待转换完成
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    
    // 获取 ADC 转换结果
    uint16_t adc_value = ADC_GetConversionValue(ADC1);
    
    // 将 ADC 值转换为电压 (假设参考电压为 3.3V,12 位 ADC)
    float voltage = (adc_value / (float)ADC_RESOLUTION) * VREF;
    
    // 计算温度 (每增加 1°C,输出电压增加 10 mV)
    float temperature = voltage * 100.0f;  // 温度 = 电压 (V) * 100 (因为 1°C 对应 10mV)
    
    return temperature;
}

int main(void) {
    // 系统初始化
    SystemInit();
    
    // 初始化 ADC
    ADC1_Init();
    
    // 主循环
    while (1) {
        // 读取温度
        float temperature = Read_Temperature();
        
        // 打印温度值(可以使用串口或其他显示方式)
        printf("Temperature: %.2f°C\n", temperature);
        
        // 延时 (避免输出过于频繁)
        for (int i = 0; i < 1000000; i++);
    }
}

五、代码解读

  1. ADC1_Init 函数

    • 该函数初始化 ADC1 模块,配置 PA0 为模拟输入,并设置 ADC 模式。
    • 使用 ADC_Init 配置 ADC 的基本参数,如工作模式、转换触发方式等。
    • 配置 ADC 的采样时间和通道,使其读取 PA0 引脚的电压。
  2. Read_Temperature 函数

    • 启动 ADC 转换并等待转换完成。
    • 从 ADC 获取转换结果(12 位数据),并将其转换为实际电压。
    • 使用公式 温度 = 电压 * 100 将电压转换为温度。因为 LM35 的输出电压每增加 1°C 增加 10 mV,因此乘以 100 即为最终温度值。
  3. 主程序

    • 在主程序中,我们通过 Read_Temperature 获取温度,并通过 printf 打印温度值。打印过程可以通过串口、LCD 或其他显示设备输出。

六、总结

  • 硬件设计:我们使用了 LM35 温度传感器并通过 STM32 的 ADC 模块读取其输出电压。通过 ADC 获取的值可以转换为实际的温度。
  • 关键点:ADC 的配置与读取、温度计算的公式以及如何处理 ADC 输出。
  • 应用场景:该设计可以应用于温度监控系统、环境检测、智能家居等嵌入式项目中。
  • 扩展性:这个基本框架可以根据需求进一步扩展,比如使用数字温度传感器(如 DS18B20),或者将温度数据传输到远程服务器进行处理等。
#include #define uchar unsigned char #define uint unsigned int sbit led=P2^5; sbit wei=P2^7; sbit duan=P2^6; sbit DQ=P2^2; uchar mazhi_duan[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,0x00}; uchar mazhi_wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xff}; void delayl(uint n) { uint i,j; for(i=n;i>0;i--) for(j=114;j>0;j--); } void delays(uchar i) { while(i--); } bit init_DS18B20() //DS8B20初始化 { bit x; DQ=1; //DQ复位 delays(8); DQ=0; //单片机将DQ拉低 delays(75); DQ=1; //拉高总线 delays(15); x=DQ; //延时过后 若x=0则初始化成功 若x=1则初始化失败 delays(5); return x; } void write_data(uchar dat) { uchar i,temp; temp=dat; DQ=1; for(i=0;i>=1; } } uchar read_data() { uchar i,dat; DQ=1; for(i=0;i>=1; DQ=1;//配置为输入 if(DQ) dat|=0x80; delays(4); } return dat; } uint readtemp() { uchar temph,templ; uint temp; float wendu; init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0x44);//启动温度转换 //delayl(100); init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0xBE);//读温度 //以下读温度,低八位在前 //高8位在后 templ=read_data(); temph=read_data(); temp = (temph<<8)|templ; wendu = temp*0.625+0.5;//温度扩大10倍,四舍五入 temp = wendu;//10倍温度 return temp; } void STC_init() { P1=0x00;//关闭led led=0; //锁存 wei=0; duan=0; } void display(uchar weil,uchar duanl,bit dp) { wei=1; P0=mazhi_wei[weil-1]; wei=0; duan=1; if(dp==1) P0=(mazhi_duan[duanl]|0x80); else P0=mazhi_duan[duanl]; duan=0; } void main() { uchar i; uint wendu; STC_init(); wendu=readtemp(); delayl(500); wendu=readtemp(); delayl(500); while(1) { wendu=readtemp(); for(i=0;i<80;i++) { display(1,wendu/100,0); delayl(3); display(2,wendu0/10,1); delayl(3); display(3,wendu,0); delayl(3); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值