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

基于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 发布时间:2020-9-23 14:39

举报

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

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

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