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.
您好!
我正在使用计时器生成延迟函数、我遇到了以下情况:
在不调用 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 每秒生成整个脉冲(在后台)。
抱歉、我无法接受任何一对一咨询。 通过在论坛上讨论设计问题 、可以让所有流窜的聪明的人都参与进来、并且未来可能会帮助解决同一个问题。