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.

[参考译文] MSP430FR2476:使用 LPM3.5唤醒 RTC、然后使用计时器 A0超时

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1331539/msp430fr2476-using-lpm3-5-waking-up-with-rtc-and-then-using-timer-a0-for-a-timeout

器件型号:MSP430FR2476

您好!

我正在使用 LPM3.5下的 MSP430FR2476、并由 RTC 唤醒。  一旦微控制器 从 LPM3.5启动、我就会在向上向下 计数模式下使用计时器 A0 、以便在函数内实现超时、这样我就可以得到超时、以防时间过长、但我无法进入 TIMER0_A1_ISR。  

我还没有见过任何将定时器与 RTC 一起用作从 LPM3.5唤醒的定时器(不用于从 LPM3.5唤醒)的示例。  

我想知道是否在 RTC 侧或 LPM3.5侧缺少某些配置。

当我使用 LPM4并通过端口中断从 LPM4模式唤醒时、计时器超时工作正常。  

我正在使用来自 MSP430FR2476的 SDK 的驱动程序库 RTC.h 和 timer_a.h

这是我的 RTC 初始化:

void initRTC(bool irqEnable,bool minsOrSec, uint16_t t)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
    uint16_t modulo;

    uint32_t mod;
    if(minsOrSec)
    {
       mod = t * 32 * 60; // Dado que al hacer 32 * t_tick = 1s * 60 = 1m
    }
    else
    {
        mod = t * 32;
    }

    //Testing
    //modulo = 32; //-->IRQs cada 1seg

    modulo = 57600; // --> IRQs cada 30mins
    if(mod < modulo)
    {
        modulo = (uint16_t)mod;
    }
    else
    {
        cantIRQs = (uint16_t)(mod/modulo); // A priori nos va a dar un numero entero. (seconds = 21600 --> 6h)
    }

    *(unsigned int*)(BKMEM_BASE) = (unsigned int)cantIRQs;
    *(unsigned int*)(BKMEM_BASE+2) = (unsigned int)countIRQs;
    P2SEL0 |= BIT0 | BIT1;                  // set XT1 pin as second function

    do
    {
        CSCTL7 &= ~(XT1OFFG | DCOFFG);      // Clear XT1 and DCO fault flag
        SFRIFG1 &= ~OFIFG;
    } while (SFRIFG1 & OFIFG);              // Test oscillator fault flag

    // Initialize RTC
    // Source = 32kHz crystal, divided by 1024
    RTC_clearInterrupt(RTC_BASE,RTC_OVERFLOW_INTERRUPT_FLAG);
    
    __bis_SR_register(GIE); //Enable interrupts
    
    RTC_init(RTC_BASE, modulo - 1, RTC_CLOCKPREDIVIDER_1024);
    RTC_enableInterrupt(RTC_BASE, RTC_OVERFLOW_INTERRUPT);
    RTC_clearInterrupt(RTC_BASE,RTC_OVERFLOW_INTERRUPT_FLAG);
    RTC_start(RTC_BASE,RTC_CLOCKSOURCE_XT1CLK);//RTC_CLOCKSOURCE_XT1VLOCLK

 }

这就是我进入 LPM3.5模式的方式

    PMMCTL0_H = PMMPW_H;                    // Open PMM Registers for write
    PMMCTL0_L |= PMMREGOFF;                 // and set PMMREGOFF

    __bis_SR_register(LPM3_bits | GIE);     // Enter LPM3.5 and Enable Interruptions

我通过这种方式初始化计时器 A 实例0、

    //Initialize Timer0_A3 --> Up-Down Mode
    Timer_A_initUpDownModeParam upDownCtr;
    upDownCtr.clockSource = TIMER_A_CLOCKSOURCE_ACLK;
    upDownCtr.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;
    upDownCtr.timerPeriod = 65535;  //From 0h to 0FFFFh  --> ~ 4 seg (updown)
    upDownCtr.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;
    upDownCtr.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
    upDownCtr.timerClear = TIMER_A_DO_CLEAR;
    upDownCtr.startTimer = false;

    Timer_A_initUpDownMode(TIMER_A0_BASE ,&upDownCtr);

从 RTC 唤醒时、我再次运行所需的一切的初始化、然后使用  Timer_A_startCounter (timer_a0_BASE、timer_a_updown_mode)启动计时器 A; 但我从未遇到计时器中断:

// Timer0_A3 CC1-2, TA Interrupt Handler
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A1_VECTOR))) TIMER0_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch(__even_in_range(TA0IV,TA0IV_TAIFG))
    {
        case TA0IV_NONE:                            // No interrupt
            break;
        case TA0IV_TACCR1:                          // CCR1 not used
            break;
        case TA0IV_TACCR2:                          // CCR2 not used
            break;
        case TA0IV_TAIFG:                           // overflow
            counterTimer--;
            if(counterTimer <= 0)
            {
                timeOut = true;
            }
            break;
        default:
            break;
    }
}

此外、Code Composer Studio 编译器不允许我在中断内部放置一个断点(第23行)、因此我认为 LPM3.5模式或 RTC 模式的配置存在问题。  

为了防止这种情况、我将包含 RTC 中断矢量的代码:

 // RTC interrupt service routine
 #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
 #pragma vector=RTC_VECTOR
 __interrupt void RTC_ISR(void)
 #elif defined(__GNUC__)
 void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
 #else
 #error Compiler not supported!
 #endif
 {
     cantIRQs = *(unsigned int*)BKMEM_BASE;
     countIRQs = *(unsigned int*)(BKMEM_BASE+2) + 1;
     switch(__even_in_range(RTCIV,RTCIV_RTCIF))
     {
         case  RTCIV_NONE:   break;          // No interrupt
         case  RTCIV_RTCIF:         // RTC Overflow
         {
             RTC_clearInterrupt(RTC_BASE,RTC_OVERFLOW_INTERRUPT_FLAG);
             if(countIRQs == cantIRQs)
             {
                 cbStatus = true;
                 countIRQs=0;
             }
             else
             {
                 cbStatus = false;
             }
             *(unsigned int*)(BKMEM_BASE+2) = 0;
             *(unsigned int*)(BKMEM_BASE+2) = countIRQs;
         }
             break;
         default: break;
     }
 }

非常感谢您提供使用 LPM3.5 + RTC 唤醒+计时器的提示或示例。

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

    我必须补充一点、我认为有一种解决方案可以只是轮询 TA0CTL 寄存器位 TAIFG 来检查定时器是否已经结束了上数周期、但我不确定 TAIFG 是否被设置为1、直到它被读取或自动下降到0 仅在 MSP430FR4xcxxFamilyUsersGuide.pdf 中的该图中

    例如、在本例中、我只想让 time out 从该函数中读取 UART 端口

        //Poll for flag
        if (!(HWREG16(EUSCI_A1_BASE + OFS_UCAxIE) & UCRXIE)){
            //Poll for receive interrupt flag and exit if timeout
            while ((!(HWREG16(EUSCI_A1_BASE + OFS_UCAxIFG) & UCRXIFG)) && (HWREG16(TIMER_A0_BASE + OFS_TAxCCTL0) & TAIFG));
        }
    
        uint8_t word = 0;
        if(HWREG16(TIMER_A0_BASE + OFS_TAxCCTL0) & TAIFG)
            HWREG16(TIMER_A0_BASE + OFS_TAxCCTL0) &= ~TAIFG;          --> Clear interrupt?
        else
            word = HWREG16(EUSCI_A1_BASE + OFS_UCAxRXBUF);
    

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

    嗨、 Maria Ines Quihillalt

    请检查  https://www.ti.com/tool/download/SLAC781上的 msp430fr267x_LPM3_5_01.c

    在 MCU 唤醒期间、 需要 SYSRSTIV = SYSRSTIV_LPM5WU 检查。

    MCU 器件从冷启动和 LPM3.5模式加电时、都 需要使用所有寄存器初始化。

    在文档中、请查看  MSP430FR4xx 和 MSP430FR2xx 系列的1.4.3低功耗模式 LPM3.5和 LPM4.5 (LPMx.5)用户指南(修订版 I)

    谢谢!