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.

[参考译文] MSP430FR4133:从 LPM3.5唤醒的状态

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1035519/msp430fr4133-wakeup-state-from-lpm3-5

器件型号:MSP430FR4133

我正在尝试了解当器件从 LPM3.5唤醒时、一切工作原理。  我的设置基本上是从传感器读取数据并在 LCD 上显示这些数据、使用 RTC 每10分钟从传感器获取读数。  在大多数时间内、该单元将处于 LPM3.5模式、而 RTC 和 LCD 可使用 XT1晶振运行。  此外、在此期间、在 LPM3.5模式下、我将所有与 LCD/XT1晶振无关的 GPIO 设置为输出、并以低功耗驱动为低电平。  当我从 LPM3.5唤醒时、我想设置一些 IO 端口和计时器来读取我的传感器、将值写入 LCD 存储器、然后返回 LPM 3.5。  

阅读用户指南、当 LOCKLPM5被置位时(通过进入 LPM3.5)、它将锁定引脚状态以及 RTC 和 LCD 的配置。  在用户指南中:"从 LPMx.5唤醒后、I/O 和连接到 RTC LDO 的模块的状态将被锁定并保持不变、直到您清除 PM5CTL0寄存器中的 LOCKLPM5位。"  数据表指示 RTC 和 LCD 处于"LPM3.5域"中。  

由于我将 LPM3.5中未使用的所有 GPIO 设置为输出和低电平、如果我想为传感器操作设置一些 IO、我显然需要更改端口映射、从而清除 LOCKLPM5位。  当我清零 LOCKLPM5位时、这强制我必须重新初始化 XT1、RTC 和 LCD 控制器、对吧? 下面的用户指南部分似乎表明我必须重新初始化几乎所有内容、因为唤醒是一个 BOR。  编辑: 在 LPM3.5唤醒后、RTC 和 LCD 设置似乎仍然存在、我不必重新初始化它们。  我找到了一个例子,他们没有重新改造这些东西,它运转良好,所以这有点令人困惑…

用户指南还在"从 LPM3.5唤醒"中提到

1.4.3.3从 LPM3.5唤醒
从 LPM3.5唤醒后执行以下步骤:
1.按照与 RTC LDO 连接的模块的原样初始化它们的寄存器
在器件进入 LPM3.5之前进行了配置、但不启用中断。
2.初始化端口寄存器的方式与器件进入之前配置的方式完全相同
LPM3.5、但不启用端口中断。
3.如果在 LPM3.5中使用了 LF 晶振,则相应的 I/O 必须配置为 LFXIN
和 LFXOUT。 必须在时钟系统中启用 LF 晶振(请参阅时钟系统 CS)
章)。
4.将 PM5CTL0寄存器中的 LOCKLPM5位清零。
5.根据需要启用端口中断。
6.使能模块中断。
启用端口和模块中断后、唤醒中断将被视为正常中断。

在我的情况下、在我进入 LPM3.5之前、我有一些用于传感器读数的端口、这些端口作为低功耗输出/低电平。  但是、当我唤醒以进行测量时、我将需要一些驱动为高电平的电平、以及一对用作输入的电压。  在设置传感器读取所需的端口之前、我是否需要将端口寄存器设置为所有输出/低电平(不用于 XT1和 LCD)?

我一直在研究在 Launchpad 板的 LCD 上显示时间的 RTC 示例。  我想这个示例从 LPM3.5唤醒时从不需要重新初始化任何内容的原因是它从不需要清零 LOCKLPM5位、因为它只使用 RTC 和 LCD:

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

    if (SYSRSTIV == SYSRSTIV_LPM5WU)                        // If LPM3.5 wakeup
    {
        Inc_RTC();                                          // Real clock

        PMMCTL0_H = PMMPW_H;                                // Open PMM Registers for write
        PMMCTL0_L |= PMMREGOFF_L;                           // and set PMMREGOFF
        __bis_SR_register(LPM3_bits | GIE);                 // Re-enter LPM3.5
    }
    else
    {
        // Initialize GPIO pins for low power
        Init_GPIO();

        *Seconds = 0;                                       // Set initial time to 12:00:00
        *Minutes = 0;
        *Hours = 12;

        // Configure XT1 oscillator
        P4SEL0 |= BIT1 | BIT2;                              // P4.2~P4.1: crystal pins
        do
        {
            CSCTL7 &= ~(XT1OFFG | DCOFFG);                  // Clear XT1 and DCO fault flag
            SFRIFG1 &= ~OFIFG;
        }while (SFRIFG1 & OFIFG);                           // Test oscillator fault flag
        CSCTL6 = (CSCTL6 & ~(XT1DRIVE_3)) | XT1DRIVE_2;     // Higher drive strength and current consumption for XT1 oscillator

        // Disable the GPIO power-on default high-impedance mode
        // to activate previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;

        // Configure RTC
        RTCCTL |= RTCSS__XT1CLK | RTCIE;                    // Initialize RTC to use XT1 and enable RTC interrupt
        RTCMOD = 32768;                                     // Set RTC modulo to 32768 to trigger interrupt each second

        // Configure LCD pins
        SYSCFG2 |= LCDPCTL;                                 // R13/R23/R33/LCDCAP0/LCDCAP1 pins selected

        LCDPCTL0 = 0xFFFF;
        LCDPCTL1 = 0x07FF;
        LCDPCTL2 = 0x00F0;                                  // L0~L26 & L36~L39 pins selected

        LCDCTL0 = LCDSSEL_0 | LCDDIV_7;                     // flcd ref freq is xtclk

        // LCD Operation - Mode 3, internal 3.08v, charge pump 256Hz
        LCDVCTL = LCDCPEN | LCDREFEN | VLCD_6 | (LCDCPFSEL0 | LCDCPFSEL1 | LCDCPFSEL2 | LCDCPFSEL3);

        LCDMEMCTL |= LCDCLRM;                               // Clear LCD memory

        LCDCSSEL0 = 0x000F;                                 // Configure COMs and SEGs
        LCDCSSEL1 = 0x0000;                                 // L0, L1, L2, L3: COM pins
        LCDCSSEL2 = 0x0000;

        LCDM0 = 0x21;                                       // L0 = COM0, L1 = COM1
        LCDM1 = 0x84;                                       // L2 = COM2, L3 = COM3

        LCDCTL0 |= LCD4MUX | LCDON;                         // Turn on LCD, 4-mux selected (LCD4MUX also includes LCDSON)

        // Display time
        LCDMEM[pos1] = digit[(*Hours) / 10];
        LCDMEM[pos2] = digit[(*Hours) % 10];
        LCDMEM[pos3] = digit[(*Minutes) / 10];
        LCDMEM[pos4] = digit[(*Minutes) % 10];
        LCDMEM[pos5] = digit[(*Seconds) / 10];
        LCDMEM[pos6] = digit[(*Seconds) % 10];

        // Display the 2 colons
        LCDMEM[7] = 0x04;
        LCDMEM[11] = 0x04;

        PMMCTL0_H = PMMPW_H;                                // Open PMM Registers for write
        PMMCTL0_L |= PMMREGOFF_L;                           // and set PMMREGOFF
    
        __bis_SR_register(LPM3_bits | GIE);                 // Enter LPM3.5
        __no_operation();                                   // For debugger
    }
}

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

    您好、Alexander、

    首先、我对您的问题进行总结、如果有任何误解、请予以更正:
    当退出 LPM3.5时、您需要通过某些 GPIO 与传感器通信、因此必须清除 LOCKPM5位以解锁 GPIO。您想了解在从 LPM3.5模式唤醒后是否需要重新初始化晶体的 GPIO。

    我认为是的、您必须重新初始化 LFXT 模块并清除 LOCKPM5位、您可以参考以下示例代码:

    https://dev.ti.com/tirex/explore/node?node=AIIst5gLtBM7DVuyhd5.8A__IOGqZri__LATEST

    谢谢!

    此致

    Johnson

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

    感谢您的回复! 是的、看起来每次唤醒时、我都必须重新配置 GPIO 和 XT1、但 RTC 和 LCD 配置仍然存在。  

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

    好的、谢谢!

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

    另一个与唤醒行为相关的注释是、在我的代码中、我有两个来自 lpm3.5的唤醒源、即 RTC 和 I/O  当退出 LPM3.5时、BOR 复位后、我必须检查哪个中断是唤醒的源、以便我知道要调用哪个函数。  WAKEUP 代码的第一行是__ENABLE_INTERRUPT (),它应使 RTC 或 I/O ISR 执行。  在 I/O ISR 中、我基本上设置一个标志、如果该标志为 true、那么我执行函数 A。 否则、 然后我知道这是一个 RTC 中断,我执行函数 B。 在我看来,在执行__enable_interrupt ()并且 ISR 开始执行之后,有一点延迟。  在我的代码中,它在跳转到 ISR 之前执行_enable_interrupt()下面的行。  这似乎是正确的吗?

    if (SYSRSTIV == SYSRSTIV_LPM5WU)                        // If LPM3.5 wakeup
            {
                __enable_interrupt();
                // The below line will get executed before jumping to the ISR
                display_units = BAKMEM0;  //Get display_units from bakmem
                // Between above line and below line, the ISR will execute. 
                temperature_c = BAKMEM1; // Get temperature displayed from bakmem
              
                if (button_flag)
                {
                    functionA();
                }
                else
                    functionB();

    我找不到任何有关启用中断后 ISR 执行所需时间的文档。  

    再想一想、我不确定是否需要任何 ISR 来实现这些唤醒中断。  main 函数本质上用作我的两个唤醒源的大型 ISR。  我可以在唤醒时检查 P1IV 寄存器、以查看唤醒源是否是 I/O (按钮)。  (如果不是、那么我知道它是 RTC、并且可以读取 RTCIV 来将其清除)。  

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

    您好、Alexander、

    您的问题是 _enable_interrupt ()和  ISR 之间存在一些延迟

    延迟多大? 这是否会影响您的应用?

    我想、如果您想知道唤醒的来源、正如您所描述的、您可以检查 P1IV 或 RTCIV。

    谢谢!

    此致

    Johnson