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.

[参考译文] MSP430FR5994:LPM3和计时器

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1206563/msp430fr5994-lpm3-and-timers

器件型号:MSP430FR5994
主题中讨论的其他器件:ENERGYTRACEADS1220

您好!

我正在使用计时器生成延迟函数、我遇到了以下情况:

在不调用 delay 函数的情况下、LPM3中的电流消耗为10uA。

调用任何延迟函数后、LPM3中的功耗电流均为+/- 150uA。

下面是一个代码片段和配置附件。

对我的设置有什么建议吗?

////////////////////////////////////////////////////////////////////////////////
//       Rotina para Gerar Atrasos para Leituras dos Sensores de Pressões     //
////////////////////////////////////////////////////////////////////////////////
void Delay_PRESS(void)
{
   TA4CCTL0 |= CCIE_1;                                                          // Habilita a Interrupção do TIMER4_A0
   TA4CTL = TASSEL_1 + MC_1 + TACLR;                                            // Configura o TIMER4_A0 (ACLK, UP Mode)
   TA4CCR0 = 1966;                                                              // Periodo de Tempo da Leitura dos Sensores de Pressão de Entrada e Saída
   __bis_SR_register(LPM3_bits + GIE);                                          // Entra em LPM3 (Modo de Baixo Co
}
////////////////////////////////////////////////////////////////////////////////
//     Rotina para Gerar Atrasos para Acionamentos das Válvulas Solenóides    //
////////////////////////////////////////////////////////////////////////////////
void Delay_SOLENOIDE(void)
{
   TA3CCTL0 |= CCIE_1;                                                          // Habilita a Interrupção do TIMER3_A0
   TA3CTL = TASSEL_1 + MC_1 + TACLR;                                            // Configura o TIMER3_A0 (ACLK, UP Mode)
   TA3CCR0 = 327;                                                               // Periodo de Tempo de Acionamento das Válvulas Solenóides de Controle
   __bis_SR_register(LPM3_bits + GIE);                                          // Entra em LPM3 (Modo de Baixo Consumo)
}


////////////////////////////////////////////////////////////////////////////////
//              Rotina Principal do Smart Logger VRP Controller               //
////////////////////////////////////////////////////////////////////////////////
void main(void)
{
   WDTCTL = WDTPW + WDTHOLD;                                                    // Desabilita o WDT
  
   // Disable the GPIO power-on default high-impedance mode to activate
   // previously configured port settings
   PM5CTL0 &= ~LOCKLPM5;
  
   // Rotinas para Inicialização das Portas e Pinos do MSP430FR5994
   initPORTS();                                                                 // Inicializa os Ports
  
   // Rotinas para Inicialização do Clock e Oscilador do MSP430FR5994
   //initClockTo1MHz();                                                          // Seleciona o Clock para 1MHz
   //initClockTo8MHz();                                                          // Seleciona o Clock para 8MHz
   initClockTo16MHz();                                                          // Seleciona o Clock para 16MHz     
  
   // TimerA3 configuration
   TA3CTL = 0;                                                                  // Desabilita o TimerA3
   
   // TimerA4 configuration
   TA4CTL = 0;                                                                  // Desabilita o TimerA4
            
   // Habilita os Periféricos RTC e BT
   RTCCTL13 &= ~RTCHOLD;                                                        // Habilita o RTC
  
   // Rotina Principal do Loop
   do                                            
     {
        __bis_SR_register(LPM3_bits + GIE);                                     // Entra em LPM3 (Modo de Baixo Consumo)
        __no_operation ();                                                      // Não Faz Nada    
     }
   while (1);                                                                   // Enquanto While Igual a 1, Garante o LPM3
}


////////////////////////////////////////////////////////////////////////////////
//    Rotina de Tratamento da Interrupção do Timer3_A0 de Ciclos Periódicos   //
////////////////////////////////////////////////////////////////////////////////
// Timer3_A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER3_A0_VECTOR
__interrupt void TIMER3_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER3_A0_VECTOR))) TIMER3_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
   __bic_SR_register_on_exit(LPM3_bits);                                        // Sai do Modo de Baixo Consumo
   TA3CCTL0 |= CCIE_0;                                                          // Desabilita a Interrupção do TIMER3_A0
   TA3CTL = 0;                                                                  // Desabilita o TIMER3_A0
}
////////////////////////////////////////////////////////////////////////////////
//    Rotina de Tratamento da Interrupção do Timer4_A0 de Ciclos Periódicos   //
////////////////////////////////////////////////////////////////////////////////
// Timer4_A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER4_A0_VECTOR
__interrupt void TIMER4_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER4_A0_VECTOR))) TIMER4_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
   __bic_SR_register_on_exit(LPM3_bits);                                        // Sai do Modo de Baixo Consumo
   TA4CCTL0 |= CCIE_0;                                                          // Desabilita a Interrupção do TIMER4_A0
   TA4CTL = 0;                                                                  // Desabilita o TIMER4_A0
}

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

    我看不到您描述的在 Launchpad 上运行时的行为。 EnergyTrace 在 while (1)中报告约1.5uA (无论是否调用 delay_press ())均可。

    我不得不填补一些空白——我定义 initGPIO()来做输入/下拉,定义 initClockTo16MHz()来启动 LFXT。 我在 main ()中的 while (1)循环之前调用 delay_press ()。

    您能否进一步描述测试用例?

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

    //******************************************************************************
    //  MSP430FR69xx Demo - RTC in real time clock mode
    //
    //  Description: This program demonstrates the RTC mode by triggering an
    //  interrupt every second and minute. This code toggles P1.0 every second.
    //  This code recommends an external LFXT crystal for RTC accuracy.
    //  ACLK = LFXT = 32768Hz, MCLK = SMCLK = default DCO = 1MHz
    //
    //                MSP430FR6989
    //             -----------------
    //        /|\ |              XIN|-
    //         |  |                 | 32768Hz
    //         ---|RST          XOUT|-
    //            |                 |
    //            |            P1.0 |--> Toggles every second
    //            |                 |
    //
    //   William Goh
    //   Texas Instruments Inc.
    //   August 2014
    //   Built with IAR Embedded Workbench V5.60 & Code Composer Studio V6.0
    //******************************************************************************
    
    #include <msp430fr6989.h>
    
    void delay_timer(int timer)
    {
       TA1CCR0 = (int)(10 * timer);                                                 // Set count target
       TA1CTL |= MC__UP;                                                            // Set count mode to up (Changed from TA1CTL = MC__UP;)
       __bis_SR_register(LPM3_bits | GIE);                                          // Enter LPM3
    }
    
    int main(void)
    {
       WDTCTL = WDTPW | WDTHOLD;                                                    // Stop WDT
    
       // Configure GPIO
       P1OUT = 0;                                                                   // Reseta Todos os Pinos da Porta P1
       P1DIR = 0xFF;                                                                // Define Todos os Pinos da Porta P1 como Saídas
       P1OUT &=~ 0xFF;                                                              // Inicializa Todos os Pinos da Porta P1 com Nível Lógico "0" Baixo
       P1DIR &=~ (BIT1);                                                            // Define Todos os Pinos da Porta P1 como Entradas
       P1REN |= (BIT1);                                                             // Habilita os Resistores de Pull Up dos Pinos da Porta P1  
       P1OUT |= (BIT1);                                                             // Inicializa Todos os Pinos da Porta P1 com Nível Lógico "1" Alto
       P1IE |= (BIT1);                                                              // Habilita as Interrupções para os Pinos da Porta P1
       P1IES |= (BIT1);                                                             // Habilita Interrupções como Borda Descida para os Pinos da Porta P1
       P1IFG &=~ (BIT1);                                                            // Limpa as Flags das Interrupções dos Pinos da Porta P1
      
       P2OUT = 0;
       P2DIR = 0xFF;
    
       P3OUT = 0;
       P3DIR = 0xFF;
    
       P4OUT = 0;
       P4DIR = 0xFF;
    
       P5OUT = 0;
       P5DIR = 0xFF;
    
       P6OUT = 0;
       P6DIR = 0xFF;
    
       P7OUT = 0;
       P7DIR = 0xFF;
    
       P8OUT = 0;
       P8DIR = 0xFF;
    
       P9DIR |= BIT7;                                                               // LED interrupt
       P9OUT |= BIT0;
       
    
       P10OUT = 0;
       P10DIR = 0xFF;
    
       PJOUT = 0;
       PJSEL0 = BIT4 | BIT5;                                                        // For XT1
       PJDIR = 0xFFFF;
       
       // Disable the GPIO power-on default high-impedance mode to activate
       // previously configured port settings
       PM5CTL0 &= ~LOCKLPM5;
    
       // XT1 Setup
       CSCTL0_H = CSKEY >> 8;                                                       // Unlock CS registers
       CSCTL1 = DCOFSEL_0;                                                          // Set DCO to 1MHz
       CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;                        // Set ACLK = XT1; MCLK = DCO
       CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;                                        // Set all dividers to 1
       CSCTL4 &= ~LFXTOFF;
       do
        {
           CSCTL5 &= ~LFXTOFFG;                                                     // Clear XT1 fault flag
           SFRIFG1 &= ~OFIFG;
        }
       while (SFRIFG1&OFIFG);                                                       // Test oscillator fault flag
       CSCTL0_H = 0;                                                                // Lock CS registers
      
       TA1CCTL0 = CCIE;                                                             // TACCR0 interrupt enabled
       TA1CTL = TASSEL__ACLK | MC__UP;                                              // ACLK, up mode
       TA1CCR0 = 0;                                                                 // Set count target to 0 by default
       
       do
        {
           P9OUT &= ~(BIT7);                                                        // LED OFF
           __bis_SR_register(LPM3_bits | GIE);                                      // Enter LPM3 w/ interrupt
           __no_operation ();                                                       // Não Faz Nada
        }
       while(1);
    }
    
    // Timer A1 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = TIMER1_A0_VECTOR
    __interrupt void Timer1_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER1_A0_VECTOR))) Timer1_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
       //TA1CTL &= ~MC_3; // Para o cronômetro para evitar a repetição da contagem 
       TA1CTL |= MC__STOP; //  Stop timer to prevent repeat counting (Changed from TA1CTL = MC__STOP;)
       __bic_SR_register_on_exit(LPM3_bits);
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    //               Rotina de Tratamento da Interupção do Port 1                 //
    ////////////////////////////////////////////////////////////////////////////////
    //#pragma vector=PORT1_VECTOR
    //__interrupt void Port1_ISR (void)
    // Port 1 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(PORT1_VECTOR))) Port_1 (void)
    #else
    #error Compiler not supported!
    #endif
    {   
       // Rotina de Monitoramento dos Estados e Acionamentos dos Botões SW1, SW2, SW3, SW4, ADS1220 e USB
       switch (__even_in_range(P1IV, P1IV_P1IFG7))
         {
            // Vector  P1IV_NONE:  No Interrupt pending
            case  P1IV_NONE: break;                                                 //0x000
    
            // Vector  P1IV_P1IFG0:  P1IV P1IFG.0
            case  P1IV_P1IFG0: break;                                               //0x002
             
            // Vector  P1IV_P1IFG1:  P1IV P1IFG.1
            case  P1IV_P1IFG1:                                                      //0x004
                  P9OUT |= (BIT7);                                                  //LED ON
                  delay_timer(1000);                                                       //Delay
            break;
            // Vector  P1IV_P1IFG2:  P1IV P1IFG.2
            case  P1IV_P1IFG2: break;                                               //0x006
               
            // Vector  P1IV_P1IFG3:  P1IV P1IFG.3
            case  P1IV_P1IFG3: break;                                               //0x008
                  
            // Vector  P1IV_P1IFG4:  P1IV P1IFG.4
            case  P1IV_P1IFG4: break;                                               //0x010
    
            // Vector  P1IV_P1IFG5:  P1IV P1IFG.5
            case  P1IV_P1IFG5: break;                                               //0x012
    
            // Vector  P1IV_P1IFG1:  P1IV P1IFG.6
            case  P1IV_P1IFG6: break;                                               //0x014
    
            // Vector  P1IV_P1IFG7:  P1IV P1IFG.7                                   
            case  P1IV_P1IFG7: break;                                               //0x016
    
            // Default case
            default: break;
         }
       
      P1IFG &=~ (BIT1);                                                             // Limpa as Flags das Interrupções de Todos os Pinos da Porta P1
    }

    你好,布鲁斯!

    我还使用 FR6989进行了该测试、并注意到3.6V 电池上存在高电流消耗的变化。 约为32uA。

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

    > TA1CTL |= MC_STOP;//停止计时器以防止重复计数(从 TA1CTL = MC_STOP;更改)

    这不会停止计时器、因为 MC__STOP==0。 请尝试改用:

    > TA1CTL &=~MC_3;     //设置 MC=0以停止计时器

    ----------------

    > delay_timer (1000);//延迟

    在 ISR 中启用 GIE (通过 DELAY_TIMER)通常很危险。 由于我没有看到 P1.1按钮的任何去抖、因此这里的情况更是如此。 我建议您使用"_ bic_SR_register_on_exit (LPM3_BITS);"唤醒 main 并让它执行延迟。

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

    Bruce、您好!

    我建议您使用"_ bic_SR_register_on_exit (LPM3_BITS);"唤醒 main 并让它执行延迟。

    我不太明白你的建议。 请问您能提供更多详细信息吗?

    是否有研究和测试的示例?

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

    我不确定哪个器件缺失。  在原始示例中、您使用了__BIC_SR_REGISTER_ON_EXIT 将工作(就像它一样)从 ISR 推回 main。  

    在像这样的简单演示程序中、即使存在危险、事物也可能看起来起作用。 您打算如何在最终应用中使用这些延迟函数? 我建议您避免在 ISR 中使用它们。

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

    ////////////////////////////////////////////////////////////////////////////////
    //    Rotina de Tratamento da Interrupção do Timer2_A1 de Ciclos Periódicos   //
    ////////////////////////////////////////////////////////////////////////////////
    // Timer2_A1 Interrupt Vector (TAIV) handler
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER2_A1_VECTOR
    __interrupt void TIMER2_A1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER2_A1_VECTOR))) TIMER2_A1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {  
       switch(__even_in_range(TA2IV, TAIV__TAIFG))
         {
            case TAIV__NONE:    break;                                              // No interrupt
            case TAIV__TACCR1:  break;                                              // CCR1 not used 
            case TAIV__TACCR2:  break;                                              // CCR2 not used                                             
            case TAIV__TACCR3:  break;                                              // reserved
            case TAIV__TACCR4:  break;                                              // reserved
            case TAIV__TACCR5:  break;                                              // reserved
            case TAIV__TACCR6:  break;                                              // reserved
            case TAIV__TAIFG:                                                       // overflow
                 Monitora_Pressoes = Monitora_Pressoes + 1;                         // Monitoramento das Pressões de Entrada e Saída a Cada 1 Segundo                                  
                 Monitora_Solenoides = Monitora_Solenoides + 1;                     // Monitoramento das Válvulas Solenóides a Cada 1 Segundo     
                 Monitora_Controle = Monitora_Controle + 1;                         // Monitoramento do Controle da VRP a Cada 1 Segundo
            break;
            default: break; 
         }
       // Monitoramento das Pressões de Entrada e Saída
       if ((((uint32_t)PRESS1 <= ((uint32_t)Pressao_Entrada_MIN)))||((uint32_t)PRESS2 >= (uint32_t)PRESS1)) // Se a Pressão de Referencia < PRESS2 de Saída - 1 AND Maior que ZERO?
       //if ((((uint32_t)PRESS1 <= ((uint32_t)Pressao_Entrada_MIN - 1)) && Positivo((uint32_t)Pressao_Entrada_MIN) == 1)||((uint32_t)PRESS2 >= (uint32_t)PRESS1)) // Se a Pressão de Referencia < PRESS2 de Saída - 1 AND Maior que ZERO?  
         {
            Controle_Baixa = 0;                                                     // Desabilita Acionamento da Válvula Solenóide de Entrada
            Controle_Alta = 0;                                                      // Desabilita Acionamento da Válvula Solenóide de Saída
         }
       // Monitoramento das Válvulas Solenóides de Entrada e Saída                               
       if (Monitora_Solenoides == Intervalo_Controle)                               // Se Acionamentos Habilitados e Temporiza 1 Segundo = Intervalo Controle?
         {                     
            if (Controle_Baixa == 1)                                                // Se Controle de Pressão Baixa?
              {
                 PORTA_P8OUT |= G2012_S32;                                          // Habilita o Circuito da Válvula Solenóide de Entrada
                 //delay_ms(10);
                 Delay_SOLENOIDE();                                                 // Periodo de Tempo da Válvula Solenóide de Entrada Aberta
                 PORTA_P8OUT &=~ G2012_S32;                                         // Desabilita o Circuito da Válvula Solenóide de Entrada
              }
            else
              {
                 if (Controle_Alta == 1)                                            // Se Controle de Pressão Alta?
                   {
                      PORTA_P8OUT |= G2012_S31;                                     // Habilita o Circuito da Válvula Solenóide de Saída
                      //delay_ms(10);
                      Delay_SOLENOIDE();                                            // Periodo de Tempo da Válvula Solenóide de Saída Aberta
                      PORTA_P8OUT &=~ G2012_S31;                                    // Desabilita o Circuito da Válvula Solenóide de Saída
                   }
              }
            Monitora_Solenoides = 0;                                                // Reseta a Variável Temporiza 1 segundo
         }
    }

    Bruce、您好!

    我将在计时器中断中使用延迟函数。

    我需要每1秒钟检查一次(不时)、并在开/关之间间隔10毫秒激活螺线管。

    我正在一个项目中、我们将吸收 MSP430FR5994和两个 ADS1220以及其他外设。

    Bruce、您是否有一封电子邮件、我可以将所有代码发送给您以供您理解?

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

    规范方法是对于您发布的 TA2 ISR 在某个位置设置一个标记"现在对螺线管施加脉冲"、并唤醒主函数;然后主函数将执行设置/延迟/清除序列。

    替代方案可能是使用延迟计时器 ISR 来关闭该计时器(P8?)、 而不是通过唤醒间接调用 GPIO。 与此同时、你可以从 TA2 ISR 返回并执行其他操作。 由于您已经为该功能指定了计时器、因此这是一个相当小的编码变化。

    另一种方法是将螺线管移至计时器输出引脚(例如 P1.3=TA1.2)并使用 OUTMOD 每秒生成整个脉冲(在后台)。

    抱歉、我无法接受任何一对一咨询。 通过在论坛上讨论设计问题 、可以让所有流窜的聪明的人都参与进来、并且未来可能会帮助解决同一个问题。