【STM32嵌入式系统设计与开发】——17STM32Temper(ADC内部温度传感器应用)

发布于:2024-04-16 ⋅ 阅读:(25) ⋅ 点赞:(0)


STM32资料包:
百度网盘下载链接:链接:https://pan.baidu.com/s/1mWx9Asaipk-2z9HY17wYXQ?pwd=8888
提取码:8888

一、任务描述

在这里插入图片描述

二、任务实施

观察电路图:
TXD(底板) ————————> PA10
RXD(底板) ————————> PA9
读取内部温度传感器的值需要通过ADC进行模拟信号转换,并根据芯片的参考温度值进行转换为实际温度

在这里插入图片描述

1、工程文件夹创建

步骤1:复制工程模板“1_Template”重命名为“14_ADC”。
在这里插入图片描述

步骤2:修改项目工程名,先删除projects文件夹内除了Template.uvprojx文件外的所有内容并修改为“ADC.uvprojx”。并删除output/obj和output/lst中的所有文件。
在这里插入图片描述
步骤3:运行“PassiveBeep.uvprojx”打开目标选项“Options for Target”中的“Output”输出文件,并修改可执行文件名称为“ADC”点击“OK”保存设置。最后点击“Rebuild”编译该工程生成Usart文件。
在这里插入图片描述

步骤4:复制2_LEDTest中的"1_LED"和文件复制到hardware中。
在这里插入图片描述

步骤5:在system文件夹中新建一个adc文件夹并在该文件夹下新建adc.c和adc.h两个文件。
在这里插入图片描述
步骤6:工程组文件中添加“1_LED”和“2_ADCKEY”文件夹内的所有文件。
在这里插入图片描述
步骤7:工程组文件中添加“adc”文件夹内的所有文件。
在这里插入图片描述
步骤6:目标选项添加添加头文件路径。
在这里插入图片描述

2、函数编辑

(1)主函数编辑

基于STM32的检测定时器超时状态并翻转LED的状态,同时检测AD按键状态并输出按下的按键编号到串口。
在这里插入图片描述

步骤2:循环函数编写

	while(1)
	{	 								
		if(WaitTimerOut(3))
		{
			/*得到温度值*/
			temp=Get_Temprate();
			temp2 = temp*0.01;                             //缩小100倍
			
			/* 判断温度是否小于0 */
			if(temp<0)  
            printf("STM32 Temper: -%2.2f \r\n",temp2);    //负温度				
			else
				printf("STM32 Temper: %2.2f \r\n",temp2); //正温度

		}
	}	

在这里插入图片描述

(2)ADC初始化函数(T_Adc_Init())

步骤1:初始化ADC

/*********************************************************************
 @Function  : 初始化ADC
 @Parameter : N/A
 @Return    : N/A
**********************************************************************/
void T_Adc_Init(void) 
{
    ADC_InitTypeDef ADC_InitStructure; 
    // 定义 ADC_InitTypeDef 结构体变量,用于配置 ADC 参数

    /* 时钟使能 */	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);// 使能 GPIOA 和 ADC1 的时钟	   
    
    /* ADC 时钟配置 */	
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                          // 将 ADC 时钟设置为 APB2 时钟的 1/6,即 72MHz / 6 = 12MHz
    
    ADC_DeInit(ADC1);                                                          // 将 ADC1 寄存器恢复默认值,相当于复位 ADC1
    
    /* ADC 配置 */	
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	                       // 设置 ADC 工作模式为独立模式,即单个 ADC 工作
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;	                           // 禁用扫描模式,使用单通道模式
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	                       // 禁用连续转换模式,使用单次转换模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	       // 转换由软件启动,不使用外部触发
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	                   // ADC 数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;	                                   // 使用的 ADC 通道数目为 1
    ADC_Init(ADC1, &ADC_InitStructure);	                                       // 根据上述配置初始化 ADC1
	
    /* 开启内部温度传感器 */	
    ADC_TempSensorVrefintCmd(ENABLE);                                          // 开启 ADC 内部温度传感器

    /* 使能 ADC */	
    ADC_Cmd(ADC1, ENABLE);	                                                   // 使能 ADC1

    /* 复位 ADC */	
    ADC_ResetCalibration(ADC1);	                                               // 复位 ADC1 的校准寄存器
    while(ADC_GetResetCalibrationStatus(ADC1));	                               // 等待校准寄存器复位完成
    ADC_StartCalibration(ADC1);	                                               // 开始 ADC1 的校准
    while(ADC_GetCalibrationStatus(ADC1));	                                   // 等待校准完成
}

在这里插入图片描述

(3)获得通道值函数(T_Get_Adc())

/*********************************************************************
 @Function  : 获得某个通道值 
 @Parameter : ch :通道号
 @Return    : 对应通道的ADC值
**********************************************************************/
uint16_t T_Get_Adc(uint8_t ch)   
{ 
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1通道3,第一个转换,采样时间为239.5周期	  			     
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		                        //使能ADC1软件转换启动功能
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));                     //等待转换结束
	return ADC_GetConversionValue(ADC1);	                            //返回最近一次ADC1规则组的转换结果
}

在这里插入图片描述

(4)获得ADC的平均值函数(T_Get_Adc_Average())

/*********************************************************************
 @Function  : 得到ADC采样内部温度传感器的值
 @Parameter : N/A
 @Return    : 取10次的平均温度值
**********************************************************************/
uint16_t T_Get_Temp(void)
{
    uint16_t temp_val = 0;                        // 初始化变量 temp_val,用于存储采样值的累加结果
    uint8_t t;                                    // 循环计数器

    for (t = 0; t < 10; t++)
    {
        temp_val += T_Get_Adc(ADC_Channel_16);	  // 获取内部温度传感器采样值并累加到 temp_val 中
        delay_ms(5);                              // 延时 5 毫秒,确保 ADC 转换完成
    }

    return temp_val / 10;                         // 返回 10 次采样的平均值
}

在这里插入图片描述

(4)获得ADC的平均值函数(T_Get_Adc_Average())

/*********************************************************************
 @Function  : 获取通道 ch 的转换值
 @Parameter : ch :通道号
              times :获取 ADC 通道值的次数
 @Return    : 取 times 次的平均值
**********************************************************************/
uint16_t T_Get_Adc_Average(uint8_t ch, uint8_t times)
{
    u32 temp_val = 0;                // 定义用于累加 ADC 值的变量,类型为无符号32位整数
    uint8_t t;                       // 循环计数器

    for (t = 0; t < times; t++)
    {
        temp_val += T_Get_Adc(ch);   // 调用 T_Get_Adc 函数获取通道 ch 的 ADC 值,并累加到 temp_val 中
        delay_ms(5);                 // 延时 5 毫秒,等待 ADC 转换完成
    }

    return temp_val / times;         // 返回累加值的平均值,即取 times 次采样的平均值
}

在这里插入图片描述

(5)ADC按键初始化函数(Get_Temperature())

/*********************************************************************
 @Function  : 得到温度值
 @Parameter : N/A
 @Return    : 温度值(扩大了100倍,单位:℃)
**********************************************************************/
short Get_Temperature(void)	
{
    u32 adcx;           // 定义用于存储 ADC 平均值的变量
    short result;       // 定义最终温度值的变量
    double temperature; // 定义温度变量,类型为双精度浮点数

	  /* 读取通道 16,进行 20 次采样取平均值 */
    adcx = T_Get_Adc_Average(ADC_Channel_16, 20); 

    /* 计算电压值(假设 ADC 参考电压为 3.3V,分辨率为 12 位,即 4096 个刻度 */
    temperature = (float)adcx * (3.3 / 4096);

    /* 根据传感器特性将电压值转换为温度值(假设转换公式为温度 = (1.43V - 电压值) / 0.0043 + 25℃)*/
    temperature = (1.43 - temperature) / 0.0043 + 25;

	  /* 将温度值扩大 100 倍,并转换为整数类型 */
    result = temperature * 100; 

    return result;     // 返回扩大了 100 倍的温度值
}

在这里插入图片描述

3、头文件添加

步骤1:adc所需头文件添加

#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_adc.h"
#include ".\adc\adc.h"
#include ".\delay\delay.h"

步骤2:添加STM32Temper源文件所需的头文件

#include "stm32f10x_adc.h"
#include ".\adc\adc.h"
#include "STM32Temper.h"

步骤3:函数声明

  short temp=0;
  float temp2; 
	delay_init();                   //启动滴答定时器
    usart1_init(9600);              //USART1初始化
	SystemTinerInit(1000-1,3600-1); //系统时间初始化 定时100ms
	LED_Init();                     //板载LED初始化
	T_Adc_Init();		  		    //ADC初始化	

4、头文件编辑

//bord.h
#ifndef __BORD_H_
#define __BORD_H_
#include "system_config.h"

//头文件包含
/*************SYSTEM*****************/
/*#include ".\sys\sys.h"*/
#include ".\delay\delay.h"
#include ".\usart\usart.h"
#include ".\timer\timer.h"
#include ".\adc\adc.h"

/***********Hardweare***************/
#include "led.h"
#include "STM32Temper.h"
 

/***********Funlibrary***************/





#endif


步骤2:主函数添加函数的声明

//adc.h
#ifndef __ADC_H
#define __ADC_H
#include <stdint.h>

/* 函数声明 */
void T_Adc_Init(void); 
uint16_t  T_Get_Adc(uint8_t ch); 
uint16_t  T_Get_Adc_Average(uint8_t ch,uint8_t times);	 

#endif


!

步骤2:添加STM32Temper的头文件

//STM32Temper.h
#ifndef __STM32TEMPER_H
#define __STM32TEMPER_H
#include "stdint.h"

short Get_Temperature(void)	;

#endif

4、知识链接

(1)内部温度工作原理

STM32内部温度传感器在芯片内部与ADCx_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值,继而换算成温度值。因此,我们只需设置一下内部ADC,并激活其内部通道就可以了。

(2)编写步骤

1、配置ADC
2、获取某个通道值
3、内部温度传感器的值计算

5、工程测试

在这里插入图片描述