实验目的

STM32内部集成了一个温度传感器,可以用来测量芯片的温度,本章学习如何读取此温度值,数据手册请参看第11章。

实验简介

STM32的内部温度传感器在内部和ADCx_IN16输入通道相连接,此通道把传感器输出的电压换成数字。温度传感器模拟输入推荐采样时间是17.1us。STM32的内部温度传感器支持的范围为-40~125度。精度比较差,为±1.5度左右。STM32内部温度传感器的使用很简单,只要设置一下内部ADC,并激活其内部通道就差不多了。

读温度
为使用传感器:
1.选择ADC1_IN16输入通道
2.选择采样时间为17.1us
3.设置ADC控制寄存器2(ADC_CR2)的TSVREFE位,以唤醒关电模式下温度传感器
4.通过设置ADON位启动ADC转换(或用外部触发)
5.读ADC数据寄存器上的Vsense数据结果
6.利用下列公式得出温度
温度( °C )= {(V25 - Vsense)/Avg_Slope } +25;
这里:
V25 = Vsense在25°C时的数值
Avg_Slope = 温度与Vsense曲线的平均斜率(单位为mV/°C或uV/°C)
其中V25和Avg_Slope的参考值在下图中

代码

main.c

#include "MyIncludes.h"char buff[100];
int16_t Val;u16 sys_cnt = 0;
void systick_isr(void)
{if(sys_cnt < 1000)sys_cnt++;else{sys_cnt = 0;HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5);}
}int main(void)
{ System_Init();LED_Init();SysTick_Init(systick_isr);USART1_Init(115200,NULL,NULL);STM32_TempSample_Init();//内部温度采集while(1){delay_ms(1000);Val = Temp_Sample();if(Val < 0)sprintf(buff,"Chip Temp: -%d%d.%d'C\n",Val/1000,Val%1000/100,Val%100/10);elsesprintf(buff,"Chip Temp: %d%d.%d'C\n",Val/1000,Val%1000/100,Val%100/10);printf(buff);}
}

adc.c

#ifndef __ADC_H_
#define __ADC_H_#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"#define ADC_DMA_ENABLE
//使能DMA传输typedef struct
{void (*isr_op)(void);//中断处理
} _ADC_ISR_;extern ADC_HandleTypeDef AdcHandle;void  STM32_ADC_Init(ADC_TypeDef *ADCx,uint32_t Channel,void(*ISR)(void));
//ADC初始化
uint32_t Vol_Sample(void);
//电压采样void STM32_VRefSample_Init(void);
//内部参考电压Vref采集
uint16_t VRef_Sample(void);
//内部参考电压Vref采样void STM32_TempSample_Init(void);
//内部温度传感器采集
int Temp_Sample(void);
//内部温度采样
#endif

adc.c

#include "adc.h"ADC_HandleTypeDef    AdcHandle;
//ADC句柄结构变量声明
_ADC_ISR_  adc_isr;
//DMA句柄结构变量声明
#ifdef ADC_DMA_ENABLE
//使能DMA
uint32_t   aADCxConvertedValues;
#endif//在HAL_ADC_Init中调用
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{GPIO_InitTypeDef          GPIO_InitStruct;//GPIO初始化结构变量声明static DMA_HandleTypeDef  hdma_adc;//DMA句柄结构变量声明RCC_PeriphCLKInitTypeDef  PeriphClkInit;//RCC扩展时钟结构变量声明PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;//要配置的扩展时钟 ADC外围时钟PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;//ADC时钟源 可以是预分频器的值 PCLK(IO接口时钟)2/6HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);//RCC外围时钟源配置__ADC1_CLK_ENABLE();//使能ADC1时钟__GPIOA_CLK_ENABLE();//使能GPIOA时钟GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;//模拟输入模式GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);//GPIO初始化配置#ifdef ADC_DMA_ENABLE__HAL_RCC_DMA1_CLK_ENABLE();//使能DMA1时钟hdma_adc.Instance = DMA1_Channel1;
//寄存器基址hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;//外设到内存方向hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;//外围增量模式禁用hdma_adc.Init.MemInc = DMA_MINC_ENABLE;//内存增量模式启用hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;//外围数据对齐 半字hdma_adc.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;//外围数据对齐 半字hdma_adc.Init.Mode = DMA_CIRCULAR;//圆形模式hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;//优先级 高HAL_DMA_Init(&hdma_adc);//DMA 初始化__HAL_LINKDMA(hadc, DMA_Handle, hdma_adc);//将初始化的DMA句柄与ADC句柄关联HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);//设置优先级HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);//设置中断源#endif
}
void STM32_ADC_Init(ADC_TypeDef *ADCx, uint32_t Channel, void (*ISR)(void))
{ADC_ChannelConfTypeDef sConfig;//ADC通道结构变量声明adc_isr.isr_op = ISR;   //挂载中断处理函数//配置ADC外设AdcHandle.Instance          = ADCx;//寄存器基址ADC1  AdcHandle.Init.ScanConvMode = ADC_SCAN_DISABLE;  //禁止扫描模式          AdcHandle.Init.ContinuousConvMode = ENABLE;   //使能连续转换AdcHandle.Init.DiscontinuousConvMode = DISABLE;  //禁止常规通道不连续采样  AdcHandle.Init.NbrOfDiscConversion = 0;   //不连续采样模式下的转换常规通道         AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;  //软件启动      AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;    //右对齐AdcHandle.Init.NbrOfConversion = 1;                 //常规通道序列长度,2次转换HAL_ADC_Init(&AdcHandle);//ADC初始化//配置ADC通道sConfig.Channel = Channel;//转换通道   sConfig.Rank = ADC_REGULAR_RANK_1;//指定常规组序列器的列组sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;//要为选定通道设置的采样时间值HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);//ADC配置通道HAL_ADCEx_Calibration_Start(&AdcHandle);  //ADC校准#ifdef ADC_DMA_ENABLE     //ʹÄÜDMA//使能DMAHAL_ADC_Start_DMA(&AdcHandle, &aADCxConvertedValues, sizeof(aADCxConvertedValues));#elseHAL_ADC_Start_IT(&AdcHandle);//使能ADC中断,启动ADC#endif
}void ADC_IRQHandler(void)
//ADC中断函数
{HAL_ADC_IRQHandler(&AdcHandle);
}void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
//转换完成回调,在HAL_ADC_IRQHandler中调用
{if(adc_isr.isr_op != NULL) adc_isr.isr_op();
}#ifdef ADC_DMA_ENABLE
//使能DMA
void DMA1_Channel1_IRQHandler(void)
//DMA中断
{HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);
}
#endif//电压采样
uint32_t Vol_Sample(void)
{#ifdef ADC_DMA_ENABLE//使能DMA return (aADCxConvertedValues&0xFFF)*3300/4096;#elseuint32_t Vol_ADC_Val;Vol_ADC_Val = HAL_ADC_GetValue(&AdcHandle);return Vol_ADC_Val*3300/4096;//返回电压值扩大1000倍#endif
}
ADC_HandleTypeDef    AdcBatHandle;
//ADC句柄结构变量声明
void STM32_VRefSample_Init(void)
{ADC_ChannelConfTypeDef sConfig;//配置ADC常规组结构变量声明__ADC1_CLK_ENABLE();//使能ADC1时钟//配置ADC外设AdcBatHandle.Instance          = ADC1;//寄存器基址AdcBatHandle.Init.ScanConvMode = ADC_SCAN_DISABLE;//禁止扫描模式AdcBatHandle.Init.ContinuousConvMode = ENABLE;//使能连续转换AdcBatHandle.Init.DiscontinuousConvMode = DISABLE;  //禁止常规通道的不连续采样模式AdcBatHandle.Init.NbrOfDiscConversion = 0;  //不连续采样模式下的转换常规通道数         AdcBatHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;//软件启动AdcBatHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;  //右对齐AdcBatHandle.Init.NbrOfConversion = 1;                 //常规通道序列长度 2次转换HAL_ADC_Init(&AdcBatHandle);//ADC配置初始化//配置ADC通道sConfig.Channel = ADC_CHANNEL_VREFINT;   //VBAT检测,通道为ADC1_IN17sConfig.Rank = ADC_REGULAR_RANK_2;//指定常规组序列器的列组sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;//要为选定通道设置的采样时间值HAL_ADC_ConfigChannel(&AdcBatHandle, &sConfig);//ADC配置通道 HAL_ADC_Start(&AdcBatHandle);//启动ADC
}uint16_t VRef_Sample(void)
//内部参考电压Vref采样
{uint32_t VBat_ADC_Val;VBat_ADC_Val = HAL_ADC_GetValue(&AdcBatHandle);return VBat_ADC_Val*3300/4096;//返回电压值扩大1000倍
}
void STM32_TempSample_Init(void)
//内部温度传感器采集
{ADC_ChannelConfTypeDef sConfig;__ADC1_CLK_ENABLE();//使能ADC1时钟AdcBatHandle.Instance          = ADC1;//寄存器基址AdcBatHandle.Init.ScanConvMode = ADC_SCAN_DISABLE;//禁止扫描模式AdcBatHandle.Init.ContinuousConvMode = ENABLE;  //使能连续转换AdcBatHandle.Init.DiscontinuousConvMode = DISABLE; //禁止常规通道的不连续采样模式AdcBatHandle.Init.NbrOfDiscConversion = 0;  //不连续采样模式下的转换常规通道数AdcBatHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;  //软件启动AdcBatHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;  //右对齐AdcBatHandle.Init.NbrOfConversion = 1;                 //常规通道序列长度 2次转换HAL_ADC_Init(&AdcBatHandle);//ADC初始化//配置通道sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;   //内部温度采集 通道为ADC1_IN16;sConfig.Rank = 1;//指定常规组序列器的列组sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;//要为选定通道设置的采样时间值HAL_ADC_ConfigChannel(&AdcBatHandle, &sConfig);//ADC通道设置HAL_ADC_Start(&AdcBatHandle);//ADC启动
}//内部温度采样
//温度 = {(V25 - VSENSE)/Avg_Slope} + 25;
//其中v25 = 1.43,Avg_Slope = 0.0043
//参考数据手册温度传感器电器特性一节
float temperate;
int Temp_Sample(void)
{uint32_t ADC_Val;float temperate;ADC_Val = HAL_ADC_GetValue(&AdcBatHandle);temperate = (float)ADC_Val*3.3/4096;   //返回电压值temperate = (1.43 - temperate)/0.0043 + 25;return (int)temperate * 100;//结果扩大100倍
}

实验现象

D5 D6 LED灯闪烁

HAL库代码

test.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include  "adc.h"int main(void)
{short temp;Stm32_Clock_Init(9);//系统时钟设置    uart_init(72,115200);//串口初始化为115200 delay_init(72); //延时初始化      LED_Init();    //初始化与LED连接的硬件接口            Adc_Init();while(1){LED3 = !LED3;temp = Get_Temperature();printf("%hd.%hdC\r\n",temp/100,temp%100);delay_ms(250);}
}

adc.h

#ifndef __ADC_H
#define __ADC_H
#include "sys.h"#define ADC_CH1  1
#define ADC_CH7  7 //通道7连接在PA7
#define ADC_CH_TEMP  16//温度传感器通道    short Get_Temperature(void);
void Adc_Init(void); //ADC通道初始化
u16  Get_Adc(u8 ch); //获得某个通道值
u16 Get_Adc_Average(u8 ch,u8 times);
//得到某个通道的采样平均值
#endif 

adc,c

#include "adc.h"
#include "delay.h"                       void  Adc_Init(void)
{    //初始化IO口RCC->APB2ENR|=1<<2; //使能PORTA口时钟   GPIOA->CRL&=0X0FFFFFFF;//PA7 输入RCC->APB2ENR|=1<<9;   //ADC1时钟使能RCC->APB2RSTR|=1<<9;  //ADC1复位RCC->APB2RSTR&=~(1<<9);//复位结束RCC->CFGR&=~(3<<14);  //分频因子清零//SYSCLK/DIV2=12M ADC时钟设置为12M//ADC最大时钟不能超过14M!//否则将导致ADC准确度下降RCC->CFGR|=2<<14;           ADC1->CR1&=0XF0FFFF;  //工作模式清零ADC1->CR1|=0<<16; //独立工作模式    ADC1->CR1&=~(1<<8);  //非扫描模式 ADC1->CR2&=~(1<<1);  //单次转换模式 ADC1->CR2&=~(7<<17);       ADC1->CR2|=7<<17;//软件控制转换     ADC1->CR2|=1<<20; //使用用外部触发(SWSTART)!!必须使用   一个事件触发 ADC1->CR2&=~(1<<11);  //右对齐ADC1->CR2 |= 1<<23; //使能温度传感器ADC1->SQR1&=~(0XF<<20);//1个转换在规则序列中,也就是只转换规则序列1ADC1->SQR1|=0<<20;//设置通道1的采样时间     ADC1->SMPR2&=~(3*1); //通过1采样时间清空  ADC1->SMPR2|=7<<(3*1); //通道1 239.5周期,提高采样时间可以提高精确度ADC1->SMPR1&=~(7<<3*6);//清除通道16原来的设置ADC1->SMPR1|=7<<(3*6);  //通道16 239.5周期,提高采样时间可以提高精确度ADC1->CR2|=1<<0;//开启AD转化器      ADC1->CR2|=1<<3; //使能复位校准     while(ADC1->CR2&1<<3); //等待校准结束  ADC1->CR2|=1<<2;   //开启AD校准        while(ADC1->CR2&1<<2);  //等待校准结束//该位由软件设置以开始校准,并在校准结束时由硬件清除}                //获得ADC1某个通道的值
u16 Get_Adc(u8 ch)
{//设置转换序列        ADC1->SQR3&=0XFFFFFFE0;//规则序列1 通道chADC1->SQR3|=ch;                     ADC1->CR2|=1<<22;  //启动规则转换通道    while(!(ADC1->SR&1<<1));    //等待转换结束   return ADC1->DR;  //返回adc值
}u16 Get_Adc_Average(u8 ch,u8 times)
{u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}return temp_val/times;
} short Get_Temperature(void)
{u32 adcx;short result;double temperature;adcx = Get_Adc_Average(ADC_CH_TEMP,20);temperature = (float)adcx*(3.3/4096);temperature = (1.43 - temperature)/0.0043 + 25;result = temperature*=100;return result;}

STM32F103 内部温度传感器实验相关推荐

  1. 32_STM32内部温度传感器实验

    目录 内部温度传感器简介 STM32ADC对应引脚 内部温度传感器使用注意使用事项 开启内部温度传感器步骤 实验源码 内部温度传感器简介 内部温度传感器框图 从图上可以看出温度传感器可通过TSVREF ...

  2. [嵌入式]stm32内部温度传感器实验

    实验概述 文章目录 实验概述 一.概述 二.实验平台 (1)硬件平台ALIENTEK MiniSTM32 开发板 (2)软件平台 三.实验过程 1.STM32 内部温度传感器简介 2.硬件设计 3.软 ...

  3. 实验15:内部温度传感器实验

    一.简介 STM32F407有一个内部的温度传感器(位于CPU内部),可以用来测量CPU及周围的温度. 该温度传感器在内部和ADCx_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值. 温 ...

  4. stm32Cubemx实用篇(三):DAC电压输出和ADC电压检测以及内部温度传感器测温

    stm32Cubemx实用篇(三):DAC电压输出和ADC电压检测以及内部温度传感器测温 本章将介绍使用stm32Cubemx软件配置DAC电压输出和ADC电压检测.最终将两个引脚连接起来通过一个AD ...

  5. 内部温度传感器和光敏传感器实验

    内部温度传感器 STM32F407 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(TA).该温度传感器在内部和 ADC1_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值. ...

  6. STM32学习心得二十四:内部温度传感器原理及实验

    记录一下,方便以后翻阅~ 主要内容: 1) STM32内部温度传感器概述: 2) 相关实验代码解读. 实验功能:系统启动后,实时将内部温度传感器的值传至串口助手上. 官方资料:<STM32中文参 ...

  7. 《嵌入式 – GD32开发实战指南》第14章 内部温度传感器

    开发环境: MDK:Keil 5.30 开发板:GD32F207I-EVAL MCU:GD32F207IK 14.1内部温度传感器工作原理 GD32 有一个内部的温度传感器,可以用来测量 CPU 及周 ...

  8. STM32F103 TFTLCD显示实验(一)

    文章内容 本文将介绍有关TFTLCD的有关知识,包括几个部分,分别如下: TFTLCD简介 相关指令 配置步骤 FSMC简介 由于篇幅过长,因此,代码讲解放到下一章中,链接如下: STM32F103 ...

  9. STM32CubeMX系列|内部温度传感器

    内部温度传感器 1. 内部温度传感器简介 STM32F1有一个内部的温度传感器,可以用来测量CPU及周围的温度.该温度传感器在内部和ADCx_IN16输入通道相连接,此通道把传感器输出的电压转换成数字 ...

最新文章

  1. TypeError: __init__() got an unexpected keyword argument #34serialized_options #34
  2. vc6.0打开工程出现程序崩了的原因
  3. RIPv1 与 RIPv2 基础配置
  4. bp神经网络matlab实例蚊子,bp神经网络matlab实例
  5. C语言 几种排序方法(冒泡、选择、插入、归并、快速)
  6. 你小时候家里最穷的时候有多穷?
  7. python 函数中参数的传递方式(三分钟读懂)
  8. !!!常用CSS代码块
  9. eureka 注册中心高可用失败,没有互为副本
  10. 脚本小子福利:安卓远控木马直接生成
  11. 2018 CISSP考试一路走来
  12. 互联网晚报 | 7月16日 星期六 |抖音回应“外卖功能上线”;上半年国内生产总值同比增长2.5%;雷军8月将携小米工程样车亮相...
  13. 成长之路——发现问题、提出问题和解决问题
  14. java简易计算器报告_简易计算器java实训报告.docx
  15. 2021年安全员-C证(陕西省)考试总结及安全员-C证(陕西省)模拟考试系统
  16. C++实现凸包Graham_scan算法
  17. 【FPGA学习】Quartus II新建工程流程
  18. opengl碗状_OpenGLES简单入门
  19. R语言 NetCoMi包 Co-occurrence网络图 微生物16S 网络比较 核心物种
  20. MySQL创建数据库表的语句和基础语句

热门文章

  1. pytorch模型(.pt)转onnx模型(.onnx)的方法详解(1)
  2. XP系统加入域提示无法找到网络路径处理方法
  3. 迁移系统至固态硬盘的采坑回顾
  4. 计算机网络实验华中科技大学,华中科技大学计算机网络实验报告.pdf
  5. 夜间旅游在经济发展中起到哪些作用
  6. 图像分析:二值图像连通域标记-基于行程的标记方法
  7. 《Microduino实战》——2.5 Microduino传感器系列
  8. Svn中可能出现的问题解决办法
  9. webots车轮下陷问题 车轮在地下
  10. windows常用脚本bat合集