基于STM32战舰开发板的内部温度传感器实验

发布者:ww313618最新更新时间:2022-05-31 来源: eefocus关键字:STM32  战舰开发板  内部温度传感器 手机看文章 扫描二维码
随时随地手机看文章

内部温度传感器简介

测量的温度位置

内部温度传感器集成在芯片中,测量的是芯片的温度。


如何测量对应位置的温度?

温度传感器与ADC1_CH16相连,另外ADC1_CH17是与内部参照电压VREF+相连,因此我们可以通过ADC1的第16路通道测量芯片温度实时对应的电压转换得来的数字量,也可以通过ADC1的第17路通道测量内部参照电压对应的数字量。


我们知道STM32的ADC转换DATA是12Bits的,因此输入电压(小于3.3V大于0V)ADC转换为数字量的值为“大于0小于4096”。

我们由“T-V关系图”,“V的数字量”和“ADC量程”,可以得知“此时的温度”。


内部传感器配置注意事项

① 读取内部温度传感器数据的周期应大于17.1us;


② 内部温度传感器的温度测量误差约为1.5℃,因此内部温度传感器更适合于检测温度的变化,而不是测量绝对的温度。如果需要测量精确的温 度,应该使用一个外置的温度传感器。


内部温度传感器配置流程

image.png

image.png

内部温度传感器实验代码解析

ADC初始化代码

void ADC_InitConfig()  

{  

    ADC_InitTypeDef ADC_InitStructure;  

      

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);  

      

    ADC_DeInit(ADC1);  

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);  

      

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;  

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  

    ADC_InitStructure.ADC_NbrOfChannel = 1; // 定义规则通道的长度  

    ADC_InitStructure.ADC_ScanConvMode = DISABLE;  

    ADC_Init(ADC1,&ADC_InitStructure);  

      

    ADC_TempSensorVrefintCmd(ENABLE); // 使能内部温度传感器  

      

    ADC_Cmd(ADC1,ENABLE); // 使能ADC1  

      

    ADC_ResetCalibration(ADC1); // 开始ADC1的校准寄存器复位  

    while(ADC_GetResetCalibrationStatus(ADC1));  

      

    ADC_StartCalibration(ADC1); // 开始ADC1的自动校准功能  

    while(ADC_GetCalibrationStatus(ADC1));  

      

    delay_init();  

}  


我们应该注意到:ADC1_CH16连接着内部温度传感器,不用初始化具体的GPIO口引脚,只需要将寄存器的相应位使能即可:

我们有些同学在用如下“等待”代码的时候有些疑问:


ADC_ResetCalibration(ADC1); // 开始ADC1的校准寄存器复位  

while(ADC_GetResetCalibrationStatus(ADC1));  

  

ADC_StartCalibration(ADC1); // 开始ADC1的自动校准功能  

while(ADC_GetCalibrationStatus(ADC1));  

 

我们用while循环为ADC外设提供执行任务所需的等待时间,但是我们一对比如下while代码,就有点懵了:


ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  

  

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束  

 

在while循环中,应该“取非”?这个是个让人不解的问题。


我们此时应该看寄存器,看寄存器中位与状态的对应关系:


ADC1复位校准功能与ADC1执行校准功能分别对应“ADC控制寄存器 2(ADC_CR2)”对应的如下两个位:

我们看到上图,可以得到如下结论:

image.png

此外,ADC_SR状态寄存器中的标志位EOC位代表着“ADC转换工作是否结束”:

image.png

ADC转换函数

u16 ADC_GetValue()  

{     

    ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5 );  //ADC1,ADC通道3,第一个转换,采样时间为239.5周期                      

   

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  

      

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束  

      

    return ADC_GetConversionValue(ADC1);    //返回最近一次ADC1规则组的转换结果  

}  

 


注意:我们一定要在读取ADC通道转换值得函数中去执行:


ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  

      

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 

 


我们初始化时只想初始化ADCx设备的属性,而函数“ADC_SoftwareStartConvCmd”得功能是根据ADCx各个引脚的属性启动ADCx外设进行转换操作。显然,初始化时不应进行获取转换值得操作。


多次读取取平均函数

 //获取通道ch的转换值  

//取times次,然后平均  

u16 T_Get_Adc_Average(u8 ch,u8 times)  

{  

    u32 temp_val=0;  

    u8 t;  

    for(t=0;t    {  

        temp_val+=T_Get_Adc(ch);  

        delay_ms(5);  

    }  

    return temp_val/times;  

 


ADC转换的数字量转换为所需温度的函数

//得到温度值  

//返回值:温度值(扩大了100倍,单位:℃.)  

short Get_Temprate(void)    //获取内部温度传感器温度值  

{  

    u32 adcx;  

    short result;  

    double temperate;  

    adcx=T_Get_Adc_Average(ADC_Channel_16,20);  //读取通道16,20次取平均  

    temperate=(float)adcx*(3.3/4096);       //电压值   

    temperate=(1.43-temperate)/0.0043+25;   //转换为温度值       

    result=temperate*=100;                  //扩大100倍.  

    return result;  

}

 


总体代码示例

TempSensor.c

#include "TempSensor.h"  

#include "stm32f10x.h"  

#include "delay.h"  

  

void ADC_InitConfig()  

{  

    ADC_InitTypeDef ADC_InitStructure;  

      

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);  

      

    ADC_DeInit(ADC1);  

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);  

      

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;  

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  

    ADC_InitStructure.ADC_NbrOfChannel = 1; // 定义规则通道的长度  

    ADC_InitStructure.ADC_ScanConvMode = DISABLE;  

    ADC_Init(ADC1,&ADC_InitStructure);  

      

    ADC_TempSensorVrefintCmd(ENABLE); // 使能内部温度传感器  

      

    ADC_Cmd(ADC1,ENABLE); // 使能ADC1  

      

    ADC_ResetCalibration(ADC1); // 开始ADC1的校准寄存器复位  

    while(ADC_GetResetCalibrationStatus(ADC1));  

      

    ADC_StartCalibration(ADC1); // 开始ADC1的自动校准功能  

    while(ADC_GetCalibrationStatus(ADC1));  

      

    delay_init();  

}  

  

u16 ADC_GetValue()  

{     

    ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5 );  //ADC1,ADC通道3,第一个转换,采样时间为239.5周期                      

   

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  

      

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束  

      

    return ADC_GetConversionValue(ADC1);    //返回最近一次ADC1规则组的转换结果  

}  

  

u16 ADC_GetAverageValue()  

{  

    u8 i = 0;  

    u16 temp = 0;  

      

    for(;i<5;i++)  

    {  

        temp += ADC_GetValue();  

        delay_ms(5);  

    }  

    return temp/5;  

}  

  

u16 DigitalValueConversion()  

{  

    float temp = ADC_GetAverageValue();  

    return ((1.43-3.3*(temp/4096))/0.043+25)*100;  

}  

 


TempSensor.h

#ifndef _TEMPSENSOR_H  

#define _TEMPSENSOR_H  

  

#include "sys.h"  

  

void ADC_InitConfig();  

u16 ADC_GetValue();  

u16 ADC_GetAverageValue();  

u16 DigitalValueConversion();  

  

#endif  

 


Main.c

#include "TempSensor.h"  

#include "stm32f10x.h"  

#include "usart.h"  

#include "delay.h"  

#include "lcd.h"  

  

int main()  

{  

    u16 temp = 0;  

      

    ADC_InitConfig();  

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  

    uart_init(115200);  

    delay_init();  

    LCD_Init();  

    LCD_Clear(BLUE);  

      

    temp = DigitalValueConversion();  

      

    POINT_COLOR=RED;//设置字体为红色   

    LCD_ShowString(30,50,200,16,16,"WarShip STM32");      

    LCD_ShowString(30,70,200,16,16,"Temperature TEST");   

    LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");  

    LCD_ShowString(30,110,200,16,16,"2015/1/14");  

    LCD_ShowString(30,140,200,16,16,"TEMPERATE: 00.00C");  

      

    while(1)  

    {  

        temp = DigitalValueConversion();  

        LCD_ShowNum(30+11*8,140,temp/100,2,16);  

        LCD_ShowNum(30+14*8,140,temp%100,2,16);  

        delay_ms(150);  

    }  

}  

 

程序运行结果

关键字:STM32  战舰开发板  内部温度传感器 引用地址:基于STM32战舰开发板的内部温度传感器实验

上一篇:基于STM32战舰开发板的USMART调试组件的使用
下一篇:STM32的ADC实验的原理简介

推荐阅读最新更新时间:2024-11-11 02:39

STM32 LL库为什么比HAL库高效呢?
概 述 有些应用要求MCU能高效处理,特别是跑一些算法时,对CPU执行效率要求较高。 网上有很多文章说STM32Cube HAL执行效率不高,代码量大等问题 ,导致很多还没有入门,或初学的读者就产生各种各样的疑惑。 说实话,HAL相对标准外设库来说确实存在代码效率不高、代码量大灯这些问题,那么与之对应的STM32Cube LL恰好避免了这样的问题。 LL能高效的原因 简单总结一下原因: 巧妙运用C语言静态、内联函数直接操作寄存器 。 当然,这是其中重要的原因,还有一些其它原因,这里暂不描述。 你会在LL库.h文件中发现大量类似,静态、内联函数直接读写寄存器的函数。 比如读写IO口: __STATIC_
[单片机]
<font color='red'>STM32</font> LL库为什么比HAL库高效呢?
stm32学习之NOR flash和NAND flash区别,RAM 和ROM区别
ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写。ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,典型的RAM就是计算机的内存。 RAM 有两大类,一种称为静态RAM(Static RAM/SRAM),SRAM速度非常快,是目前读写最快的存储设备了,但是它也非常昂贵,所以只在要求很苛刻的地方使用,譬如CPU的一级缓冲,二级缓 冲。另一种称为动态RAM(Dynamic RAM/DRAM),DRAM保留数据的时间很短,速度也比SRAM慢,不过它还是比任何的ROM都要快,但从价格上来说DRAM相比SRAM要便宜很
[单片机]
STM32之中断管理
关于STM32的中断,相信大家玩过单片机的朋友就知道,中断是MCU的一大优点,使MUC工作能够分清事情的”轻重缓急“ ,从而达到处理事情井井有条; 今天就讲解下STM32-Cortex-M3内核的中断管理机制,其他处理器的也类似;M3中F103系列的有60个可屏蔽的中断和16个内核级别的中断; 大家知道,操作一款MCU 其实实质就是操作的寄存器,而寄存器有机的结合起来就实现了特定的功能;中断系统也不例外,下面来认识一下中断系统中的几个重要的寄存器; 1. ISER (Interrupt Set-Enable Registers),就是中断使能寄存器组,这个数组有8个成员,每个成员是32位的寄存器;写1有效,写0无效;
[单片机]
在MDK调试STM32出现“could not stop cortex-m device”解决办法
错误如http://www.amobbs.com/forum.php?mod=viewthread&tid=4075329 错误图片如下: 我的解决办法: 发现RESET一直在1V附近,将RESET处的下拉电容换掉后第一个错误没有,但是跳出下面的错误:No Cortex-M Device found in JTAG chain。 解决办法:发现JTAG线没插上,插上就好了。 http://no001.blog.51cto.com/1142339/857117 网上的解决办法: 1 我遇到这个问题的原因是Boot1没接地,所以可以考虑下是否是硬件的原因 2 如果MCU出于reset状态,也会出现这种情
[单片机]
在MDK调试<font color='red'>STM32</font>出现“could not stop cortex-m device”解决办法
STM32进入HardFault_Handler的调试方法
在编写STM32程序代码时由于自己的粗心会发现有时候程序跑着跑着就进入了 HardFault_Handler中断,按照经验来说进入HardFault_Handler故障的原因主要有两个方面: 1:内存溢出或则访问越界。 2:堆栈溢出。 发生异常后我们可以首先查看LR寄存器的值,确认当前使用的堆栈是MSP还是PSP,然后找到相对应的堆栈指针,并在内存中查看相对应堆栈的内容,内核将R0~R3,R12,LR,PC,XPRS寄存器依次入栈,其中LR即为发生异常前PC将要执行的下一条指令地址。那么Cortex-M3 内核HardFault错误调试定位方法有: 方法1 如何精确定位出问题代码的所在位置: 以访问越界为例:(对STM32F1
[单片机]
<font color='red'>STM32</font>进入HardFault_Handler的调试方法
关于stm32的堆、栈、内存管理以及外扩ram的使用总结
刚接手STM32时,编写一个空工程,BUILD后, Program Size: Code=340 RO-data=252 RW-data=0 ZI-data=1632 程序已用了1600多的RAM,要是在51单片机上,会心疼死了,这1600多的RAM跑哪儿去了, 分析map,你会发现是堆和栈占用的,在startup_stm32f10x_md.s文件中,它的前面几行就有以上定义,这下该明白了吧。 Stack_Size EQU 0x00000400 Heap_Size EQU 0x00000200 对于一个C语言程序而言,内存空间主要由五个部分组成:代码段(.text)、数据段(.data)、静态区(.
[单片机]
STM32之旅1——LED
学习了51单片机后,就要接触到更高级一点的单片机了,比如STM32,ST也有很多款单片机,现在用比较基础的学习——STM32F103RCT6。 LED驱动 hal库的使用比较简单,可以直接在STM32CubeMX中分配好IO之后一键生成工程,为了提高程序的可读性,自己写一个头文件,在调用过程中会比较简单。 drv_led.h: #ifndef __DRV_LED_H #define __DRV_LED_H #define LED1_PIN GPIO_PIN_8 #define LED1_PORT GPIOA #define LED2_PIN GPIO_PIN_2 #define LED2_PORT G
[单片机]
STM32--如何产生8路PWM波
实验描述:PA0,PA1,PA2,PA3,PA8,PA9,PA10,PA11输出不同占空比的PWM波 程序清单: #include PWM.H #include stm32f10x.h void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //启动GPIO RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //启动AFIO RCC_APB2PeriphClockCmd(RCC_A
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved