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.

CCS/MSP-EXP430FR2433: Getting the Timer value with UART

Part Number: MSP-EXP430FR2433
Other Parts Discussed in Thread: MSP430FR2633

Tool/software: Code Composer Studio

Hi,

I'm using MSP-EXP430FR2433. On my launchboard I got 2 LEDs (P1.0/RED and P1.1/Green) and two Switches (P2.3 and P2.7). My project is to change the red LED's blinking speed. If I press the P2.3 switch it reduces the speed and if I press the P2.7 switch it  raises the speed of the blinking. I know this part. But I don't know how to get the Timer's value with UART, so I can see it on my PC. Can somebody help me, please?

Thanks

Here is my code:

#include <msp430.h> 


unsigned int aku1 = 0;                            // counter1
unsigned int aku2= 0;                             // counter2
int counter = 0x1111;

#define SMCLK_115200    0
#define SMCLK_9600      1

#define UART_MODE       SMCLK_115200//SMCLK_9600//

void initUART()
{
    // Configure USCI_A0 for UART mode
    UCA0CTLW0 |= UCSWRST;                      // Put eUSCI in reset
#if UART_MODE == SMCLK_115200

    UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK
    // Baud Rate Setting
    // Use Table 21-5
    UCA0BRW = 8;
    UCA0MCTLW |= UCOS16 | UCBRF_10 | 0xF700;   //0xF700 is UCBRSx = 0xF7

#elif UART_MODE == SMCLK_9600

    UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK
    // Baud Rate Setting
    // Use Table 21-5
    UCA0BRW = 104;
    UCA0MCTLW |= UCOS16 | UCBRF_2 | 0xD600;   //0xD600 is UCBRSx = 0xD6
#else
    # error "Please specify baud rate to 115200 or 9600"
#endif

    UCA0CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
    UCA0IE |= UCTXIE + UCRXIE;                         // Enable USCI_A0 RX interrupt
}

void initClockTo16MHz()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

    __bis_SR_register(SCG0);    // disable FLL
    CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
    CSCTL0 = 0;                 // clear DCO and MOD registers
    CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
    CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
    CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n)
                                //                   = (487 + 1)*(32.768 kHz/1)
                                //                   = 16 MHz
    __delay_cycles(3);
    __bic_SR_register(SCG0);                        // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked

    CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;
}

void initGPIO()
{
    // Configure GPIO
    P1DIR |= BIT0;                                // P1.0 output
    P1OUT &= ~BIT0;                               // P1.0 törlés

    P1DIR |= BIT1;                                // P1.1 output
    P1OUT &= ~BIT1;                               // P1.1 törlés

    P2REN |= BIT3;                                // felhúzóellenállás engedélyezése
    P2OUT |= BIT3;                                // Select pull-up mode for P2.3
    P2IE |= BIT3;                                 // P2.3 interrupt engedélyezés
    P2IES |= BIT3;                                // P2.3 Hi/lo edge
    P2IFG &= ~BIT3;                               // P2.7 IFG törlése

    P2REN |= BIT7;                                // Enable internal pull-up/down resistors
    P2OUT |= BIT7;                                // Select pull-up mode for P2.7
    P2IE |= BIT7;                                 // P2.7 interrupt enabled
    P2IES |= BIT7;                                // P2.7 Hi/lo edge
    P2IFG &= ~BIT7;                               // P2.7 IFG törlése

}

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

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

    //TimerA0 konfig
    TA0CCTL0 |= CCIE;                             // TACCR0 interrupt enabled
    TA0CCR0 = 0x1111;
    TA0CTL |= TASSEL__SMCLK | MC_1 | ID__8;       // SMCLK, up to equal mode

    //TimerA1 konfig
    TA1CCR0 = 0x5fff;
    TA1CTL |= TASSEL__SMCLK | MC_1 | ID__8;      // SMCLK, up to equal mode

    __bis_SR_register(LPM0_bits | GIE);           // LPM3(low power mode) és interruptok engedélyezése
    __no_operation();                             // végtelen ciklus
}

// Timer A0 interrupt service routine
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A (void)

{
     P1OUT ^= BIT0;                               // P1.0 LED villogtatása
}

// Timer A1 interrupt service routine
#pragma vector = TIMER1_A0_VECTOR                 //P1.1 LED visszajelző beállítása
__interrupt void Timer_B (void)

{
    if(aku1 == aku2)
    {
        TA1CCTL0 &= ~CCIE;
        aku1=0;
    }
    else
    {
        P1OUT ^= BIT1;
        aku1++;
    }

}

// Port 2 interrupt service routine
#pragma vector=PORT2_VECTOR
__interrupt void Port_2_7(void)
{
    if(P2IFG & BIT3)                            //ha a P2.3-as gomb interrupt flagje aktív
    {
        if(TA0CCR0 == 0x0000)                   // ha a TimerA0 elérte a minimumot
        {
            P2IFG &= ~BIT3;                     // P2.3 IFG torles
            TA1CCTL0 |= CCIE;                   // TA1CCR0 interrupt engedelyezes
            TA1CCR0 = 0x8fff;                   // TimerA1 sebességének megadása
            TA0R = 0;                           // TimerA0 counter nullázása
            UCA0RXBUF=TA0CCR0;
            aku2 = 4;                           // 2-t villan a visszajelző LED (P1.1)

        }
        else
        {
            P2IFG &= ~BIT3;                     // P2.3 IFG törlés
            TA0CCR0 = TA0CCR0 - 0x1111;         // TimerA0 értékének csökkentese
            counter = counter - 0x1111;
            TA0R = 0;                           // TimerA0 counter nullázása
            TA1CCTL0 |= CCIE;                   // TimerA1 interrupt engedélyezés
            TA1CCR0 = 0x5fff;                   // TimerA1 sebességének megadása
            UCA0RXBUF = TA0CCR0;
            aku2 = 4;                           // 2-t villan a visszajelző LED (P1.1)
        }
    }

    if(P2IFG & BIT7)                            // ha a P2.7-as gomb interrupt flagje aktív
    {
        if(TA0CCR0 == 0xFFFF)                   // ha a TimerA0 elérte a maximumot
        {
            P2IFG &= ~BIT7;                     // P2.7 IFG cleared
            TA1CCTL0 |= CCIE;                   // TimerA1 interrupt engedelyezes
            TA1CCR0 = 0x8fff;                   // TimerA1 sebességének megadása
            TA0R = 0;                           // TimerA0 counter nullázása
            UCA0RXBUF=TA0CCR0;
            aku2 = 6;                           // 3-t villan a visszajelző LED (P1.1)
        }
        else
        {
            P2IFG &= ~BIT7;                     // P2.7 IFG cleared
            TA0CCR0 = TA0CCR0 + 0x1111;         // TimerA0 értékének növelése
            counter = counter + 0x1111;
            TA0R = 0;                           // TimerA0 counter nullázása
            TA1CCTL0 |= CCIE;                   // TimerA1 interrupt engedelyezes
            TA1CCR0 = 0x5fff;                   // TimerA1 sebességének megadása
            UCA0RXBUF = TA0CCR0;
            aku2 = 6;                           // 3-t villan a visszajelző LED (P1.1)
         }
    }
}

//******************************************************************************
// UART Interrupt ***********************************************************
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCA0IV, USCI_UART_UCTXCPTIFG))
  {
    case USCI_NONE: break;
    case USCI_UART_UCRXIFG:
     /* while(!(UCA0IFG&UCTXIFG));
      UCA0TXBUF = UCA0RXBUF;
      __no_operation();*/
      break;
    case USCI_UART_UCTXIFG:
    while(!(UCA0IFG&UCRXIFG));
          UCA0RXBUF = UCA0TXBUF;
          __no_operation();
          break;
    case USCI_UART_UCSTTIFG: break;
    case USCI_UART_UCTXCPTIFG: break;
  }
}

  • Ok, let's see if we can get you up and running.

    The first thing I don't see are the port pin's secondary function being selected - this changes the pin from digital input/output (default) to other functions, such as UART.

    Since you are using UCA0, this means port pins P1.4 and P1.5 need to be switched to their secondary function as shown here.  You can do this in your initGPIO() function by setting the P1SEL register bits that correspond to the IO pins.

    P1SEL |= (GPIO_PIN4 | GPIO_PIN5);

    Next, I see in your code in a couple of places you are copying the current timer's counter value into the UCA0RXBUF.  You don't want to do that.  That is the register that gets populated automatically by the UART when a byte is received.  Instead you want to use the UCA0TXBUF to send your data, BUT, you must first convert the 16-bit binary value into ASCII so it will display properly on the PC terminal.

    I have attached a UART example for the MSP430FR2633 that receives messages from a PC terminal and can either send a fixed (static) message back to the PC or the value of my TA0R register.

    Please look at the TIMER0 ISR Handler at bottom of the file to see how I convert my TA0R register value into ASCII before sending to my PC.

    The cool thing about this demo is the data is transmitted using only interrupts while the CPU remains in LPM0 mode.

    Look through the code and see how I configure my clocks and IO pins.  Feel free to adapt to suit your needs.  If you have any questions let me know.

    /*
     * Basic ASCII UART example for MSP430FR2633 EVM
     * Demonstrates both transmit and receive handlers
     * Runs at 9600 or 115200 baud
     */
    #include <msp430.h> 
    #include <stdio.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    //******************************************************************************
    // PROGRAM DEFINES
    //******************************************************************************
    #define LED_OUT     P1OUT
    #define LED_DIR     P1DIR
    #define LED_PIN     BIT0
    
    #define SMCLK_115200    0
    #define SMCLK_9600      1
    
     // SELECT THE BAUD RATE
    #define UART_MODE       SMCLK_9600
    //#define UART_MODE       SMCLK_115200
    
    //******************************************************************************
    // GLOBAL PROGRAM VARIABLES
    //******************************************************************************
    unsigned char RXDataBuffer[64];
    unsigned char TXDataBuffer[64];
    unsigned char* pTXBuffer = &TXDataBuffer[0];
    unsigned char* pRXBuffer = &RXDataBuffer[0];
    unsigned int bytesToSend;
    unsigned int bytesReceived;
    bool msg_received = false;
    bool uart_busy = false;
    
    //******************************************************************************
    // UART Initialization
    //******************************************************************************
    void initUART()
    {
        // Configure USCI_A0 for UART mode
        UCA0CTLW0 |= UCSWRST;                      // Put eUSCI in reset
    #if UART_MODE == SMCLK_115200
    
        UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK
        // Baud Rate Setting
        // Use Table 21-5
        UCA0BRW = 8;
        UCA0MCTLW |= UCOS16 | UCBRF_10 | 0xF700;   //0xF700 is UCBRSx = 0xF7
    
    #elif UART_MODE == SMCLK_9600
    
        UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK
        // Baud Rate Setting
        // Use Table 21-5
        UCA0BRW = 104;
        UCA0MCTLW |= UCOS16 | UCBRF_2 | 0xD600;   //0xD600 is UCBRSx = 0xD6
    #else
        # error "Please specify baud rate to 115200 or 9600"
    #endif
    
        UCA0CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
        UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
    }
    
    //******************************************************************************
    // GPIO Initialization
    //******************************************************************************
    
    void initGPIO()
    {
    
        // Set the two pins that drive LEDs as outputs
        P1DIR = BIT6 | BIT7;
        P1OUT = 0x00;
    
        // Configure GPIO as USCI_A0 UART PINS
        P1SEL0 |= BIT4 | BIT5;
    
        // Not using PORT2 so set as outputs and drive low
        P2DIR = 0xFF;
        P2OUT = 0x00;
    
        // Not using PORT3 so set as outputs and drive low
        P3DIR = 0xFF;
        P3OUT = 0x00;
    
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
    }
    
    //******************************************************************************
    // Clock Initialization
    //******************************************************************************
    
    void initClockTo16MHz()
    {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRCTL0 = FRCTLPW | NWAITS_1;
    
        __bis_SR_register(SCG0);    // disable FLL
        CSCTL3 |= SELREF__REFOCLK;  // Set REFO as FLL reference source
        CSCTL0 = 0;                 // clear DCO and MOD registers
        CSCTL1 &= ~(DCORSEL_7);     // Clear DCO frequency select bits first
        CSCTL1 |= DCORSEL_5;        // Set DCO = 16MHz
        CSCTL2 = FLLD_0 + 487;      // set to fDCOCLKDIV = (FLLN + 1)*(fFLLREFCLK/n)
                                    //                   = (487 + 1)*(32.768 kHz/1)
                                    //                   = 16 MHz
        __delay_cycles(3);
        __bic_SR_register(SCG0);                        // enable FLL
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));      // FLL locked
    
        CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;
    }
    
    //******************************************************************************
    // Transmits data out UART
    //******************************************************************************
    void TransmitData(unsigned char* string, unsigned int length)
    {
        // Turn on TX LED (P1.6) to show we are transmitting
        P1OUT |= BIT6;
    
        // Wait here in case transmission already in progress
        while(uart_busy == true);
    
        uart_busy = true;                           // Show the UART is busy
        pTXBuffer = string;                         // Set pointer to the transmit buffer
        bytesToSend = length;                       // Setup how many bytes to send
        UCA0IE |= UCTXIE;                           // Enable USCI_A0 TX interrupt
    
        // From here the UART will automatically transmit all the bytes in the string
        // while the CPU remains in LPM0.
    }
    
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;                 // Stop watchdog timer
        initGPIO();
        initClockTo16MHz();
        initUART();
    
        __bis_SR_register(GIE);
    
        // Example use of timer to send periodic message to PC
        // Skip this if you are sending other messages
        // Configure timer to periodically transmit string
        TA0CCTL0 |= CCIE;                             // TACCR0 interrupt enabled
        TA0CTL |= TASSEL__SMCLK | MC__CONTINUOUS | ID__8;     // SMCLK, continuous mode
    
        while (1)
        {
            // Enter LPM0 and wait for interrupt to wake the CPU
            __bis_SR_register(LPM0_bits | GIE);
    
            // Ok we are awake so
            // Check if message was received and send an acknowledgment
            if(msg_received == true)
            {
                TransmitData("Thanks!\r\n", 9);
                msg_received = false;
            }
        }
    }
    
    
    //******************************************************************************
    // USCI_A0 ISR HANDLER
    //******************************************************************************
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    {
        switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG))
        {
            case USCI_NONE: break;
            case USCI_UART_UCRXIFG:
                  P1OUT |= BIT7;                      // Turn on RX LED
                  UCA0IFG &=~ UCRXIFG;              // Clear interrupt
                  *pRXBuffer = UCA0RXBUF;             // Clear buffer
                  if (UCA0RXBUF == '\r')            // This works because my terminal app sends CR only (\r).  If yours sends CR + LF change this to '\n'
                      msg_received = true;
                  P1OUT &= (~BIT7);                  // Turn off RX LED
    
                  __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti
                  break;
    
            case USCI_UART_UCTXIFG:
                UCA0TXBUF = *pTXBuffer++;
                if(--bytesToSend == 0)
                {
                    UCA0IE &= ~UCTXIE;            // Disable USCI_A0 TX interrupt after last byte of string has been transmitted.
                    P1OUT &= (~BIT6);             // Turn off TX LED
                    uart_busy = false;
                    __bis_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti
                }
    
                break;
            case USCI_UART_UCSTTIFG: break;
            case USCI_UART_UCTXCPTIFG: break;
        }
    
    }
    
    
    // Set our test message as const so it will be placed in FRAM, not RAM
    const uint8_t HelloMsg[] = "Hello MSP430 World - Have a great day!\r\n";
    
    //******************************************************************************
    // TIMER0_A0 ISR HANDLER - Automatically transmits message to PC terminal
    //******************************************************************************
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A (void)
    {
        static int count = 40;
        uint8_t length;
    
        if(--count == 0)
        {
            count = 40;
            // # of bytes to send is one less than the string length.
            // Compiler added '0' to end of our string and we don't want to send it.
    // TO ENABLE SENDING STATIC MESSAGE, SET #if 1
    // TO ENABLE SENDING DYNAMIC MESSAGE, SET #1 0
    
    #if 0
           // Send static message
           TransmitData((uint8_t*) HelloMsg, sizeof(HelloMsg)-1);
    
    #else
           // Send dynamic message - in this case the current value of timer
           //Use sprintf() function to automatically convert TA0R into ASCII
           length = sprintf((char*)TXDataBuffer, "%d\r\n", TA0R);
    
           TransmitData(TXDataBuffer, length);
    #endif
    
        }
    }
    

  • First of all thank you!

    I have one question. If I want to communicate trough an USB cable, do I have to write what you said P1SEL |= {GPIO_PIN4 | GPIO_PIN5}; , or just change the position of the jumpers on the board?

    Thanks

  • All you need to do is ensure the RX and TX jumpers are installed.

    Take a look at section 2.2.4 in the FR2433 Launchpad User's guide

    Yes, P1SEL |= (GPIO_PIN4 | GPIO_PIN5) **** Note the use of "()" and not "{}" as you have in the previous reply..

  • Hello,

    I haven’t heard from you in several days now, so I’m assuming you were able to resolve your issue.
    If this isn’t the case, please click the "This did NOT resolve my issue" button and reply to this thread with more information.
    If this thread locks, please click the "Ask a related question" button and in the new thread describe the current status of your issue and any additional details you may have to assist us in helping to solve your issues.

**Attention** This is a public forum