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.

MSP430FG4618: MSP430FG4618 Frequency Meter

Part Number: MSP430FG4618

Hello,

I am wanting to understand this firmware to know how the measured frequency acquisition works.

Could someone help me?

How can I see the measured frequency at the input of the P1.5 PIN?

Regards,

Follow the link with the source code:

e2e.ti.com/.../33855

  • Hi,

    Could you please clarify what code in the link you are talking about specifically?

    And what exactly do yo mean by the "measured frequency at the input of the P1.5 PIN"? Are you just trying to see the input to this pin?

    Regards,
    Nathan
  • Hi Nathan,

    I need to measure a pulse frequency from a flowmeter per pulse in any variable and send it by serial rs232.

    I would like to use the pulse capture mode and measure the period between one pulse and another to calculate the measured volume.

    I have been looking for a few days for some example of this for the MSP430 especially the MSP430FG4618 that I am using. I found some examples for other MSP430 families, but I came across the difficulty of changing registers that are slightly different from the MSP430FG4618.

    I have no idea how I can do this little stretch to measure flow according to the pulses generated by the meter.

    I found this topic where it speaks a bit of frequency measurement.

    Thanks for the feedback.

    Anderson.
  • Hi Anderson,

    I do not believe that the code in the post that you linked to is doing quite what you are looking for. It is not actually measuring flow rate. What other code examples are you referring to?

    Regards,
    Nathan
  • Generally you set up two counters, one counts the input signal and another counts a known frequency. One of the counters will gate the other.

    The code linked to has some elements of that but has some weird elements in it yet missing other elements.
  • Hello

    I am using a port1 p1.0 interrupt pin to count the flow pulses.

    After 5 seconds generated by the basic timer BT (temp ++;) I do the flow measurement:

    Q = Pulses / Timer.

    float flow = (bottom scale of the meter x pulses x 3600 x 1000) / temp;

    3600 x 1000 for unit of m3 / h.

    For example:  10.15 Hz equal 36.353 m3/h calculated.

    My code: 10.15 Hz equal  25.456 m3/h when measured accurately and does not oscillate.

    I realized that it is very slow and inaccurate due to being using the XTAL1 32.768kHz crystal.

    Maybe the XTAL2 I can get a better result due to frequency being faster but I tried configuring it by slac118l.zip example and could not get it to work .... I guess I did not know how to configure correctly.

    I'm also thinking of counting the pulses at the input of the 74HC590 and using the timer A to precisely time it ... I think milliseconds or microseconds get a better result.

    What do colleagues have to tell me?

  • Danny F's solution works best for fast signals, since you don't have to deal with the individual pulses.

    The flow meters I'm familiar with are pretty slow (10-100Hz). For those you may prefer input capture, since you don't need to guess how often to check -- the pulses determine your output latency. Also you can set up a separate CCR to detect timeout (0Hz).
  • if the frequency is that low, I would use a free running timer and time stamp the edges. taking the time difference between the two edges, you know the flow rate.
  • Hello,

    I was able to assemble this code however I am not getting the result waiting! For example: The calculated frequency is different from that shown on the oscilloscope, where it is generated 10Hz is measured 20Hz. 

    And where it is generated 16.6Hz is measured 513Hz!

    Did I do something wrong?

    I would also like to know if the timer is set correctly in capture mode?

    Is it possible to work in LPM3 mode?



    #include <stdio.h> #include <intrinsics.h> #include <stdlib.h> #include <string.h> #include <msp430xG46x.h> volatile unsigned int count, edge1, edge2, period; // Global variables float freq; unsigned char string_freq[10]; volatile unsigned int i; /* defines - testar flag de tx da usci 0 e usci1 */ #define testa_tx_cr() while(!(IFG2 & UTXIFG1)); //************************************************************************************************************// // Definições e Inicialização da Comunicação Serial RS232 do Data Logger // //************************************************************************************************************// void initRS232(void) { P4SEL |= 0x03; // P4.1,0 = USART1 TXD/RXD ME2 |= UTXE1 + URXE1; // Enable USART1 TXD/RXD U1CTL |= CHAR; // 8-bit character U1TCTL |= SSEL0; // UCLK = ACLK U1BR0 = 0x03; // 32k/9600 - 3.41 U1BR1 = 0x00; // U1MCTL = 0x4A; // Modulation U1CTL &= ~SWRST; // Initialize USART state machine IE2 |= URXIE1; // Enable USART1 RX interrupt } //************************************************************************************************************// // Rotina para Transmissão Serial do Data Logger // //************************************************************************************************************// void msg_rs232_cr(unsigned char *string) {// envia uma string via rs232 via UCA0 while (*string != 0) { testa_tx_cr();// testa flag de tx TXBUF1 = *string; *string++; } // while string } void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer FLL_CTL0 |= XCAP14PF; // Configure load caps // Wait for xtal to stabilize do { IFG1 &= ~OFIFG; // Clear OSCFault flag for (i = 0x47FF; i > 0; i--); // Time for flag to set } while ((IFG1 & OFIFG)); // OSCFault flag still set? P1DIR &= ~BIT2; // Set P1.2 -> Input P1SEL |= BIT2; // Set P1.2 -> TA0.1 Capture Mode //P1DIR &= ~BIT0; // Set P1.0 -> Input //P1SEL |= BIT0; // Set P1.0 -> TA0 Capture Mode MSP430FG4618 initRS232(); // Inicializa o RS232 TA0CCTL1 = CAP + CM_1 + CCIE + SCS + CCIS_0; // Capture Mode, Rising Edge, Interrupt // Enable, Synchronize, Source -> CCI0A //TACTL = TASSEL_1 + MC_2 + TAIE + TACLR; // ACLK, cont. mode, TA0CTL |= TASSEL_2 + MC_2 + TACLR; // Clock -> SMCLK, Cont. Mode, Clear Timer while(1) { count = 0; // Initialise count for new capture __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, Enable Interrupt //Exits LPM0 after 2 rising edges are captured if (edge2 > edge1) // Ignore calculation if overflow occured { period = edge2 - edge1; // Calculate Period freq = 1000000L/period; // Calculate Frequency msg_rs232_cr("Frequency: "); // Transmite a string Frequency sprintf(string_freq,"%.2f",freq); msg_rs232_cr(string_freq); msg_rs232_cr(" \r\n"); } __no_operation(); // For inserting breakpoint in debugger } } // Timer_A3 Interrupt Vector (TAIV) handler #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=TIMERA1_VECTOR __interrupt void Timer_A (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMERA1_VECTOR))) Timer_A (void) #else #error Compiler not supported! #endif { switch( TAIV ) { case 2: if (!count) // Check value of count { edge1 = TA0CCR1; // Store timer value of 1st edge count++; // Increment count } else { edge2 = TA0CCR1; // Store timer value of 2nd edge count=0; // Reset count __bic_SR_register_on_exit(LPM0_bits + GIE); // Exit LPM0 on return to main } break; // TACCR1 used case 4: break; // TACCR2 not used case 10: break; // overflow } } /* #pragma vector = TIMER0_A1_VECTOR __interrupt void TIMER0_A1_ISR (void) { switch(__even_in_range(TA0IV,0x0A)) { case TA0IV_NONE: break; // Vector 0: No interrupt case TA0IV_TACCR1: // Vector 2: TACCR1 CCIFG if (!count) // Check value of count { edge1 = TA0CCR1; // Store timer value of 1st edge count++; // Increment count } else { edge2 = TA0CCR1; // Store timer value of 2nd edge count=0; // Reset count __bic_SR_register_on_exit(LPM0_bits + GIE); // Exit LPM0 on return to main } break; case TA0IV_TACCR2: break; // Vector 4: TACCR2 CCIFG case TA0IV_6: break; // Vector 6: Reserved CCIFG case TA0IV_8: break; // Vector 8: Reserved CCIFG case TA0IV_TAIFG: break; // Vector 10: TAIFG default: break; } } */

  • Easy to debug. Ask yourself how the code works and what you expect.

  • Below about 1MHz/65536 = ~15Hz, the timer will wrap between pulses. Consider using e.g. ID=3 (timer at 1MHz/8=125kHz).

    Also you can set up a separate CCR to detect timeout (0Hz).
  • Thank everyone! But I'm new to learning MSP430 and I have some difficulties.

    Could the gentlemen please start this configuration?

    Could you post the code snippet or an example code?

    I necessarily need to measure a frequency from 0.1Hz to 100Hz!
  • I think you're on the right track, you just need to understand what your timer is actually measuring: timer ticks, the length of which depend on the timer's input clock. 1/Time=Frequency

    Measuring 0.1Hz will be a challenge, since -- no matter how you do it -- you'll need to wait 10 seconds just to find out. How many L/m is that?

    You may want a different clock source for the timer, since 1MHz is pretty fast for what you're doing. Using the ID bits [see also SLAU056L sec. 15.2.1] you can divide the clock by up to /8 (ID_3). 1MHz/8=125kHz, /65536 is about 0.5 seconds (before wrapping) so your lower bound is about 2Hz.

    If you have a 32kHz crystal on ACLK (the MSP-EXP430F4618 has one [SLAU213A sec. 6.4.2]) you can use that for the timer (TASSEL_1). Dividing that by /8 gives you 4096Hz. That's about 40 ticks for 100Hz (10ms). The 16-bit wrap will happen at 4096/65536 = 0.0625Hz (16sec).
  • Thanks for the support Bruce!

    Yes I need to measure the flow of a pulsed Hydrometer with a scale of 0.001 m3 / h.

    I found this code example on the internet and chose to test it and saw that the lowest measured frequency is 200Hz.

    Can you configure it as you said?



    /*************************************************************************************/ /* Lab 4C - Frequency measurement */ /* */ /* */ /* */ /* MSP430 Teaching ROM */ /* Produced by: MSP430@UBI Group - www.msp430.ubi.pt */ /* */ /* Exercise: Using the MSP-EXP430FG4618 Development Tool and the */ /* MSP430FG4618 device, perform a frequency measurement */ /* */ /* Instructions: */ /* */ /* Complete the code below: */ /* - Configure Basic Timer1 */ /* - Configure Timer_A */ /* - Configure Timer_B */ /* - Configure P1, P2 and P3 */ /* */ /* */ /* */ /* Copyright Texas Instruments 2009 */ /**********************************************************************************/ #include <msp430xG46x.h> #include "LCD_defs.h" //****************************************************************** // Global data //****************************************************************** unsigned char flag, capture, counter, tick; unsigned int T, T1, T2, freq; //****************************************************************** // Write frequency (Hz) in LCD //****************************************************************** void LCD_freq(void) { unsigned int freq1, freq2, freq3, freq4; freq = 7995392/T; freq1 = freq / 1000; freq2 = freq % 1000; switch (freq1) // switch to write frequency first digit { case 1:P4_A1; break; case 2:P4_A2; break; case 3:P4_A3; break; case 4:P4_A4; break; case 5:P4_A5; break; case 6:P4_A6; break; case 7:P4_A7; break; case 8:P4_A8; break; case 9:P4_A9; break; case 0:P4_A0; break; } freq3 = freq2 % 100; freq2 = freq2 / 100; switch (freq2) // switch to write seconds frequency digit { case 1: P3_A1; break; case 2: P3_A2; break; case 3: P3_A3; break; case 4: P3_A4; break; case 5: P3_A5; break; case 6: P3_A6; break; case 7: P3_A7; break; case 8: P3_A8; break; case 9: P3_A9; break; case 0: P3_A0; } freq4 = freq3 % 10; freq3 = freq3 / 10; switch (freq3) // switch to write seconds frequency digit { case 1: P2_A1; break; case 2: P2_A2; break; case 3: P2_A3; break; case 4: P2_A4; break; case 5: P2_A5; break; case 6: P2_A6; break; case 7: P2_A7; break; case 8: P2_A8; break; case 9: P2_A9; break; case 0: P2_A0; } switch (freq4) // switch to write seconds frequency digit { case 1: P1_A1; break; case 2: P1_A2; break; case 3: P1_A3; break; case 4: P1_A4; break; case 5: P1_A5; break; case 6: P1_A6; break; case 7: P1_A7; break; case 8: P1_A8; break; case 9: P1_A9; break; case 0: P1_A0; } } //****************************************************************** // LCD clean routine //****************************************************************** void LCD_all_off(void) { LCDM2 = 0x00; LCDM3 = 0x00; LCDM4 = 0x00; LCDM5 = 0x00; LCDM6 = 0x00; LCDM7 = 0x00; LCDM8 = 0x00; LCDM9 = 0x00; LCDM10 = 0x00; LCDM11 = 0x00; LCDM12 = 0x00; LCDM13 = 0x00; } //****************************************************************** // Timer A Interrupt Service Routine //****************************************************************** #pragma vector=TIMERA1_VECTOR __interrupt void TimerA1_ISR (void) { switch (TAIV) { case TAIV_TACCR1: if (capture == 0){ T1 = TACCR1; flag = 1; capture = 1; } else { if (flag == 1) { T2 = TACCR1; if (T2 > T1) T = T2-T1; } else{ TAR = 0; } capture = 0; flag = 0; } break; case TAIV_TACCR2: break; case TAIV_TAIFG: tick++; if (tick == 60){ LCD_freq(); tick = 0; } if (flag == 1)flag = 0; break; default: break; } } //***************************************************************** // Basic Timer Interrupt Service Routine. Run with 1 sec period //***************************************************************** #pragma vector=BASICTIMER_VECTOR __interrupt void basic_timer_ISR(void) { unsigned int read_data; // read data from file , frequency in kHz P2OUT^=0x06; // toogle LED1 and LED2 counter++; if (counter == 5){ counter = 0; read_data = 200; TBCCR0 = 7995392/read_data; TBCCR4 = TBCCR0/2; } } //****************************************************************** // Main routine //****************************************************************** void main (void) { //Stop WatchDog WDTCTL = WDTPW | WDTHOLD; // Stop WDT //FLL+ configuration // ACLK - 32.768 kHz FLL_CTL0 |= DCOPLUS + XCAP18PF; // DCO+ set, freq = xtal x D x N+1 SCFI0 |= FN_4; // x2 DCO freq, 8MHz nominal DCO SCFQCTL = 121; // (121+1) x 32768 x 2 = 7.99 MHz // Ports COM0-COM1-COM2-COM3 configuration P5DIR |= 0x1E; // Ports P5.2, P5.3 and P5.4 as outputs P5SEL |= 0x1E; // Ports P5.2, P5.3 and P5.4 as special function (COM1, COM2 and COM3) // S0-S21 ports configuration LCDAPCTL0 = LCDS24 | LCDS20 | LCDS16 | LCDS12 | LCDS8 | LCDS4; // LCDA configuration LCDACTL = LCDFREQ_192 | LCD4MUX | LCDSON | LCDON; // (ACLK = 32768)/192, 4-mux LCD, LCD_A on, Segments on LCDAVCTL0 = LCDCPEN; // Charge pump enable LCDAVCTL1 = VLCD_3_44; // VLCD = 3.44 V LCD_all_off(); // Basic Timer 1 Configuration BTCTL = BTDIV | BT_fCLK2_DIV128; // (ACLK/256)/128 IE2 |= BTIE; // Enable BT interrupt with 1 sec period // TimerB configuration TBCCR0 = 39977; // Output 200 Hz signal with 50% duty cicle TBR = 0; // reset TBR TBCCTL4 = OUTMOD_3; // CCR4 output mode 3 (set/reset) TBCCR4 = TBCCR0/2; TBCTL = TBSSEL_2 | CNTL_0 | TBCLGRP_0 |MC_1 | ID_0; // SMCLK, continuous mode // TimerA configuration TACTL = TASSEL_2 |MC_2 | ID_0 | TAIE; // SMCLK, continuous mode up to 0xffff TACCTL1 = CM1 | CCIS_0 | CAP | CCIE; // Capture on rising edge, Cap mode, cap/com interrupt enable // TACCR1 input signal selected // TA1 (TACCR1) configuration (Port1) P1SEL = 0x04; // P1.2 as special function (TA1) P1DIR = 0x00; // P1.2 as input // LED1 and LED2 configuration (Port2) P2DIR = 0x06; // P2.2 and P2.1 as digital output P2OUT = 0x04; // LED1 on and LED2 off // TB4 configuration (Port3) P3SEL = 0x20; // P3.5 as special function (TB4) P3DIR = 0x20; // P3.5 as output // global data initialition counter = 0; tick = 0; // Interrupts enabled //_BIS_SR(GIE); // all interrupts enable __bis_SR_register(LPM0_bits + GIE); //enter low power mode0 with interrupt enable for(;;); } //***************************************************************** // End of Lab3d_solution.c //*****************************************************************

  • I think I've explained (twice, including references) how to fix, or at least improve, what you're doing. Now I think you need to do your own homework.
  • Thanks Bruce for the tips!

    Here is a code that measures frequencies from 1Hz.

    Now I need to better evaluate how to measure frequencies smaller than 1Hz.

    Thank you all for your patience!




    #include <stdio.h> #include <intrinsics.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stdint.h> #include <msp430xG46x.h> #include "LCD16x2_Data_Logger.c" volatile int Temporizador = 0; unsigned char string_vazao[10]; unsigned char flag, capture, counter, tick; unsigned int T, T1, T2; float freq = 0.0; float vazao = 0.0; //************************************************************************************************************// // Definições dos Pinos de Entrada e Saída do MSP430 do Data Logger // //************************************************************************************************************// void initPORTS(void) { P1OUT = 0; // All P1.x reset P1DIR = 0xFF; // All P1.x outputs P2OUT = 0; // All P2.x reset P2DIR = 0xFF; // All P2.x outputs P3OUT = 0; // All P3.x reset P3DIR = 0xFF; // All P3.x outputs P4OUT = 0; // All P4.x reset P4DIR = 0xFF; // All P4.x outputs P5OUT = 0; // All P5.x reset P5DIR = 0xFF; // All P5.x outputs P6OUT = 0; // All P6.x reset P6DIR = 0xFF; // All P6.x outputs P7OUT = 0; // All P7.x reset P7DIR = 0xFF; // All P7.x outputs P8OUT = 0; // All P8.x reset P8DIR = 0xFF; // All P8.x outputs P9OUT = 0; // All P9.x reset P9DIR = 0xFF; // All P9.x outputs P10OUT = 0; // All P10.x reset P10DIR = 0xFF; // All P10.x outputs // TA1 (TACCR1) configuration (Port1) P1SEL = 0x04; // P1.2 as special function (TA1) P1DIR = 0x00; // P1.2 as input // LED1 and LED2 configuration (Port2) P2DIR = 0x07; // P2.2 and P2.1 as digital output P2OUT &=~ 0x04; // LED1 on and LED2 off P5DIR = 0x02; // Define P5.1 como Saída P5OUT &=~ 0x02; // Zera o Pino LED4 P5OUT = !(BIT1); // Desabilita a Conversão de Tensão Step-Up } //************************************************************************************************************// // Definições e Inicialização da Comunicação Serial RS232 do Data Logger // //************************************************************************************************************// void initRS232(void) { P4SEL |= 0x03; // P4.1,0 = USART1 TXD/RXD ME2 |= UTXE1 + URXE1; // Enable USART1 TXD/RXD U1CTL |= CHAR; // 8-bit character U1TCTL |= SSEL0; // UCLK = ACLK U1BR0 = 0x03; // 32k/9600 - 3.41 U1BR1 = 0x00; // U1MCTL = 0x4A; // Modulation U1CTL &= ~SWRST; // Initialize USART state machine IE2 |= URXIE1; // Enable USART1 RX interrupt } //************************************************************************************************************// // Definições e Inicialização do BASIC TIMER para Temporizações do Data Logger // //************************************************************************************************************// void initBT(void) { BTCNT1 = BTCNT2 = 0; BTCTL = BTDIV + BT_fCLK2_DIV128; // Configura o Basic Timer IE2 |= BTIE; // Habilita o Basic Timer } //************************************************************************************************************// // Rotina para Transmissão Serial do Data Logger // //************************************************************************************************************// void msg_rs232_cr(unsigned char *string) {// envia uma string via rs232 via UCA0 while (*string != 0) { testa_tx_cr();// testa flag de tx TXBUF1 = *string; *string++; } // while string } //************************************************************************************************************// // Rotina de Conversão dos Dados do Canal de Pressão Manométrica para Apresentação no Display LCD 16X4 do Data Logger //************************************************************************************************************// void Mostra_Vazao(float Vazao) { sprintf(string_vazao,"%.2f",Vazao); LCDSetPosition(0,1); LCDPrintString("Frequency Meter"); LCDSetPosition(1,2); LCDPrintString("F:"); // Escreve Q: LCDSetPosition(1,6); // Posiciona para Escrita do Valor de Vazão no LCD16x2 LCDPrintString(string_vazao); // Apresenta o Valor da Vazão no LCD16x2 LCDSetPosition(1,13); // Posiciona para Escrita da Unidade de Vazão no LCD16x2 LCDPrintString("Hz"); // Escreve a Unidade de Vazão no LCD16x2 } //****************************************************************** // Write frequency (Hz) in LCD //****************************************************************** void LCD_freq(void) { freq = 32768L/(float)T; } void main (void) { volatile unsigned int j; WDTCTL = WDTPW + WDTHOLD; // Stop WDT // Clock default: MCLK = 32 x ACLK = 1MHz , FLL+ operating FLL_CTL0 |= XCAP14PF; // Configure load caps do { IFG1 &= ~OFIFG; // Clear OSCFault flag for (j = 0x47FF; j > 0; j--); // Time for flag to set } while ((IFG1 & OFIFG)); // OSCFault flag still set? initPORTS(); // Inicializa os PORTS initBT(); // Inicializa o BT initRS232(); // Inicializa o RS232 P5OUT &=~ 0x02; // Habilita o MAX761CPA para Conversão de Tensão InitLCD(); LCDPrintString("Testando..."); __delay_cycles(500000); LCDSetPosition(1,0); LCDPrintString("Display LCD16X2"); __delay_cycles(500000); LCDClear(); // TimerA configuration TACTL = TASSEL_1 |MC_2 | ID_0 | TAIE; // SMCLK, continuous mode up to 0xffff TACCTL1 = CM1 | CCIS_0 | CAP | CCIE; // Capture on rising edge, Cap mode, cap/com interrupt enable // TACCR1 input signal selected do // Rotina Principal { __bis_SR_register(LPM3_bits + GIE); // Entra em LPM3 (Modo de Baixo Consumo) __no_operation (); // Não faz nada } while (1); // Enquanto adjustment for < que 38, garante o LPM3 __bis_SR_register(LPM3_bits + GIE); // Entra em LPM3 (Modo de Baixo Consumo) } // ---------------------------------------------------------------------- // Interrupt service routine for basic timer: start captures on CCI2B // Flag cleared automatically // ---------------------------------------------------------------------- #pragma vector = BASICTIMER_VECTOR __interrupt void BASICTIMER_ISR (void) { /* Temporizador++; if(Temporizador == 5) { Temporizador = 0; // Reseta Temporizador vazao = (freq * 0.001 * 3600); // Converte a Vazão Mostra_Vazao(vazao); // Apresenta a Vazão } */ Mostra_Vazao(freq); // Apresenta a Vazão } //****************************************************************** // Timer A Interrupt Service Routine //****************************************************************** #pragma vector=TIMERA1_VECTOR __interrupt void TimerA1_ISR (void) { switch (TAIV) { case TAIV_TACCR1: if (capture == 0) { T1 = TACCR1; flag = 1; capture = 1; } else { if (flag == 1) { T2 = TACCR1; if (T2 > T1) T = T2-T1; LCD_freq(); } else { TAR = 0; } capture = 0; flag = 0; } break; case TAIV_TACCR2: break; case TAIV_TAIFG: tick++; if (tick == 60) { LCD_freq(); tick = 0; } if (flag == 1) flag = 0; break; default: break; } }

  • Thank you Bruce!
    
    Your instructions were very important to my learning!
    
    Code running as I like!
    
    Regards,
    
    #include <stdio.h>
    #include <intrinsics.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdbool.h> 
    #include <stdint.h>
    #include <msp430xG46x.h>
    #include "LCD16x2_Data_Logger.c"
    
    volatile int Temporizador = 0;
    unsigned char string_freq[10];
    unsigned char flag, capture, counter, tick;
    unsigned int T, T1, T2;
    float freq = 0.0;
    //************************************************************************************************************//
    // Definições dos Pinos de Entrada e Saída do MSP430 do Data Logger                                           //
    //************************************************************************************************************//
    void initPORTS(void)
    {
      P1OUT = 0;                   // All P1.x reset
      P1DIR = 0xFF;                // All P1.x outputs
      P2OUT = 0;                   // All P2.x reset
      P2DIR = 0xFF;                // All P2.x outputs
      P3OUT = 0;                   // All P3.x reset
      P3DIR = 0xFF;                // All P3.x outputs
      P4OUT = 0;                   // All P4.x reset
      P4DIR = 0xFF;                // All P4.x outputs
      P5OUT = 0;                   // All P5.x reset
      P5DIR = 0xFF;                // All P5.x outputs
      P6OUT = 0;                   // All P6.x reset
      P6DIR = 0xFF;                // All P6.x outputs
      P7OUT = 0;                   // All P7.x reset
      P7DIR = 0xFF;                // All P7.x outputs
      P8OUT = 0;                   // All P8.x reset
      P8DIR = 0xFF;                // All P8.x outputs
      P9OUT = 0;                   // All P9.x reset
      P9DIR = 0xFF;                // All P9.x outputs
      P10OUT = 0;                  // All P10.x reset
      P10DIR = 0xFF;               // All P10.x outputs
      
      // TA1 (TACCR1) configuration (Port1)
      P1SEL = 0x04;                             // P1.2 as special function (TA1)
      P1DIR = 0x00;                             // P1.2 as input
        
      // LED1 and LED2 configuration (Port2)
      P2DIR = 0x07;                             // P2.2 and P2.1 as digital output
      P2OUT &=~ 0x04;                             // LED1 on and LED2 off
      
      P5DIR = 0x02;                // Define P5.1 como Saída
      P5OUT &=~ 0x02;              // Zera o Pino LED4  
      P5OUT = !(BIT1);             // Desabilita a Conversão de Tensão Step-Up
    }
    //************************************************************************************************************//
    // Definições e Inicialização da Comunicação Serial RS232 do Data Logger                                      //
    //************************************************************************************************************//
    void initRS232(void)
    {
      P4SEL |= 0x03;                            // P4.1,0 = USART1 TXD/RXD
      ME2 |= UTXE1 + URXE1;                     // Enable USART1 TXD/RXD
      U1CTL |= CHAR;                            // 8-bit character
      U1TCTL |= SSEL0;                          // UCLK = ACLK
      U1BR0 = 0x03;                             // 32k/9600 - 3.41
      U1BR1 = 0x00;                             //
      U1MCTL = 0x4A;                            // Modulation
      U1CTL &= ~SWRST;                          // Initialize USART state machine
      IE2 |= URXIE1;                            // Enable USART1 RX interrupt
    }
    //************************************************************************************************************//
    // Definições e Inicialização do BASIC TIMER para Temporizações do Data Logger                                //
    //************************************************************************************************************//
    void initBT(void)
    {
      BTCNT1 = BTCNT2 = 0;
      BTCTL = BTDIV + BT_fCLK2_DIV128;  // Configura o Basic Timer 
      IE2 |= BTIE; // Habilita o Basic Timer
    }
    //************************************************************************************************************//
    // Rotina para Transmissão Serial do Data Logger                                                              //
    //************************************************************************************************************//
    void msg_rs232_cr(unsigned char *string)
    {// envia uma string via rs232 via UCA0
      while (*string != 0) 
      {
        testa_tx_cr();// testa flag de tx
        TXBUF1 = *string;
        *string++;
      }  // while string  
    } 
    //************************************************************************************************************//
    // Rotina de Conversão dos Dados do Canal de Pressão Manométrica para Apresentação no Display LCD 16X4 do Data Logger
    //************************************************************************************************************//
    void Mostra_Freq(float Freq)
    { 
      sprintf(string_freq,"%.2f",Freq);
      LCDSetPosition(0,2);
      LCDPrintString("Frequency Meter");
      LCDSetPosition(1,2);
      LCDPrintString("F:");                                         
      LCDSetPosition(1,6);                                          
      LCDPrintString(string_freq);                                 
      LCDSetPosition(1,13);                                         
      LCDPrintString("Hz");                                       
    }
    //******************************************************************
    // Write frequency (Hz) in LCD 
    //******************************************************************
    void LCD_freq(void)
    {
      freq = 4096L/(float)T;
    }
    
    void main (void)
    {
      volatile unsigned int j;
    
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      // Clock default: MCLK = 32 x ACLK = 1MHz , FLL+ operating
      FLL_CTL0 |= XCAP14PF;                     // Configure load caps
    
      do
      {
        IFG1 &= ~OFIFG;                           // Clear OSCFault flag
        for (j = 0x47FF; j > 0; j--);             // Time for flag to set
      }
      while ((IFG1 & OFIFG));                   // OSCFault flag still set?
      
      initPORTS(); // Inicializa os PORTS
      initBT();    // Inicializa o BT 
      initRS232(); // Inicializa o RS232
        
      P5OUT &=~ 0x02; // Habilita o MAX761CPA para Conversão de Tensão
      InitLCD();
      LCDPrintString("Testando...");
      __delay_cycles(500000);
      LCDSetPosition(1,0);
      LCDPrintString("Display LCD16X2");
      __delay_cycles(500000);
      LCDClear();
      
      // TimerA configuration
      TACTL = TASSEL_1 |MC_2 | ID_3 | TAIE;    // SMCLK, continuous mode up to 0xffff   
      TACCTL1 = CM1 | CCIS_0 | CAP | CCIE;     // Capture on rising edge, Cap mode, cap/com interrupt enable
                                               // TACCR1 input signal selected
       
      do // Rotina Principal
        {
          __bis_SR_register(LPM3_bits + GIE); // Entra em LPM3 (Modo de Baixo Consumo)
          __no_operation (); // Não faz nada
        }
        while (1); // Enquanto adjustment for < que 38, garante o LPM3
      
      __bis_SR_register(LPM3_bits + GIE);   // Entra em LPM3 (Modo de Baixo Consumo)
    }
    // ----------------------------------------------------------------------
    // Interrupt service routine for basic timer: start captures on CCI2B
    // Flag cleared automatically
    // ----------------------------------------------------------------------
    #pragma vector = BASICTIMER_VECTOR
    __interrupt void BASICTIMER_ISR (void)
    {
      Mostra_Freq(freq);                                // Apresenta a Vazão
    }
    //******************************************************************
    // Timer A Interrupt Service Routine
    //******************************************************************
    #pragma vector=TIMERA1_VECTOR
    __interrupt void TimerA1_ISR (void)
    {
     switch (TAIV)
     {
       case TAIV_TACCR1: 
            if (capture == 0)
              {
                T1 = TACCR1;
                flag = 1;
                capture = 1;
              }
            else 
              {
                if (flag == 1) 
                  {
                    T2 = TACCR1;
                    if (T2 > T1)
                      T = T2-T1; 
                      LCD_freq();
                  }
                else
                  {
                    TAR = 0;
                  }
                capture = 0;
                flag = 0; 					
              } 
       break;
       
       case TAIV_TACCR2:
       break;
    
       case TAIV_TAIFG:
            tick++;
            if (tick == 60)
              {
                LCD_freq();
                tick = 0;
              }
            if (flag == 1)
              flag = 0;
       break;                     
      
       default:
       break;  
     }
    }	
    

  • I'm glad it worked out.

**Attention** This is a public forum