急!STM32F103温度传感器使用问题

ahongye   2007-12-6 14:14 楼主
1.如何计算温度。例如:Channel16的采样值为1980,则温度 = ?
2.我在测试时的采样值如下图所示,左边是刚开始运行时的采样值,
  右边是运行1分钟以后的采样值,数据差为450左右。高手可否帮我分析下原因。
  另:发下我的测试源程序。

/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : main.c
* Author             : MCD Application Team
* Date First Issued  : 05/21/2007
* Description        : Main program body
********************************************************************************
* History:
* 05/21/2007: V0.3
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADC1_DR_Address    ((u32)0x4001244C)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/ 
u16 ADC_ConvertedValue[128];  
ErrorStatus HSEStartUpStatus;

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void NVIC_Configuration(void);
void DMA1_Configuration(void);
void ADC_Coniguration(void);

/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name  : main
* Description    : Main program
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();

  /* DMA1 Configuration */
  DMA1_Configuration();

  /* ADC1 Configuration */
  ADC_Coniguration();

  /* NVIC configuration */
  NVIC_Configuration(); 

  while(1)
  {
  }    
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{   
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
  
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);
    
    /* ADCCLK = PCLK2/8 = 9MHz */
    RCC_ADCCLKConfig(RCC_PCLK2_Div8); 

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }

  /* TIM1, GPIOA and GPIOB clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);
}

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures Vector Table base location.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NVIC_Configuration(void)
{   
#ifdef  VECT_TAB_RAM  
  /* Set the Vector Table base location at 0x20000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif 
}

/*******************************************************************************
* Function Name  : ADC_Coniguration
* Description    : None
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void ADC_Coniguration(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    /* ADC1 configuration ----------------------------------------------------*/
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    /* ADC1 regular channel group configuration */
    ADC_RegularChannelConfig(ADC1, ADC_Channel_16,1, ADC_SampleTime_239Cycles5);    

    /* Enable ADC1 DMA */
    ADC_DMACmd(ADC1, ENABLE);

    /* Enable ADC1 */  
    ADC_Cmd(ADC1, ENABLE);
    ADC_TempSensorVrefintCmd(ENABLE);     
    
    /* Enable ADC1 reset calibaration register */   
    ADC_ResetCalibration(ADC1);
    /* Check the end of ADC1 reset calibration register */
    while(ADC_GetResetCalibrationStatus(ADC1));

    /* Start ADC1 calibaration */
    ADC_StartCalibration(ADC1);
    /* Check the end of ADC1 calibration */
    while(ADC_GetCalibrationStatus(ADC1));

    /* Start ADC1 Software Conversion */ 
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

/*******************************************************************************
* Function Name  : DMA_Configuration
* Description    : None
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void DMA1_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;    
    DMA_DeInit(DMA_Channel1);
    DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = 128;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA_Channel1, &DMA_InitStructure);

    /* Enable DMA Channel1 Transfer Complete interrupt */
    //DMA_ITConfig(DMA_Channel1, DMA_IT_TC, ENABLE); 
    
    /* Enable DMA channel1 */
    DMA_Cmd(DMA_Channel1, ENABLE);
    
}

/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/

回复评论 (21)

在线等高手来

                                 在线等待问题解决
点赞  2007-12-6 14:56

STM32F103温度传感器使用问题,如何计算温度?

请参考STM32技术参考手册,第366页(最新版下载地址: http://www.st.com/stonline/products/literature/rm/13902.pdf)

Reading the temperature
To use the sensor:
1. Select the ADCx_IN16 input channel.
2. Select a sample time greater than 2.2 μs
3. Set the TSVREFE bit in the ADC control register 2 (ADC_CR2) to wake up the temperature sensor from power down mode.
4. Start the ADC conversion by setting the ADON bit (or by external trigger).
5. Read the resulting VSENSE data in the ADC data register
6. Obtain the temperature using the following formula:
Temperature (in °C) = {(V25 - VSENSE) / Avg_Slope} + 25.
Where,
V25 = VSENSE value for 25° C and
Avg_Slope = Average Slope for curve between Temperature vs. VSENSE (given in mV/° C or μV/ °C).
Refer to the Electrical characteristics section for the actual values of V25 and Avg_Slope.

Note: The sensor has a startup time after waking from power down mode before it can output VSENSE at the correct level. The ADC also has a startup time after power-on, so to minimize the delay, the ADON and TSVREFE bits should be set at the same time. 
点赞  2007-12-6 15:24

继续:STM32F103温度传感器使用问题,如何计算温度?

上述V25和Avg_Slope的值可在STM32F103xx的数据手册中找到,(最新版下载地址:http://www.st.com/stonline/products/literature/ds/13587.pdf),在第67页的表47中:
V25 = 1.42V
Avg_Slope = 4.35mV/°C


至于采样值的变化是否是因为芯片内部温度的提高而造成,我没有算过你的读数,你可以算算看。
点赞  2007-12-6 15:34

看我的计算公式对不对

查了手册,还是不大会计算。例如采样值=1980,那计算公式是不是这样滴:
温度 = (1.42 - (1980/4096)*3)/0.00435 + 25 ~= 18.05 (°C)
手册中V25 = 1.42V
      Avg_Slope = 4.35mv/(°C)
点赞  2007-12-6 15:36

参考电压

                                 忘了说了,我的ADC参考电压为3V。所示电压 = (1980/4096)*3。
点赞  2007-12-6 15:39

RE:至于采样值的变化是否是因为芯片内部温度的提高而造成

根据公式,采样值越大,则温度下降。我根据公式计算得,刚开始温度为18左右,后来慢慢变到7,8度。如果说温度慢慢升高,可以理解为片内温度提高了,
但是温度却是慢慢下降了,奇怪!
如果上面的程序没有问题,那是否是其它问题?
点赞  2007-12-6 15:42

帮顶

                                  
点赞  2007-12-6 16:05

to:LS

                                 LS滴谢谢啊。有谁使用过内置的温度传感器采温度的,出来指点一二。
点赞  2007-12-6 16:18

呵呵,LZ搞到一个电子冰箱

开个小玩笑。

你的计算公式没有大错,只是应该用4095作为分母,而不是4096。

至于你的读数值变得越来越大,这是不正常的,我暂时解释不了。

你能不能试试在读取温度传感器结果的同时,对一个外部电压源进行采样,看看是否在外部电压源电压不变的情况下,读数也会随着时间变化。这个实验是为了确定是否因为电路中的某些因素导致采样不准,还是程序因为有误,还是因为芯片内部的问题。
点赞  2007-12-6 17:42

关于channel17

                                 顺便想问下Channel17采样的值是什么?参考手册中说它连接的是Vrefint,那它是不是参考电压的采样值。如果是的话,只有它保持在稳定范围我们的采样才正确?
点赞  2007-12-7 08:32

回11楼:关于channel17

请看另一帖中的回答:STM32 AD口问题

抄录如下:
问:STM32模拟口有两个内部信号口,一是温度信号,二是VREFINT。
VREFINT多高电压的信号??实际采集的时候对应的数字量是什么含义?

答:在最新版本的数据手册中,VREFINT的最小、典型和最大电压分别是1.16V、1.20V和1.26V。
当你的应用要求不高时,可以把它当成参考电压,对你的ADC转换进行修正。


最新数据手册的下载地址为:http://www.st.com/stonline/products/literature/ds/13587.pdf
点赞  2007-12-7 10:11

同样关注,继续顶

                                  
点赞  2007-12-7 15:44

VREFINT可以看成是一个1.20V的基准电压

作为ADC转换的基准。

例如,VREFINT的转换结果为0x100,则转换结果为0x200所对应的电压是:
  1.20V * 0x200/0x100 = 2.40V

我上面已经说了“当你的应用要求不高时,可以把它当成参考电压”,如果要求高,就要使用自己更高精度的基准电压。
点赞  2007-12-7 18:10

tongyi

                                 搂主的计算方法完全正确
点赞  2007-12-7 23:44

有没有例子?

                                 不知道ST有没有使用温度传感器的一个完整例子?
点赞  2007-12-14 14:48

帮顶

                                 顶
点赞  2007-12-14 15:41

STM3210B-EVAL_Demo程序没有使用自带的TSensor

哈哈,看了一下STM3210B-EVAL_Demo程序,居然没有使用STM32内部TSensor,
而是用STLM75。嘿嘿,看来效果不怎么好。
点赞  2007-12-18 13:47

本贴小结

经过实验和讨论,最后结论是:
以上Channel16不正常采样是因为VDDA接的是3V的电压,如果接3.3V,则采样正确,采样误差在-+3之间。还算可以。

不知道为什么3V供电不行?
点赞  2007-12-18 16:43

没必要追究4096和4095的问题,应用中4096左移速度最快~~~

                                  
点赞  2007-12-18 21:05
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复