STM32的HAL库开发---ADC采集内部温度传感器
一、STM32内部温度传感器简介
二、温度计算方法
F1系列:
从数据手册中可以找到V25和Avg_Slope
F4、F7、H7系列只是标准值不同,自行查阅手册
三、实验简要
1、功能描述
通过ADC1通道16采集芯片内部温度传感器的电压,将电压值换算成温度后,串口发送
2、确定最小刻度
VREF+ = 3.3V ---> 0V ≤ VIN ≤ 3.3V --->最小刻度 = 3.3 / 4096
3、确定转换时间
采样时间设置为最小值239.5个ADC时钟周期,可以得到转换时间为21us,满足温度传感器要求的17us.
4、模式组合
连续转换模式、不扫描模式
四、编程实战
1、寄存器版本
adc.c源程序
#include "./BSP/ADC/adc.h"
void ADC_Init(void)
{
//开启ADC1时钟
RCC->APB2ENR |= (1 << 9);
//TSVREFE 开启内部温度传感器
ADC1->CR2 |= (1 << 23);
//设置ADC时钟分频系数为6 ADC采集时钟为12M
//这个注意温度传感器采样时间不能少于17us
RCC->CFGR |= (1 << 15);
//SCAN位 一个通道 关闭扫描模式
ADC1->CR1 &= ~(1 << 8);
//EXTTRIG 开启规则通道的外部触发
ADC1->CR2 |= (1 << 20);
//EXTSEL 设置为SWSTART软件触发
ADC1->CR2 |= (0X07 << 17);
//ALIGN 设置数据对齐为右对齐模式
ADC1->CR2 &= ~(1 << 11);
//ADCON 开启ADC
ADC1->CR2 |= (1 << 0);
//CONT 开启连续转化模式
ADC1->CR2 |= (1 << 1);
//SMP1 ADC1_CH1 设置采样时间为239.5个时钟周期
//时钟为12M 239.5 + 12.5 = 252个周期
ADC1->SMPR2 |= (0X07 << 3);
//L 设置规则通道转换数为1
ADC1->SQR1 &= (0X0F << 20);
//SQ1 设置第一个转化为ADC通道16
ADC1->SQR3 |= (16 << 0);
//RSTCAL 初始化校准寄存器
ADC1->CR2 |= (1 << 3);
/*********************注意***************/
//第一个不写会出问题
//这必须要等待两次 一个是等待校准寄存器初始化完成之后 ,再开启校准
//第二个是等待校准完成再开始转换
//等待校准完成
while(ADC1->CR2 & (1 << 3));
//CAL 开始校准
ADC1->CR2 |= (1 << 2);
//等待校准完成
while(ADC1->CR2 & (1 << 2));
//SWSTART 开启规则通道软件触发
ADC1->CR2 |= (1 << 22);
}
main.c主函数
主函数里边只要使用公式计算内部温度传感器温度
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/ADC/adc.h"
uint16_t ADC_Voyage = 0;
double V_SENSE = 0;
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_Init(); /* LED初始化 */
usart_init(115200);
ADC_Init();
while(1)
{
LED0(1);
LED1(0);
delay_ms(500);
LED0(0);
LED1(1);
delay_ms(500);
//while
//读取DR数据寄存器的值
ADC_Voyage = (ADC1 ->DR) & (0x0FFF);
//将数据值转换为电压值
V_SENSE = ((double)ADC_Voyage * 3.3) / 4096;
printf("STM32内部温度为:%f℃\r\n",((double)(1.43 - V_SENSE))/0.0043 + 25);
//触发ADC转换一次
//ADC1->CR2 |= (1 << 22);
}
}
2、库函数版本
adc.c源程序
#include "./BSP/ADC/adc.h"
GPIO_InitTypeDef GPIO_Init;
ADC_HandleTypeDef hadc;
void ADC_Init(void)
{
hadc.Instance = ADC1;
//开启连续转换
hadc.Init.ContinuousConvMode = ENABLE;
//数据右对齐 12位存16位寄存器
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
//关闭间断模式
hadc.Init.DiscontinuousConvMode = DISABLE;
//软件触发
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
//转换数量一个
hadc.Init.NbrOfConversion = 1;
//间断模式转换数量0
//关闭扫描模式 就一个通道
hadc.Init.NbrOfDiscConversion = 0;
hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
HAL_ADC_Init(&hadc);
ADC_ChannelConfTypeDef sConfig;
//配置通道1
sConfig.Channel = ADC_CHANNEL_1;
//第一个转换
sConfig.Rank = ADC_REGULAR_RANK_1;
//采样时间239.5 + 12.5
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&hadc,&sConfig );
//ADC校准功能
HAL_ADCEx_Calibration_Start(&hadc);
//开启ADC采集
HAL_ADC_Start(&hadc);
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
//开启ADC1时钟
__HAL_RCC_ADC1_CLK_ENABLE();
//开启GPIOA时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_Init.Mode = GPIO_MODE_ANALOG;
GPIO_Init.Pin = GPIO_PIN_1;
GPIO_Init.Pull = GPIO_NOPULL;
//设置PA1为模拟输入模式
HAL_GPIO_Init(GPIOA,&GPIO_Init);
RCC_PeriphCLKInitTypeDef PeriphClkInit;
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
}
这里注意要配置RCC时钟,将ADC的分频系数配置位6分频