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.

UART with MSP430F1611 at 8 Mhz external clock, 38400 Baud -- Rx interrupt enabling

Other Parts Discussed in Thread: MSP430F149, MSP430F1611

I'm using the sample code that TI has given for the MSP430F149: fet140_uart11_19200_2.c ; I'm porting it to the MSP430F1611 to communicate with an RFID module.

I can see the response from the module on my oscilloscope, so I've gotten the baud rate of 38400 done correctly. The output of the module is put into Pin 3.7 (URXD1).

My problem is, for some reason, the Rx interrupt doesn't become activated! It must have something to do with my watchdog timer, because that's the only thing I really added to the original sample code. If someone could tell me what to do to fix this problem (keep both the watchdog timer and enable the Rx interrupt correctly), I'd really appreciate it.

 

 Here's my code (I apologize for the formatting):

//******************************************************************************

// MSP-FET430P140 Demo - USART1, UART 19200 Echo ISR, XT2 HF XTAL SMCLK

//

// Description: Echo a received character, RX ISR used. Normal mode is LPM0,

// USART1 RX interrupt triggers TX Echo. Though not required, MCLK= XT2.

// ACLK =n/a, MCLK = SMCLK = UCLK1 = XT2 = 8MHz

// Baud rate divider with 8Mhz XTAL @19200 = 8MHz/19200 = 416.66 ~ 417 (01A0h)

// //* An external 8MHz XTAL on X2IN X2OUT is required for XT2CLK *//

// //* Min Vcc required varies with MCLK frequency - refer to datasheet *//

//

// MSP430F149

// -----------------

// /|\| X2IN|-

// | | | 8Mhz

// --|RST X2OUT|-

// | |

// | P3.6|------------>

// | | 19200 - 8N1

// | P3.7|<------------

//

//

// M. Buccini

// Texas Instruments Inc.

// Feb 2005

// Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.21A

//******************************************************************************

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#include

 

 

<msp430x16x.h>

 

unsigned

 

 

int

count;

volatile

 

 

unsigned char

RxBuffer[50] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00};

unsigned

 

 

short index;

//index in RxBuffer

unsigned

 

 

short

recieved;

 

void

 

 

main(void

)

{

 

 

volatile unsigned int

i;

count = 1;

index = 0;

recieved = 0;

 

WDTCTL = WDT_ADLY_1000;

 

// Interval timer

IE1 |= WDTIE;

 

// Enable WDT interrupt

 

P3SEL |= 0xC0;

 

// P3.6,7 = USART1 option select

 

BCSCTL1 &= ~XT2OFF;

 

// XT2on

 

 

 

do

{

IFG1 &= ~OFIFG;

 

// Clear OSCFault flag

 

 

for (i = 0xFF; i > 0; i--);

// Time for flag to set

}

 

 

while ((IFG1 & OFIFG));

// OSCFault flag still set?

 

BCSCTL2 |= SELM_2 + SELS;

 

// MCLK= SMCLK= XT2 (safe)

 

ME2 |= UTXE1 + URXE1;

 

// Enable USART1 TXD/RXD

UCTL1 |= CHAR;

 

// 8-bit character

UTCTL1 |= SSEL1;

 

// UCLK = SMCLK

UBR01 = 0xD0;

// 8Mhz/38400 ~ 208

UBR11 = 0x00;

UMCTL1 = 0x00;

 

// no modulation

UCTL1 &= ~SWRST;

 

// Initialize USART state machine

IE2 |= URXIE1;

 

// Enable USART1 RX interrupt

 

 

 

while (1)

{

 

 

//Send the Command

TXBUF1 = 0x02;

 

 

while (!(IFG2 & UTXIFG1));  // USART1 TX buffer ready?

TXBUF1 = 0x00;

 

 

 

while (!(IFG2 & UTXIFG1));  // USART1 TX buffer ready?

TXBUF1 = 0x08;

 

 

 

while (!(IFG2 & UTXIFG1));  // USART1 TX buffer ready?

TXBUF1 = 0x00;

 

 

 

while (!(IFG2 & UTXIFG1));  // USART1 TX buffer ready?

TXBUF1 = 0x22;

 

 

 

while (!(IFG2 & UTXIFG1));  // USART1 TX buffer ready?

TXBUF1 = 0x01;

 

 

 

while (!(IFG2 & UTXIFG1)); // USART1 TX buffer ready?

TXBUF1 = 0x01;

 

 

 

while (!(IFG2 & UTXIFG1));  // USART1 TX buffer ready?

TXBUF1 = 0x00;

 

 

 

 

while (!(IFG2 & UTXIFG1)); //  USART1 TX buffer ready?TXBUF1 = 0x00;

TXBUF1 = 0xEE;

 

 

 

 

while (!(IFG2 & UTXIFG1)); // USART1 TX buffer ready?TXBUF1 = 0x92;

_BIS_SR(LPM0_bits + GIE);

// Enter LPM0

 

}

}

 

#pragma

 

 

vector=USART1RX_VECTOR

__interrupt

 

void usart1_rx (void

)

{

 

 

while (!(IFG2 & UTXIFG1));

// USART1 TX buffer ready?

recieved = 1;

RxBuffer[index] = RXBUF1;

 

 

if

(index>48)

{

index = index;

 

//not circular buffer

}

 

else

{

index++;

}

}

 

#pragma

 

 

vector=WDT_VECTOR

__interrupt

 

void watchdog_timer (void

)

{

count++;

_BIC_SR_IRQ(LPM0_bits); //Leave LMP0 to run for loop again

 

}

  • Here is the code again -- I guess I shouldn't copy from CCS to the board directly. Sorry about that!

    //******************************************************************************
    //  MSP-FET430P140 Demo - USART1, UART 19200 Echo ISR, XT2 HF XTAL SMCLK
    //
    //  Description: Echo a received character, RX ISR used. Normal mode is LPM0,
    //  USART1 RX interrupt triggers TX Echo. Though not required, MCLK= XT2.
    //  ACLK =n/a, MCLK = SMCLK = UCLK1 = XT2 = 8MHz
    //  Baud rate divider with 8Mhz XTAL @19200 = 8MHz/19200 = 416.66 ~ 417 (01A0h)
    //  //* An external 8MHz XTAL on X2IN X2OUT is required for XT2CLK *// 
    //  //* Min Vcc required varies with MCLK frequency - refer to datasheet *// 
    //
    //               MSP430F149
    //            -----------------
    //        /|\|             X2IN|-
    //         | |                 | 8Mhz
    //         --|RST         X2OUT|-
    //           |                 |
    //           |             P3.6|------------>
    //           |                 | 19200 - 8N1
    //           |             P3.7|<------------
    //
    //
    //  M. Buccini
    //  Texas Instruments Inc.
    //  Feb 2005
    //  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.21A
    //******************************************************************************

    #include  <msp430x16x.h>

    unsigned int count;
    volatile unsigned char RxBuffer[50] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00};
    unsigned short index; //index in RxBuffer
    unsigned short recieved;

    void main(void)
    {
      volatile unsigned int i;
      count = 1;
      index = 0;
      recieved = 0;
     
      WDTCTL = WDT_ADLY_1000;                   // Interval timer
      IE1 |= WDTIE;                             // Enable WDT interrupt
     
      P3SEL |= 0xC0;                            // P3.6,7 = USART1 option select

      BCSCTL1 &= ~XT2OFF;                       // XT2on

      do
      {
      IFG1 &= ~OFIFG;                           // Clear OSCFault flag
      for (i = 0xFF; i > 0; i--);               // Time for flag to set
      }
      while ((IFG1 & OFIFG));                   // OSCFault flag still set?

      BCSCTL2 |= SELM_2 + SELS;                 // MCLK= SMCLK= XT2 (safe)

      ME2 |= UTXE1 + URXE1;                     // Enable USART1 TXD/RXD
      UCTL1 |= CHAR;                            // 8-bit character
      UTCTL1 |= SSEL1;                          // UCLK = SMCLK
      UBR01 = 0xD0;        // 8Mhz/38400 ~ 208
      UBR11 = 0x00;                             //
      UMCTL1 = 0x00;                            // no modulation
      UCTL1 &= ~SWRST;                          // Initialize USART state machine
      IE2 |= URXIE1;                            // Enable USART1 RX interrupt

      while(1)
      {
       //TXBUF1 = 0xFF;
          //Send the Command
          TXBUF1 = 0x02;
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
          TXBUF1 = 0x00;
      
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
          TXBUF1 = 0x08;
         
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
          TXBUF1 = 0x00;
         
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
          TXBUF1 = 0x22;
         
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
          TXBUF1 = 0x01; 
         
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
          TXBUF1 = 0x01;
         
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
          TXBUF1 = 0x00;
         
         
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?TXBUF1 = 0x00;
          TXBUF1 = 0xEE;  
         
         
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?TXBUF1 = 0x92;


      _BIS_SR(LPM0_bits + GIE);               // Enter LPM0

      }
    }

    #pragma vector=USART1RX_VECTOR
    __interrupt void usart1_rx (void)
    {
      while (!(IFG2 & UTXIFG1));                // USART1 TX buffer ready?
      recieved = 1;
      RxBuffer[index] = RXBUF1;
      if (index>48)
      {
        index = index; //not circular buffer
      }else{
     index++;
      }
    }

    #pragma vector=WDT_VECTOR
    __interrupt void watchdog_timer (void)
    {  
     count++; 
      _BIC_SR_IRQ(LPM0_bits);                   // leave LMP3
     
    }

  • I do not understand the code.

    You said: //  ACLK =n/a, ...

    Yet, you use: WDTCTL = WDT_ADLY_1000;

    Inside the watchdog_timer isr, you have: count++;

    What is "count" for? 


  • Hi,

    Sorry -- I didn't clean up any of the commenting / lines mainly used for debugging when posting it. I mainly put it up to show how I set up the interrupts.

    "count" is just for tracking purposes while debugging; I use it to keep track of how often I send the link of commands to the RFID module; as in, how many times I've asked it for tag ID information.

    My main goal is to figure out why the Rx interrupt isn't functioning; I can watch the input into the Rx pin on the microcontroller, and I just want to store the bytes into the buffer. For some reason, the interrupt isn't activated.

     

  • Revathi Murthy said:

    volatile unsigned int i;

    do
      {
      IFG1 &= ~OFIFG;                           // Clear OSCFault flag
      for (i = 0xFF; i > 0; i--);               // Time for flag to set
      }
      while ((IFG1 & OFIFG));                   // OSCFault flag still set?

    First, for local variables, the volatile keyword is usually void, as the compiler KNWOS that nobody but the current function has a reference on this variable. So it won't keep the compiler from optimizing your waiting loop away. You should plae a __no_operation() into the loop to ensure that it is at least 255 cycles long (even if it might measn the compiler is unrolling to loop to 17 cycles with 15 NOPs inside. Or use the delay_cycles() function. Furthermore, you cannot clear OFIFG properly if you have XT1 still enabled and it is not running. You'll need to set the OSCOFF bit in SR to disable XT1 and keep it from settign OFIFG again after some time.

    In your current setup it is possible that the crystal is still not up and running when the check succeeds. And then, the USART runs on DCO frequency (switching to XT2 fails) instead (800kHz instead of the intended 8MHz). And of course the external device will see 'something' coming in with 3840Bd and responds with an error at 38400Bd which of course the USART won't understand. (parity/framing error, but you don't trigger an ISR for errors, nor do you check for them)

    The RX/TX code itself looks fine and should do. Except that you wait in our ISR for UTXIFG for no apparent reason (it was necessary in teh demo as it was copying from RXBUF to TXBUF inside the RX ISR, but you don't, so remove this line)

     

  • Hi Jens-Michael,

    "Furthermore, you cannot clear OFIFG properly if you have XT1 still enabled and it is not running. You'll need to set the OSCOFF bit in SR to disable XT1 and keep it from settign OFIFG again after some time."

    I implemented all of your recommended changes except for this one; how do I do this? Sorry, I'm still trying to figure this stuff out on the fly.

  • Well, I was not very clear at this point.

    It wasn't meant to be a solution, just a necessary step to ensure that XT2 is running.

    First set the OSCOFF bit in SR (__BIS_SR...), then perform the OFIFG check with XT2 (XT1 won't interfere now). When you're sure that XT2 is running properly, you of course have to clear the OSCOFF bit again so the XT1 is activated. Then proceed and ignore OFIFG in future. It will, however, nullify the option of getting warned by a later  XT2 failure if XT1 has problems with OFIFG.

    Well, other systems have no crystal checking at all. The ATMega128, if the crystal isn't running, cannot even programmed (including the oscillator settings).

  • Ok, I will give that a shot.

    Do these recommendations apply for a crystal, a crystal oscillator, or both?

    Currently, I have an 8 MHz crystal oscillator connected, but I also have a 10 Mhz crystal that I could put in with 20 pF caps to ground; which would be better for my application?

  • A crystal oscillator should require a different setup of the clock system: digital oscillator input instead of HF crystal. And when digital input is selected, the whole OFIFG mechanism should be disabled for this clock source (no OFIFG if the oscillator fails).

    Anyway, I'd recommend a crystal if power consumption is an issue. The MSPs crystal driving circuit is optimized for low power consumption and also allows deactivating the crystal if not required for a longer time, while an external oscillator usually consumes much more power and does so continuously.

    Arew you sure 20pF is okay for the 10MHz quartz? This results in only 11pF effective load (20||20 pF for the capacitors and 1pF for the processor pins), which seems a bit low to me. Check the crystals datasheet for the required load..

**Attention** This is a public forum