Cortex-M3-STM32F1 开发:(四十七)ADC 实例 5 :内部温度传感器读取
| 上一篇 | 下一篇 |
|---|---|
| ADC 实例 4 :单通道 ADC 过采样实例,使用 DMA |
3.5)内部温度传感器读取
STM32 各系列 MCU 中内部温度传感器的相关数据:

上电在 HAL_ADC_ConfigChannel() 函数中执行。
① 温度计算公式:
T ( ℃ ) = ( V 25 − V S E N S E A v g _ S l o p e ) + 25 \large T(℃) = (\frac{V_{25}−V_{SENSE}}{Avg\_Slope})+25 T(℃)=(Avg_SlopeV25−VSENSE)+25
V 25 V_{25} V25 = 25 ℃ 时的 V S E N S E V_{SENSE} VSENSE 值(典型值为: 1.43)
A v g _ S l o p e Avg\_Slope Avg_Slope = 温度与 V S E N S E V_{SENSE} VSENSE 曲线的平均斜率(单位: mv/℃ 或 uv/℃)(典型值:4.3mv/℃)
V S E N S E V_{SENSE} VSENSE 是 ADC 采集到内部温度传感器的电压值(换算后的)
② 实验简要:
- 功能描述:
- 通过 ADC1 通道16 芯片内部温度传感器的电压,将电压值换算成温度后,用串口打印
- 确定最小刻度:
- V R E F + = 3.3 V V_{REF+} = 3.3V VREF+=3.3V → 0 V ≤ V I N ≤ 3.3 V 0V≤V_{IN}≤3.3V 0V≤VIN≤3.3V → 最小刻度 = 3.3 / 4096 V 3.3/4096V 3.3/4096V
- 确定转换时间:
- 采样时间设置为最大值 239.5 个 ADC 时钟周期,可以得到转换时间为 21us
- 模式组合:
- 单次转换模式、不使用扫描模式(即不使用 DMA 传输)
- 注意:
- 在单片机内部,调用
HAL_ADC_ConfigChannel()函数的时候,会判断是否为温度传感器,是则给其上电。
- 在单片机内部,调用
③ 代码:
adc.c 文件代码:
#include "adc.h"
#include "delay.h"
#include "usart.h"
ADC_HandleTypeDef adc_handle;
/**
* @brief ADC初始化函数
* @param none
* @retval none
* @note 单通道、单次转换模式、不使用扫描模式(不使用DMA)
*/
void adc_temperature_init(void)
{
ADC_ChannelConfTypeDef adc_ch_conf;
// 配置ADC工作参数
adc_handle.Instance = ADC1;
adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 对齐方式:右对齐
adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE; // 扫描模式:失能
adc_handle.Init.ContinuousConvMode = DISABLE; // 连续转换模式:失能
adc_handle.Init.NbrOfConversion = 1; // 转换通道总数
adc_handle.Init.DiscontinuousConvMode = DISABLE; // 不用管:直接失能
adc_handle.Init.NbrOfDiscConversion = 0; // 不用管:直接赋0
adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
HAL_ADC_Init(&adc_handle);
// ADC校准
HAL_ADCEx_Calibration_Start(&adc_handle);
// 配置ADC通道相关参数
adc_ch_conf.Channel = ADC_CHANNEL_16; // 输入通道号:通道16,内部温度传感器
adc_ch_conf.Rank = ADC_REGULAR_RANK_1; // 转换顺序:第一个转换
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 采样时间:239.5个周期
HAL_ADC_ConfigChannel(&adc_handle, &adc_ch_conf);
}
/**
* @brief ADC MSP初始化函数
* @param ADC 句柄
* @retval none
* @note 定义通道1 → PA1、使能时钟
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
// 时钟使能:ADC1
__HAL_RCC_ADC1_CLK_ENABLE();
// 配置ADC1时钟
adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;
adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6; // 6分频,72/6=12MHz
HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);
}
}
/**
* @brief ADC结果获取函数
* @param none
* @retval uint32_t类型的转换结果(实际是低16位有效)
* @note 开始转换 → 等待转换 → 获取结果(读取DR寄存器)
*/
uint32_t adc_get_result(void)
{
HAL_ADC_Start(&adc_handle); // 开始转换
HAL_ADC_PollForConversion(&adc_handle, 10); // 等待10ms
return (uint16_t)HAL_ADC_GetValue(&adc_handle); // 获取结果
}
/**
* @brief 获取内部温度传感器温度值
* @param none
* @retval 温度值(double型)
*/
double adc_get_temperature(void)
{
uint32_t adcx;
double temperature;
adcx = adc_get_result();
temperature = adcx * (3.3 / 4096); // 电压值
temperature = (1.43 - temperature) / 0.0043 + 25; // 计算温度
return temperature;
}
adc.h 文件代码如下:
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
void adc_temperature_init(void); // ADC初始化
uint32_t adc_get_result(void); // 获取ADC转换结果
double adc_get_temperature(void); // 温度计算函数
#endif
main.c 文件代码如下:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "string.h"
#include "dma.h"
#include "adc.h"
// ====================================================================
int main(void)
{
/* 局部变量 */
float temp;
/* 初始化函数 */
HAL_Init(); // 初始化HAL库
Stm32_Clock_Init(RCC_PLL_MUL9); // 设置时钟,72M
delay_init(72); // 初始化延时函数
LED_Init(); // 初始化LED
KEY_Init(); // 按键初始化
uart_init(115200); // 串口1初始化
adc_temperature_init(); // ADC读取温度函数初始化
while(1)
{
temp = adc_get_temperature(); // 获取ADC转换结果
printf("温度为:%f 摄氏度", temp);
LED0=!LED0;
delay_ms(100);
}
}
实验结果为:

更多推荐



所有评论(0)