STM32的HAL库开发---ADC采集内部温度传感器

news/2025/2/24 14:20:45

一、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分频


http://www.niftyadmin.cn/n/5864452.html

相关文章

垂类大模型微调(二):使用LLaMA-Factory

上一篇博文和大家一起安装了LLaMA-Factory工具,并下载了大模型在上面进行了简单的加载和推理,今天尝试通过LoRa技术对大模型进行微调; 一、训练集准备 1.1 介绍训练集结构 这里演示对Qwen2.5-0.5B-Instruct-GPTQ-Int4模型进行LoRA微调, 大家可以根据垂类大模型微调(一)…

LeetCode 热题 100 560. 和为 K 的子数组

LeetCode 热题 100 | 560. 和为 K 的子数组 大家好&#xff0c;今天我们来解决一道经典的算法题——和为 K 的子数组。这道题在 LeetCode 上被标记为中等难度&#xff0c;要求我们统计数组中所有和为 k 的连续子数组的个数。下面我将详细讲解解题思路&#xff0c;并附上 Pytho…

缓存基础解释与缓存友好型编程基础

讨论了如何使用快速核心内存&#xff08;约32,000个字&#xff09;作为更大、更慢的核心内存&#xff08;约1,000,000个字&#xff09;的从属内存&#xff08;slave&#xff09;。 通过这种方式&#xff0c;可以在实际使用案例中设计出接近于更快内存的有效访问时间&#xff08…

Vue 3 + Vite 项目中配置代理解决开发环境中跨域请求问题

在 Vue 3 Vite 项目中&#xff0c;配置代理是解决开发环境中跨域请求问题的常见方法。通过在 Vite 的配置文件中设置代理&#xff0c;可以将前端请求转发到后端服务器&#xff0c;从而避免浏览器的同源策略限制。 1. 创建 Vue 3 Vite 项目 首先&#xff0c;确保你已经安装了…

广东英语十二种应用文模版范文

1. 邀请信&#xff08;Invitation Letter&#xff09; 模版 Dear [Recipients Name],I hope this letter finds you well. I am writing to invite you to [Event Name] which will be held on [Date] at [Location]. The event will start at [Time] and we would be deligh…

CSS通过webkit-scrollbar设置滚动条样式

查看::-webkit-scrollbar-*各项关系 以下图为例&#xff0c;可以分别定义滚动条背景、滚动轨道、滚动滑块的样式。 需要先给外部容器设置高度&#xff0c;再设置overflow: auto&#xff0c;最后设置三个webkit属性。 <!DOCTYPE html> <html lang"en">…

[LeetCode力扣hot100]-快速选择和快排

快速选择与快速排序的区别&#xff1a; 快速排序&#xff1a;递归地对数组的左右两部分进行排序。快速选择&#xff1a;只递归处理包含第 k 个元素的那一部分&#xff0c;目标是找到第 k 大的元素&#xff0c;而不是对整个数组排序。 快排 void quickSortHelper(vector<i…

MongoDB#常用语句

创建TTL索引(自动删除过期数据) db.xxx_collection.createIndex({ createTime: 1 }, { expireAfterSeconds: 1 * 24 * 60 * 60 * 1000 }); 查询JavaScript函数(mongosh) db.system.js.find 查询document条数 db.getCollection(‘xxx’).countDocuments({}) 根据_id查询 {‘_id’…