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.

[参考译文] TM4C123GH6PM:温度读数问题

Guru**** 2454880 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/625723/tm4c123gh6pm-temperature-reading-problem

器件型号:TM4C123GH6PM
主题中讨论的其他器件:TM4C123

大家好、我想读取内部和外部温度传感器、并使用 UART 进行显示。 我使用了 TIvAware 提供的示例、并进行了一些更改。 问题是温度值持续变化。 我的意思是温度值是22-24-23-24-22-20-24。 我认为室温可能在两个值之间的边界上、但有时会从20跳到24跳变、外部温度的行为也相同。 这是我的定制板、我使用的是 IAR。 我共享 PuTTY 终端的代码和屏幕截图。 可能是什么问题。  

谢谢

编辑:当我加热外部温度时、温度值 同时增加。 它显示了40-42-41-44。  

//
//
// uart_echo.c -在
//中从 UART 读取数据并向 UART 写入数据的示例 中断驱动方式。
//
//版权所有(c) 2012-2013 Texas Instruments Incorporated。 保留所有权利。
//软件许可协议
//
//德州仪器(TI)提供此软件仅供
和//仅供 TI 的微控制器产品使用。 软件归
// TI 和/或其供应商所有,并受适用的版权
//法律保护。 您不能将此软件与"病毒"开源
//软件组合在一起以形成更大的程序。
//
//此软件按“原样”提供,且存在所有故障。
//对于

本软件,不作任何明示、暗示或法定的保证,包括但不限于对适销性和适用性的暗示保证//特定用途。 在任何
//情况下、TI 不对任何
原因造成的特殊、意外或必然//损害负责。
//
//这是 EK-TM4C123GXL 固件包修订版1.0的一部分。
////
*****************

#include 
#include 
#include "inc/hw_ints.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"


#include "driverlib/driverlib"#include "driverlib/driver.h"#include "driverlib"#driverlib.driverlib.driverlib"#include "driverlib.driver.h"#include "driverlib.mdio.intrl.ine.h.include"#include "driverlib"#include "driverlib"#driverlib/driverlib"#driverlib.us.us.intrl"#include "driverlib"#driverlib.us.mdio.md.ide"#include "driverlib"#include







//
//! \addtogroup example_list
//! 

UART 回波(UART_ECHO)

//! //! 此示例应用利用 UART 来回显文本。 第一个 UART //! (连接到评估板上的 USB 调试虚拟串行端口) //! 将配置为115、200波特、8-n-1模式。 所有字符均接收于 //! UART 被发送回 UART。 //// ***************** // // //如果驱动程序库遇到错误,则调用的错误例程。 //// ***************** #ifdef debug void __error__(char *pcFilename、uint32_t ui32Line) { #endif void GPIOPinUnlockGPIO (uint32_t ui32Port、uint8_t ui8pins){ HWREG (ui32Port + GPIO_lock)= GPIO_lock_key; //解锁端口 HWREG (ui32Port + GPIO_CR)|= ui8引脚; //解锁引脚 HWREG (ui32Port + GPIO_LOCK)= 0; //锁定端口 } //********* // //向 UART 发送字符串。 //// ***************** void UARTSend (const uint8_t * pui8Buffer、uint32_t ui32Count) { // 循环、同时有更多字符要发送。 // while (ui32Count---) { // //将下一个字符写入 UART。 // UARTCharPutNonBlocking (UART2_base、* pui8Buffer++); } //********* // // UART 中断处理程序。 //// ***************** void UARTIntHandler (void) { uint32_t ui32Status; // //获取中断状态。 // ui32Status = UARTIntStatus (UART2_base、true); // //清除已发出的中断。 // UARTIntClear (UART2_base、ui32Status); // //循环,当接收 FIFO 中有字符时。 // while (UARTCharsAvail (UART2_base) ){ // //从 UART 读取下一个字符并将其写回 UART。 // UARTCharPutNonBlocking (UART2_base、UARTCharGetNonBlocking (UART2_base)); SysCtlDelay (SysCtlClockGet ()/(1000 * 3)); } void uart2_init (){ //初始化 UART2 //设置发送和接收中断 //0。 UART2和端口 D 的初始化时钟 SysCtlPeripheralEnable (SYSCTL_Periph_UART2); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD); //给时钟启动 SysCtlDelay (10)的时间; //将 AFSEL 设置为 D6、D7并解锁 D7 GPIOPinUnlockGPIO (GPIO_PORTD_base、GPIO_PIN_7); GPIOPinConfigure (GPIO_PD6_U2RX); GPIOPinConfigure (GPIO_PD7_U2TX); GPIOTypeUART (GPIO_PORTD_base、 GPIO_PIN_6 | GPIO_PIN_7); //设置波特率、TXE/RXE、stp2 (清除然后和 fen)和 wlen (8位_) UARTConfigSetExpClk (UART2_base、SysCtlClockGet ()、9600、(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE); // UARTFIFOEnable (UART2_base); // UARTTxIntModeSet (UART0_BASE、UART_TXINT_MODE_FIFO); // UARTFIFOLevelSet (UART2_base、UART_FIFO_TX1_8、UART_FIFO_RX1_8);//将 Rx 设置为用两个字节触发 //启用全局 NVIC 中断 IntEnable (INT_UART2); //启用本地中断 //UARTIntEnable (UART2_base、(UART_INT_TX | UART_INT_RX);//启用 Tx 和 Rx int UARTIntEnable (UART2_base、UART_RX | UART_INT_Disable); UART2_UART2_INT_INT_START (UART2_UART2_BASE) ;/ UART2_UART2_UART2_UART2_UART2_UART2_INT_INT_START) UARTFIFODisable (UART2_base); } void ADC0_init(){ // //必须启用 ADC0外设才能使用。 // SysCtlPeripheralEnable (SYSCTL_Periph_ADC0); ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE); SysCtlDelay (3); GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3); // //使用处理器信号触发器启用采样序列3。 当 处理器发送单次采样以启动 //转换时,序列3 //将执行单次采样。 每个 ADC 模块有4个可编程序列、序列0 //至序列3。 此示例任意使用序列3。 // ADCSequenceConfigure (ADC0_BASE、2、ADC_TRIGGER_PROCESSOR、0); // //配置序列3上的步骤0。 对温度传感器进行采样 //(ADC_CTL_TS)并将中断标志(ADC_CTL_IE)配置为在 采样完成时设置//。 告诉 ADC 逻辑、这是 序列3上的最后一次//转换(ADC_CTL_END)。 序列3只有一 个//可编程步长。 序列1和2有4个步长、序列0有 // 8个可编程步长。 由于我们仅使用 //序列3执行单次转换、因此我们将仅配置步骤0。 有关 // ADC 序列和步骤的更多信息、请参考数据表。 // ADCSequenceStepConfigure (ADC0_BASE、2、0、ADC_CTL_CH0); ADCSequenceStepConfigure (ADC0_BASE、 2、1、ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END); //ADCHardwareOversampleConfigure (ADC0_BASE、64); // //由于采样序列3现在已配置,因此必须启用它。 // ADCSequenceEnable (ADC0_BASE、2); // //清除中断状态标志。 这样做是为了确保 //中断标志在我们采样前被清除。 // ADCIntClear (ADC0_BASE、2); } //********* // //此示例演示了如何将一串数据发送到 UART。 //// ***************** int main (void) { // //为中断处理程序启用怠惰堆栈。 这允许 在中断处理程序中使用浮点//指令、但代价 是//额外使用栈。 // FPUEnable(); FPULazyStackingEnable(); // //将时钟设置为直接从晶体运行。 // SysCtlClockSet (SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHz); uart2_init(); ADC0_init(); // //循环通过 UART 永久回显数据。 // IntMasterEnable(); // UARTSend ((uint8_t *)"\033[2JEnter 文本:"、16); UARTStdioConfig (2、9600、8000000); // SysCtlDelay (SysCtlClockGet ()/(1000 * 3)); // // // UARTprintf ("oldu"); uint32_t ADCValues[2]; // //这些变量用于存储 //摄氏和华氏温度转换。 // uint32_t TempValueC; uint32_t TempValueC_EXT; uint32_t TempValueF; // //在控制台上显示设置。 // UARTprintf ("ADC ->\n"); UARTprintf ("类型:内部温度传感器\n"); UARTprintf ("样片:1\n"); UARTprintf ("更新速率:250ms\n"); UARTprintf ("输入引脚:内部温度传感器\n"\}); while (1) { ADCProcessorTrigger (ADC0_BASE、2); // //等待转换完成。 // while (!ADCIntStatus (ADC0_BASE、2、false)) { } // //清除 ADC 中断标志。 // ADCIntClear (ADC0_BASE、2); // //读取 ADC 值。 // ADCSequenceDataGet (ADC0_BASE、2、&ADCValues[0]); // //使用数据表中提供的非校准转换。 我在中间使用浮点数 //数学,但是你可以用10倍的幂和最后的除法运算 //确保最后分频以避免压降。 // TempValueC =(uint32_t)(147.5 -(((75.0*3.3 *(float) ADCValues[1]))/ 4096.0); TempValueC_Ext =(uint32_t)(((((1000*3.3*(float) ADCValues[0])/4096.0)-500)/10); // //获取华氏值。 确保最后分频以避免压降。 // TempValueF =((TempValueC * 9)+ 160)/5; // //在控制台上显示温度值。 // UARTprintf ("温度=%3D*C 或%3D*F 且 TempValueC_Ext =%d\r"、TempValueC、 TempValueF、TempValueC_Ext); // //此函数提供了生成恒定长度的方法 //延迟。 函数延迟(以周期为单位)= 3 *参数。 延迟 //任意地250ms。 // SysCtlDelay (8000000000 / 12); } }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Furkan Erman"]问题是温度值持续变化。

    问题可能与您的"期望"有关、而不是与这些(略有)变化的结果有关?   内部温度传感器以超高精度而闻名(毕竟它是"自由"的)-并且会根据电压、器件老化、附近的噪声源(对电源轨的印象尤其深刻) 和(可能的)此类测量期间的电流而变化。   

    您编写的定制板-请注意、您的 MCU 具有单独的 VDDA 和 GNDA 连接对-这是为了从 MCU 的模拟部分获得最佳(潜在)性能。   您是否单独(从 VDD 和 GND)提供了这些引脚 、并通过增强型、超稳定的无噪声电压提供了这些引脚?   (这是从 MCU 获得最佳模拟性能所必需的。)

    当通过 MCU 的 ADC 正确读取高度稳定的输入电压时、将"3个最低有效 ADC 位"更改为"扑动"是"正常"的。  假设一个12位 ADC 包含4096个"计数"-因此8个计数的"不确定性"为1%的1/5 (40个 ADC 计数)。

    该供应商和其他公司生产更精确的独立 ADC -某些成本比您的 MCU "高很多倍"、并且在需要更快、更精确的模拟测量时选择...

    掌握了这些知识-您的"问题"可能是"轻微的"-并且您的"期望值已调整"、以接受 MCU"无法"提供(无目的)一致的模拟读数...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 CB1_MOBILE、

    由于在您的回复后经过了许多时间、我认为其他供应商的 MCU 也经常发生这种情况。 有些人会找到基于软件的解决方案、例如获取10个样本、然后删除最高和最低值、然后再重新管理8个值。 tm4c123是否具有内置系统来实现该目的?

    谢谢
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 USER="Furkan Erman">有些人会找到基于软件的解决方案、例如获取10个样本、然后删除最高和最低值、然后再重新管理8个值。 tm4c123是否具有内置系统来实现这一目的?[/quotes]TivaWare 通过对来自同一模拟输入的多个样本求平均值来支持硬件或软件"过采样"。 有关   详细信息,请在 TivaWareTm外设驱动程序库用户指南的模数转换器(ADC)部分中搜索“过采样”。

    在执行平均值之前、我看不到 TivaWare 支持的说明来放弃最高和最低值、但大概可以在您自己的软件中实现这些值。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 USER="CB1_MOBILE]问题是否与您的"期望"有关-而不是与这些(略有不同)的结果有关?  [/报价]

    比如

    Robert