你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
STMCU-管管 发布时间:2020-9-23 14:39
内部温度传感器简介测量的温度位置

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


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

1_meitu_3.jpg


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


2_meitu_4.jpg


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


3_meitu_5.jpg


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



内部传感器配置注意事项

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

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



内部温度传感器配置流程

所属函数位置

执行步骤

ADCx的初始化函数

使能相应总线上(APB1或者APB2)ADCx与GPIOx的外设时钟

配置GPIOx口中ADCx对应的引脚为模拟输入模式(ADC外设对应的GPIO模式)

将ADCx复位为缺省值(就是将ADCx的所有设过的属性全部重设为默认值)

设置ADCx时钟分频

将ADCx的校准寄存器恢复为默认值(此时应用对应的标志位来判断此步过程是否完成,如果完成再执行下一步)

将ADCx的校准寄存器初始化,开始校准(此时应用对应的标志位来判断此步过程是否完成,如果完成再执行下一步)

使能ADC1_CH16对应的内部温度传感器

使能ADCx外设

ADCx_CHy通道数值读取函数

配置ADCx_CHy(ADCx对应的y通道)的转换序号与转换周期

启动ADCx_CHy继续转换(此时应用对应标志位判断ADCx外设所有通道是否转换完成)

读取ADCx_CHy通道的数字量的值

ADCx_CHy通道读取的数据的后期处理函数

对n次读取的数据进行取平均值处理

温度与电压数字量之间的转换函数

用温度与电压数字量之间的对应关系进行转换


内部温度传感器实验代码解析ADC初始化代码


  1. void ADC_InitConfig()  
  2. {  
  3.     ADC_InitTypeDef ADC_InitStructure;  
  4.       
  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);  
  6.       
  7.     ADC_DeInit(ADC1);  
  8.     RCC_ADCCLKConfig(RCC_PCLK2_Div6);  
  9.       
  10.     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  
  11.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;  
  12.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  
  13.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  
  14.     ADC_InitStructure.ADC_NbrOfChannel = 1; // 定义规则通道的长度  
  15.     ADC_InitStructure.ADC_ScanConvMode = DISABLE;  
  16.     ADC_Init(ADC1,&ADC_InitStructure);  
  17.       
  18.     ADC_TempSensorVrefintCmd(ENABLE); // 使能内部温度传感器  
  19.       
  20.     ADC_Cmd(ADC1,ENABLE); // 使能ADC1  
  21.       
  22.     ADC_ResetCalibration(ADC1); // 开始ADC1的校准寄存器复位  
  23.     while(ADC_GetResetCalibrationStatus(ADC1));  
  24.       
  25.     ADC_StartCalibration(ADC1); // 开始ADC1的自动校准功能  
  26.     while(ADC_GetCalibrationStatus(ADC1));  
  27.       
  28.     delay_init();  
  29. }  
复制代码

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

4_meitu_6.jpg



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



  1. ADC_ResetCalibration(ADC1); // 开始ADC1的校准寄存器复位  
  2. while(ADC_GetResetCalibrationStatus(ADC1));  
  3.   
  4. ADC_StartCalibration(ADC1); // 开始ADC1的自动校准功能  
  5. while(ADC_GetCalibrationStatus(ADC1));
复制代码

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



  1. ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  
  2.   
  3. while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
复制代码



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

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

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


5_meitu_7.jpg



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


功能

状态

位标志

检验ADC校准功能复位状态(完成/进行中)

复位执行中

1(SET)

复位完成(复位指令执行完毕)

0(RESET)

检验执行ADC校准功能的状态(完成/进行中)

正在开始执行ADC校准功能

1(SET)

ADC校准功能执行完毕

0(RESET)


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

6_meitu_8.jpg

功能

状态

位标志

查看ADC转换是否结束

ADC转换结束

1(SET)

ADC转换完成

0(RESET)


DC转换函数


  1. u16 ADC_GetValue()  
  2. {     
  3.     ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5 );  //ADC1,ADC通道3,第一个转换,采样时间为239.5周期                     
  4.    
  5.     ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  
  6.       
  7.     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束  
  8.       
  9.     return ADC_GetConversionValue(ADC1);    //返回最近一次ADC1规则组的转换结果  
  10. }
复制代码


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


  1. ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  
  2.       
  3. while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
复制代码


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



多次读取取平均函数


  1. //获取通道ch的转换值  
  2. //取times次,然后平均  
  3. u16 T_Get_Adc_Average(u8 ch,u8 times)  
  4. {  
  5.     u32 temp_val=0;  
  6.     u8 t;  
  7.     for(t=0;t<times;t++)  
  8.     {  
  9.         temp_val+=T_Get_Adc(ch);  
  10.         delay_ms(5);  
  11.     }  
  12.     return temp_val/times;  
  13. }
复制代码


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



  1. //得到温度值  
  2. //返回值:温度值(扩大了100倍,单位:℃.)  
  3. short Get_Temprate(void)    //获取内部温度传感器温度值  
  4. {  
  5.     u32 adcx;  
  6.     short result;  
  7.     double temperate;  
  8.     adcx=T_Get_Adc_Average(ADC_Channel_16,20);  //读取通道16,20次取平均  
  9.     temperate=(float)adcx*(3.3/4096);       //电压值   
  10.     temperate=(1.43-temperate)/0.0043+25;   //转换为温度值      
  11.     result=temperate*=100;                  //扩大100倍.  
  12.     return result;  
  13. }
复制代码



总体代码示例TempSensor.c


  1. #include "TempSensor.h"  
  2. #include "stm32f10x.h"  
  3. #include "delay.h"  
  4.   
  5. void ADC_InitConfig()  
  6. {  
  7.     ADC_InitTypeDef ADC_InitStructure;  
  8.       
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);  
  10.       
  11.     ADC_DeInit(ADC1);  
  12.     RCC_ADCCLKConfig(RCC_PCLK2_Div6);  
  13.       
  14.     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  
  15.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;  
  16.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  
  17.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  
  18.     ADC_InitStructure.ADC_NbrOfChannel = 1; // 定义规则通道的长度  
  19.     ADC_InitStructure.ADC_ScanConvMode = DISABLE;  
  20.     ADC_Init(ADC1,&ADC_InitStructure);  
  21.       
  22.     ADC_TempSensorVrefintCmd(ENABLE); // 使能内部温度传感器  
  23.       
  24.     ADC_Cmd(ADC1,ENABLE); // 使能ADC1  
  25.       
  26.     ADC_ResetCalibration(ADC1); // 开始ADC1的校准寄存器复位  
  27.     while(ADC_GetResetCalibrationStatus(ADC1));  
  28.       
  29.     ADC_StartCalibration(ADC1); // 开始ADC1的自动校准功能  
  30.     while(ADC_GetCalibrationStatus(ADC1));  
  31.       
  32.     delay_init();  
  33. }  
  34.   
  35. u16 ADC_GetValue()  
  36. {     
  37.     ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5 );  //ADC1,ADC通道3,第一个转换,采样时间为239.5周期                     
  38.    
  39.     ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能  
  40.       
  41.     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束  
  42.       
  43.     return ADC_GetConversionValue(ADC1);    //返回最近一次ADC1规则组的转换结果  
  44. }  
  45.   
  46. u16 ADC_GetAverageValue()  
  47. {  
  48.     u8 i = 0;  
  49.     u16 temp = 0;  
  50.       
  51.     for(;i<5;i++)  
  52.     {  
  53.         temp += ADC_GetValue();  
  54.         delay_ms(5);  
  55.     }  
  56.     return temp/5;  
  57. }  
  58.   
  59. u16 DigitalValueConversion()  
  60. {  
  61.     float temp = ADC_GetAverageValue();  
  62.     return ((1.43-3.3*(temp/4096))/0.043+25)*100;  
  63. }
复制代码


TempSensor.h


  1. #ifndef _TEMPSENSOR_H  
  2. #define _TEMPSENSOR_H  
  3.   
  4. #include "sys.h"  
  5.   
  6. void ADC_InitConfig();  
  7. u16 ADC_GetValue();  
  8. u16 ADC_GetAverageValue();  
  9. u16 DigitalValueConversion();  
  10.   
  11. #endif
复制代码


Main.c

  1. #include "TempSensor.h"  
  2. #include "stm32f10x.h"  
  3. #include "usart.h"  
  4. #include "delay.h"  
  5. #include "lcd.h"  
  6.   
  7. int main()  
  8. {  
  9.     u16 temp = 0;  
  10.       
  11.     ADC_InitConfig();  
  12.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  
  13.     uart_init(115200);  
  14.     delay_init();  
  15.     LCD_Init();  
  16.     LCD_Clear(BLUE);  
  17.       
  18.     temp = DigitalValueConversion();  
  19.       
  20.     POINT_COLOR=RED;//设置字体为红色   
  21.     LCD_ShowString(30,50,200,16,16,"WarShip STM32");      
  22.     LCD_ShowString(30,70,200,16,16,"Temperature TEST");   
  23.     LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");  
  24.     LCD_ShowString(30,110,200,16,16,"2015/1/14");  
  25.     LCD_ShowString(30,140,200,16,16,"TEMPERATE: 00.00C");  
  26.       
  27.     while(1)  
  28.     {  
  29.         temp = DigitalValueConversion();  
  30.         LCD_ShowNum(30+11*8,140,temp/100,2,16);  
  31.         LCD_ShowNum(30+14*8,140,temp%100,2,16);  
  32.         delay_ms(150);  
  33.     }  
  34. }
复制代码


程序运行结果



7.gif
2_meitu_4.jpg
4_meitu_6.jpg
44.png
收藏 1 评论1 发布时间:2020-9-23 14:39

举报

1个回答
goyhuan 回答时间:2020-9-23 18:58:04
温度检测非常重要

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版