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.

[参考译文] MSP430FR2433:LPM3模式下的每日温度记录器

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1023929/msp430fr2433-daily-temperature-recorder-in-lpm3-mode

器件型号:MSP430FR2433
主题中讨论的其他器件:ENERGYTRACE

你好,福米特人。

我计划使用2节 AA 电池开发一个为期一年的实验原型。 我的目标是尽可能减小平均电流。 为此、我使用的是 Energy Trace (不是++)、因此我只能看到我的 LaunchPad 消耗了多少电流、或者消耗了多少功率和能量。 显然、出于开发目的、我每8秒记录一次温度。

我使用具有周期性唤醒功能的 LPM3模式、并在唤醒后激活内部温度传感器中断、以便可以执行单次读取并再次进入睡眠模式。 但是、我如何才能从该原型中获得更多能量? 我正在按照 ULP 的建议执行此操作:将 除 A12 (引脚1.2)以外的所有引脚转换为启用下拉的输入。 我将 ACLK 时钟用于 ADC 内核和计时器。 任何建议都值得赞赏。 我不要求任何人给我提供代码、不要让我出错、而是让我激活禁用代码等

我还在睡眠模式下花费100uA (LMP0规定为40uA、根据数据表、LPM3和 RTC 的花费1uA)、必须有一些外设处于活动状态、我需要在某个位置禁用更多外设。

//******************************************************************************
// In this example project, we are mostly sleeping and waking up every 8 seconds
// to measure temperature and record it to FRAM Information Memory Region.
//
// Memory Layout:
//   Byte 1: Session ID(To track how many times recording session is started)
//   Byte 2: How many recordings are saved in the session
//   Byte 3-..: Start to put recordings from byte 3 and onward. Use the counter
//     value in Byte 2 to understand how many readings are valid.
//******************************************************************************

#include <msp430.h> 

void FRAMWriteTemp(void);
void FRAMWriteSession(void);
void initGPIOUnusedInputPulldown(void);
void initADC(void);
void initACLKTimer(void);

// See device datasheet for TLV table memory mapping
#define CALADC_15V_30C  *((unsigned int *)0x1A1A)                 // Temperature Sensor Calibration-30 C
#define CALADC_15V_85C  *((unsigned int *)0x1A1C)                 // Temperature Sensor Calibration-85 C
#define FRAM_TEST_START 0x1800

volatile long temp = 0;
volatile long ADC_Value = 0;
unsigned int count = 0;

char *FRAM_start_ptr = (char*) FRAM_TEST_START;
char *FRAM_count_ptr = (char*) (FRAM_TEST_START + 1);
char *FRAM_write_ptr = (char*) (FRAM_TEST_START + 2);

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

    initGPIOUnusedInputPulldown();

    initACLKTimer();

    initADC();

    FRAMWriteSession();

    while (count < 250)
    {
        // The temperature (Temp, C)=
        temp = (ADC_Value - CALADC_15V_30C) * 55
                / (CALADC_15V_85C - CALADC_15V_30C) + 30;
        FRAMWriteTemp();

        __bis_SR_register(GIE | LPM3_bits); // Enable maskables and start Low Power Mode 0
    }

    return 0;
}

// Timer A0 interrupt service routine: Enable the ADC interrupts and start
// ADC conversion. Delay for some time to settle ref voltage setting.
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
    TA0CTL &= ~(TAIFG);         // Clear the interrupt
    ADCIE |= ADCIE0;            // Enable the conversion complete interrupt;
    ADCCTL0 |= ADCENC | ADCSC;  // Enable and start the conversion
    __delay_cycles(400);        // Delay for reference settling
}

// Record ADC Reading and disable ADC Interrupts. After this ISR, control goes
// to main loop
#pragma vector = ADC_VECTOR
__interrupt void ADC_ISR(void)
{
    __bic_SR_register_on_exit(LPM3_bits);
    ADC_Value = ADCMEM0;

    ADCIE &= ~ADCIE0;            // Disable the conversion complete interrupt;
}

void FRAMWriteTemp(void)
{
    SYSCFG0 = FRWPPW | PFWP; // This instruction removes DFWP, makes FRAM writeable
    *FRAM_count_ptr = (*FRAM_count_ptr) + 1;    // Update count field in FRAM
    *FRAM_write_ptr++ = temp;                   // Record the temperature
    SYSCFG0 = FRWPPW | PFWP | DFWP;     // This instruction locks FRAM again
    count++;                            // Update count
}

void FRAMWriteSession(void)
{
    SYSCFG0 = FRWPPW | PFWP;
    *FRAM_start_ptr = (*FRAM_start_ptr) + 1;
    *FRAM_count_ptr = 0;
    SYSCFG0 = FRWPPW | PFWP | DFWP;
}

void initGPIOUnusedInputPulldown(void)
{
    // Set all P1 pins except 1.2 to input with pulldown resistor
    P1SEL1 = P1SEL0 = 0;
    P1DIR = 0;
    P1OUT &= ~(BIT0 | BIT1 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    P1REN |= BIT0 | BIT1 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7;

    // Set all P2 pins to input with pulldown resistor
    P2SEL1 = P2SEL0 = 0;
    P2DIR = 0;
    P2OUT = 0;
    P2REN = 0xFF;

    // Set all P3 pins to input with pulldown resistor
    P3SEL1 = P3SEL0 = 0;
    P3DIR = 0;
    P3OUT = 0;
    P3REN = 0xFF;

    // Finally, set P1.2 to analog function
    P1SEL1 |= BIT2;
    P1SEL0 |= BIT2;             // Set 11 to both bits for Temp Sensor(A12 -> P1.2)

    PM5CTL0 &= ~LOCKLPM5;       // Turn on IO
}

// Configure Analog 12(Internal Temp Sensor)
void initADC(void)
{
    // Configure the ADC
    ADCCTL0 &= ~ADCSHT_15;      // Clear Conversion Clock Cycles
    ADCCTL0 |= ADCSHT_1;        // Set SHT to 8 Conversion Clock Cycles
    ADCCTL0 |= ADCON;           // Set ADC Core on

    ADCCTL1 |= ADCSSEL_1;       // Choose ACLK as Source Clock
    ADCCTL1 |= ADCSHP;          // Sample signal source = sampling timer
    //ADCCTL1 |= ADCDIV_7;      // ADC Clock Divider set to /8 to slow sampling

    ADCCTL2 |= ADCRES_1;        // 10-bit conversion results
    //ADCCTL2 |= ADCPDIV__64;   // ADC Pre Clock Divider set to /64 to slow sampling

    ADCMCTL0 |= ADCSREF_1 | ADCINCH_12;      // Set A2 as ADC Input

    // Configure reference
    PMMCTL0_H = PMMPW_H;                             // Unlock the PMM registers
    PMMCTL2 |= INTREFEN | TSENSOREN; // Enable internal reference and temperature sensor
}
// Intended to raise interrupt every 8 seconds to initiate temperature sensing
void initACLKTimer(void)
{
    TA0CTL |= TASSEL__ACLK;                     // Set clock source to ACLK
    TA0CTL |= TAIE;                             // Enable Timer A Interrupts
    TA0CTL |= TACLR;                            // Clear Timer A Register
    TA0CTL |= ID_2;                             // Slow Timer by 2^X (ID_X)
    //TA0EX0 |= TAIDEX_7;                       // Slow timer by Y+1 times (TAIDEX_Y)
    TA0CTL |= MC__CONTINUOUS;                   // Set continuous mode
}

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

    常见的嫌疑人:

    1) 1)如果您使用的是 Launchpad、请移除除3V3/GND/SBWTDIO/SBWTCK 之外的所有跳线。

    2) 2)使用 EnergyTrace 时、请使用"Free Run"而不是"Run"。

    3) 3)如果可能、请使用32kHz 晶体。 FR2433上的 REFOCLK 的成本约为20uA。  Launchpad 的 Q1上有一个晶振、但您需要进行一些轻焊接才能连接它。

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

    感谢您的建议。 我有两个主要问题。

    1.在 FR2433的3个相关数据表-用户指南中找不到有关为什么使用跳线的任何有用信息。 在哪里可以找到有关这些问题的简要信息?
    3.我尝试使用 XT1甚至使用 RTC 来馈送 ACLK、但我无法理解为什么我总是在 FR2433 RTC 示例中的振荡器故障测试循环中。 可能不焊接、问题出在哪里?

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

    1跳线说明分散在《Launchpad 用户指南》(SLAU739)的第2部分中。 说明很简单;原理图中提供了完整的详细信息(第6节)。

    3)是的、要连接晶体、您需要在 R2和 R3位置(靠近 Q1)之间建立焊接桥 [请参阅用户指南第2.5节]。 您可能应该移除 R4/R5上的0欧姆电阻器以断开与 P2.0/1引脚的连接、但严格来说这并不是必需的(如果您小心的话)。

    ------

    未经请求:

    a) P1.2是 A2、而不是 A12。 A12 (温度)没有引脚、但您需要设置 TSENSOREN。 我不希望这会导致您的症状。

    b)为了有效地使用温度传感器、您需要使用内部基准(INTREFEN)。 数据表似乎并未说明、但在其他 FR2器件上、我已经以60uA 的电流对其进行了测量、因此您需要根据需要将其打开和关闭。 (对于最终器件、您可能需要考虑使用外部温度传感器、该传感器的精度更高、功耗更低。)

    [编辑:再次查看、我看到您正在打开 INTREFEN。 这可能会影响您的功耗、因此您应该对其进行占空比调节。]

    C)我建议您查看示例、这些示例可以提供可粘贴的代码以及一个比较点。 特别相关的可能是 msp430fr243x_ADC10_16.c [温度]和 msp430fr243x_LPM3_01.c [LPM3]:

    https://dev.ti.com/tirex/explore/node?node=AJ4FbEhpy0QN9VgmlO5i8g__IOGqZri__LATEST

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

    非常感谢您。 实际问题是在睡眠模式期间使 INTREFEN 保持启用状态、正如您所说的那样。 现在、我将平均电流支出削减至31 uA (睡眠期间超过65 uA 的支出消失了)。 现在、Energytrace 计算出、 如果我使用2250 mAh、该原型将运行6年以上、令人惊叹。 很显然、我检查了记录的值、它们的温度是正确的。

    接下来、我将尝试将 XT1置于工作模式、但我现在不相信我的焊接/脱焊技能。 也许我需要更多的 FR2433 LaunchPad、并且在脱焊过程中会牺牲其中一个或两个。 如果我可以使用 XT1将 REFO 的支出降低20uA、这可能像是18年的实验。 我不能压缩更多的内容。 我还会将 BUSY DELAY 函数转换为计时器中断、但这实际上是微小的升级、因为睡眠模式占主导地位、并且每12小时节省400周期的 MCU 运行时间不会给我带来太多的影响。

    您建议使用哪种电池设置? 我具有2200 mAh Lipo、在满载时可提供4.1V 电压、但超出了最佳范围。 我还在考虑使用2节镍氢电池(共2.4V)、它在我可以看到的限制范围内(FRAM 运行需要2.2V 电压)。 或者、我应该选择 Lipo plus 3.3 LDO 吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="201666" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1023929/msp430fr2433-daily-temperature-recorder-in-lpm3-mode/3785716 #3785716")我具有2200mAh Lipo、满载时可提供4.1V 电压、但超出了最佳范围。 我还在考虑使用2节镍氢电池(共2.4V)、它在我可以看到的限制范围内(FRAM 运行需要2.2V 电压)。 或者、我是否应该选择 Lipo plus 3.3 LDO?

    我没有测量过它、但在快速搜索中、可充电电池可能具有自放电功能、这可能会限制其使用寿命长达数年的持续低功耗运行。

    例如、请参阅 BU-802b 中提到的自放电:提升自放电的作用是什么?

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

    这更有利于 并联的常规纽扣电池、而我的朋友警告说、提供额外的电压将使系统在相同的输出下消耗更多的电流。 与 Lipo 提供的电压相比、3V 不是那么高。 甚至2节 AA 电池也可能是最佳解决方案。