产品用了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);
}
xyz549040622:
还是使用不当的问题,看看官方的例程,实际测试没有太大波动
//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。系统时钟40MHZSysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);//使能ADC0ADCSequenceConfigure(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 priorityADCSequenceStepConfigure(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 1while(1){ADCIntClear(ADC0_BASE, 1);ADCProcessorTrigger(ADC0_BASE, 1);//trigger the ADC conversion with softwarewhile(!ADCIntStatus(ADC0_BASE, 1, false)){}//wait for the conversion to completeADCSequenceDataGet(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.3Vui32TempValueF = ((ui32TempValueC * 9) + 160) / 5;UARTprintf("Temperature = %d*C or %d*F\r\n", ui32TempValueC,ui32TempValueF);//F = ( C * 9)/5 +32} }
xyz549040622:
回复 alex c:
PLL时钟参考频率必须在范围5 MHz 到 25 MHz 之间,你的这个4M的频率能倍频起来才怪了。
alex c:
回复 xyz549040622:
我没有使用PLL 我是外部16m晶振分频到4m
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); //clk = 4MZ
xyz549040622:
回复 alex c:
你试着主频配置为通用的80Mhz试试,老实说,降频使用,还真没试过。
user5096354:
回复 xyz549040622:
请问这个程序适合TM4C1294板子吗
xyz549040622:
回复 user5096354:
大同小异吧,可能某个函数会有出入的地方,对照着库函数修改下就好了。
user5096354:
回复 xyz549040622:
嗯嗯,谢谢,小白还有一个问题, 采样序列的采样数是8,这8具体是什么意思呢,是同时对8个通道采样?还是依次对1个通道进行8次采样?看了论坛上的一些说法,感觉还是不太明白,能不能赐教一下?
xyz549040622:
回复 user5096354:
你指的是哪个函数的哪个参数呢,这个8应该是adc的通道
user5096354:
回复 xyz549040622:
采样序列发生器0(Sample Sequencer0)的采样数是8,就是ADCSequenceStepConfigure函数的ui32Step参数,是同时对8个通道采样?还是依次对1个通道进行8次采样?非常感谢!
TI中文支持网
