STM32内部温度传感器实验指南

STM32内部是有温度传感器的,以F1为例,它的温度采集范围是-40度到125度,精度为正负2度,采样通道为ADC1_INI6,上电控制位为TSVREFE位。

温度计算方式为:T(摄氏度) = (V25 – Vsense) / Avg_Slope + 25,其中V25为25摄氏度时的Vsense数值,一般取1.43;Avg_slope为温度与Vsense曲线的平均斜率,一般取0.0043;Vsense是内部传感器采集到的电压值。(以F1为例)

实验要求:ADC1通道16采集芯片内部温度传感器的电压,将电压转算为温度后显示在液晶屏上。

我们通过下表可以知道DMA1通道1的外设对应的就是ADC1的读取。

 

首先确定我们的最小刻度,Vref = 3.3V,所以0V <= Vin <= 3.3V,所以最小刻度是3.3V / 4096(2^12)。

接下来确定转换时间。采样时间239.5个ADC时钟周期为例,可以得到转换时间为21us。

时间转换公式参考如下公式:Tcvtmin=(12.5+X)周期=(12.5 + X)/(12MHz)=21us。

 接下来编写实验代码:

先编写函数文件adc_t.c:

#include "./BSP/ADC_T/adc_t.h"

ADC_HandleTypeDef g_adc_handle;

void adc_temperature_init(void){

    ADC_ChannelConfTypeDef adc_ch_conf;
 
    g_adc_handle.Instance = ADC1;
    g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
    g_adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE; //不扫描
    g_adc_handle.Init.ContinuousConvMode = DISABLE; //单次模式
    g_adc_handle.Init.NbrOfConversion = 1; //转换通道数为1,单通道
    g_adc_handle.Init.DiscontinuousConvMode = DISABLE; //不用间断模式
    g_adc_handle.Init.NbrOfDiscConversion = 0; //无间断模式则无间断通道
    g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; //外部软件触发
 
    HAL_ADC_Init(&g_adc_handle);
    HAL_ADCEx_Calibration_Start(&g_adc_handle);
 
    adc_ch_conf.Channel = ADC_CHANNEL_1;
    adc_ch_conf.Rank = ADC_REGULAR_RANK_1; //转换顺序
    adc_ch_conf.SamplingTime = ADC_SMAPLINGTIME_239CYCLES_5; //设置为最大值
 
    HAL_ADC_ConfigChannel(&g_adc_handle, &adc_ch_conf);
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc){

    if(hadc->Instance == ADC1){
        GPIO_InitTypeDef gpio_init_struct;
        RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
 
        __HAL_RCC_GPIOA_CLK_ENABLE();  //使能ADC时钟
        __HAL_RCC_ADC1_CLK_ENABLE();   //使能GPIO时钟
 
        gpio_init_struct.Pin = GPIO_PIN_1;
        gpio_init_struct.Mode = GPIO_MODE_ANALOG; //模拟模式
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);
 
        adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC; //选择ADC外设时钟设置
        adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6; //选择6分频,72/6=12MHz
 
        HAL_RCCEx_PeriphCLKConfig(&adc_clk_init, &g_adc_handle);
    }
}

uint32_t adc_get_result(void){

    HAL_ADC_Start(&g_adc_handle);
    HAL_ADC_PollForConversion(&g_adc_handle, 10); //第二个参数比1大就行
    return (uint16_t)HAL_ADC_GetValue(&g_adc_handle);
}

short adc_get_temperature(void){
    uint32_t adcx;
    short result;
    double temperature;

    adcx = adc_get_result();
    temperature = adcx * (3.3 / 4096);
    temperature = (1.43 - temperature) / 0.0043 + 25;
    result = temperature *= 100;

    return result;
}

接下来编写函数头文件代码adc_t.h:

#ifndef __ADC_T_H
#define __ADC_T_H

#include "./SYSTEM/sys/sys.h"

void adc_temperature_init(void);
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc);
uint32_t adc_get_result(void);
short adc_get_temperature(void);

#endif

接下来编写主函数代码main.c:

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"
#include "./BSP/ADC_T/adc_t.h"


int main(void)
{
    short temp;

    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */
    delay_init(72);                             /* 延时初始化 */
    usart_init(115200);                         /* 串口初始化为115200 */
    led_init();                                 /* 初始化LED */
    lcd_init();                                 /* 初始化LCD */
    adc_temperature_init();                     /* 初始化ADC内部温度传感器采集 */

    lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);
    lcd_show_string(30,  70, 200, 16, 16, "Temperature TEST", RED);
    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 120, 200, 16, 16, "TEMPERATE: 00.00C", BLUE);

    while (1)
    {

        temp = adc_get_temperature();   /* 得到温度值 */

        if (temp < 0)
        {
            temp = -temp;
            lcd_show_string(30 + 10 * 8, 120, 16, 16, 16, "-", BLUE);   /* 显示负号 */
        }
        else
        {
            lcd_show_string(30 + 10 * 8, 120, 16, 16, 16, " ", BLUE);   /* 无符号 */
        }
        lcd_show_xnum(30 + 11 * 8, 120, temp / 100, 2, 16, 0, BLUE);    /* 显示整数部分 */
        lcd_show_xnum(30 + 14 * 8, 120, temp % 100, 2, 16, 0X80, BLUE); /* 显示小数部分 */
        
        LED0_TOGGLE();  /* LED0闪烁,提示程序运行 */
        delay_ms(250);
    }
}

到这里我们的函数代码就写完了。

物联沃分享整理
物联沃-IOTWORD物联网 » STM32内部温度传感器实验指南

发表回复