This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

tm4c123 内部温度测量问题



产品用了TM4C123内部温度传感器用来测量温度,根据参考程序写的代码,代码如下,目前测下来的问题是测量出来的温度波动范围很大,每隔一秒采样一次,取了平均值后范围在20度到30度之间,有个别几次能够到80度以上,甚至能采集到147度。所以想请教一下可能是什么问题,是代码问题?亦或是电源质量不好影响参考电压导致采样不准?或者是计算温度时浮点计算溢出出问题了?我用的ucosIII所以没有打开浮点

void init_adc0(void)

{

   SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
   SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_ADC0);
   SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);

   ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
   ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END);

}

void get_tempurate(void)

{

    INT32U pui32ADC0Value[4];
    INT32U ui32TempValueC = 0;

   

     ADCSequenceEnable(ADC0_BASE, 3);

    ADCIntClear(ADC0_BASE, 3);
    ADCProcessorTrigger(ADC0_BASE, 3);
    while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
    }
    ADCIntClear(ADC0_BASE, 3);
    ADCSequenceDataGet(ADC0_BASE, 3, &pui32ADC0Value[0]);

    ADCIntClear(ADC0_BASE, 3); 
    ADCProcessorTrigger(ADC0_BASE, 3);
    while(!ADCIntStatus(ADC0_BASE, 3, false))
   {
   }
   ADCIntClear(ADC0_BASE, 3);
   ADCSequenceDataGet(ADC0_BASE, 3, &pui32ADC0Value[1]);


   ADCIntClear(ADC0_BASE, 3); 
   ADCProcessorTrigger(ADC0_BASE, 3);
   while(!ADCIntStatus(ADC0_BASE, 3, false))
  {
  }
   ADCIntClear(ADC0_BASE, 3);
   ADCSequenceDataGet(ADC0_BASE, 3, &pui32ADC0Value[2]);


    ADCIntClear(ADC0_BASE, 3);
    ADCProcessorTrigger(ADC0_BASE, 3);
   while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
   }
   ADCIntClear(ADC0_BASE, 3);
   ADCSequenceDataGet(ADC0_BASE, 3, &pui32ADC0Value[3]);


    ADCSequenceDisable(ADC0_BASE, 3);

    ui32TempValueC = (pui32ADC0Value[0] + pui32ADC0Value[1] + pui32ADC0Value[2] + pui32ADC0Value[3]) / 4;

     ui32TempValueC = (uint32_t)(147.5 - ((75.0*3.3 *(float)ui32TempValueC)) / 4096.0);

}

  • 还是使用不当的问题,看看官方的例程,实际测试没有太大波动

    //                        sensor.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // 
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    //*****************************************************************************
    //
    //! \addtogroup adc_examples_list
    //! <h1>ADC Temperature Sensor (temperature_sensor)</h1>
    //!
    //! This example shows how to setup ADC0 to read the internal temperature
    //! sensor.
    //!
    //! NOTE: The internal temperature sensor is not calibrated.  This example
    //! just takes the raw temperature sensor sample and converts it using the
    //! equation found in the LM3S9B96 datasheet.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - ADC0 peripheral
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of the
    //! ADC.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - None.
    //
    //*****************************************************************************
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    int main(void)
    {
        uint32_t ui32ADC0Value[4];
        volatile uint32_t ui32TempAvg;
        volatile uint32_t ui32TempValueC;
        volatile uint32_t ui32TempValueF;
        SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
        InitConsole();
        //
        // Display the setup on the console.
        //
        UARTprintf("ADC ->\n");
        UARTprintf("  Type: Internal Temperature Sensor\n");
        UARTprintf("  Samples: One\n");
        UARTprintf("  Update Rate: 250ms\n");
        UARTprintf("  Input Pin: Internal temperature sensor\n\n");
        //5分频,使用PLL,外部晶振16M,system时钟源选择 main osc。系统时钟40MHZ
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        //使能ADC0
        ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
        //We want to use ADC0, sample sequencer 1,
        //we want the processor to trigger the sequence and we want to use the highest priority
        ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_TS);
        ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_TS);
        ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_TS);
        //Configure steps 0 - 2 on sequencer 1 to sample the temperature sensor (ADC_CTL_TS).
        ADCSequenceStepConfigure(ADC0_BASE,1,3,ADC_CTL_TS|ADC_CTL_IE|ADC_CTL_END);
        //Sample the temperature sensor (ADC_CTL_TS) and configure the interrupt flag (ADC_CTL_IE)
        //Tell the ADC logic that this is the last conversion on sequencer1 (ADC_CTL_END).
        ADCSequenceEnable(ADC0_BASE, 1);
        //enable ADC sequencer 1
        while(1)
        {
           ADCIntClear(ADC0_BASE, 1);
           ADCProcessorTrigger(ADC0_BASE, 1);
           //trigger the ADC conversion with software
           while(!ADCIntStatus(ADC0_BASE, 1, false))
           {
           }
           //wait for the conversion to complete
           ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
           ui32TempAvg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2] + ui32ADC0Value[3] + 2)/4;
           //Since 2/4 = 1/2 = 0.5, 1.5 will be rounded to 2.0 with
           //the addition of 0.5. In the case of 1.0, when 0.5 is added to yield 1.5, this will be rounded
           //back down to 1.0 due to the rules of integer math.即四舍五入
           ui32TempValueC = (1475 - ((2475 * ui32TempAvg)) / 4096)/10;
           //TEMP = 147.5 – ((75 * (VREFP – VREFN) * ADCVALUE) / 4096)
           //VREFP – VREFN=3.3V
           ui32TempValueF = ((ui32TempValueC * 9) + 160) / 5;
           UARTprintf("Temperature = %d*C or %d*F\r\n", ui32TempValueC,
                      ui32TempValueF);
           //F = ( C * 9)/5 +32
        }
    }
    
    
  • 我的代码基本上和官方例程差不多 主要区别就在于 主时钟上 我的mpu主频时钟采用的是外面时钟 频率为4m 没有时用PLL,

    官方例子用了pll而且频率比我4m高很多,不知道这个会不会影响到adc采样精度?

  • PLL时钟参考频率必须在范围5 MHz 到 25 MHz 之间,你的这个4M的频率能倍频起来才怪了。

  • 我没有使用PLL 我是外部16m晶振分频到4m

    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);    //clk = 4MZ

  • 你试着主频配置为通用的80Mhz试试,老实说,降频使用,还真没试过。

  • 请问这个程序适合TM4C1294板子吗

  • 大同小异吧,可能某个函数会有出入的地方,对照着库函数修改下就好了。

  • 嗯嗯,谢谢,小白还有一个问题, 采样序列的采样数是8,这8具体是什么意思呢,是同时对8个通道采样?还是依次对1个通道进行8次采样?看了论坛上的一些说法,感觉还是不太明白,能不能赐教一下?

  • 你指的是哪个函数的哪个参数呢,这个8应该是adc的通道

  • 采样序列发生器0(Sample Sequencer0)的采样数是8,就是ADCSequenceStepConfigure函数的ui32Step参数,是同时对8个通道采样?还是依次对1个通道进行8次采样?非常感谢!

  • 請問一下高手們,何謂使用不當?

  • 实际测试了下,我的理解是,采样序列发生器0可以采样8次,这个8是进行第八次采样,是对    ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_TS);

    这个函数第四个参数选择的通道进行采样,读取采样序列发生器0的第八次采样值,是这个通道的采样值。