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.

A UART problem...

Hi All,

I’m working with the CC430F137 chip.

While it’s P1.7 and P1.6 are connected to a UART source of 4800 bps I’ve configured the program as follows:

void UART_function (void)

{

WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

 

  PMAPPWD = 0x02D52;                        // Get write-access to port mapping regs 

  P1MAP6 = PM_UCA0TXD;                      // Map UCA0TXD output to P1.6

  P1MAP7 = PM_UCA0RXD;                      // Map UCA0RXD output to P1.7

  PMAPPWD = 0;                              // Lock port mapping registers

 

  P1DIR |= BIT6;                            // Set P1.6 as TX output

  P1SEL |= BIT6 + BIT7;                     // Select P1.6 & P1.7 to UART function

 

  *pNMEA_Buffer = UCA0RXBUF;                // Read the info

  pNMEA_Buffer++;                           // update the address

 

  UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**

  UCA0CTL1 |= UCSSEL_1;                     // CLK = ACLK

  UCA0BR0 = 0x06;                           // 4800

  UCA0BR1 = 0x00;                           //

  UCA0MCTL |= UCBRS_7+UCBRF_0;              // Modulation UCBRSx=6, UCBRFx=0

  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

  UCA0IE |= UCRXIE;                         // Enable USCI_A1 RX interrupt

 }

// Echo back RXed character, confirm TX buffer is ready first

#pragma vector=USCI_A0_VECTOR

__interrupt void USCI_A0_ISR(void)

{

  switch(__even_in_range(UCA0IV,4))

  {

  case 0:break;                             // Vector 0 - no interrupt

  case 2:                                   // Vector 2 - RXIFG

    while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?

    UCA0TXBUF = UCA0RXBUF;                  // TX -> RXed character

    break;

  case 4:break;                             // Vector 4 - TXIFG

  default: break;

  }

}

But it seems that I can’t read the correct baud rate (i.e. 4800).

Can someone check my 4800 configuration?

 

Thanks,

Shimon.

  • What baud rate do you observe?

    Are you observing any transmission of data?

  • Hi Bordon,

    When I step by step sometimes I can see the received information.

    But when I'm doing it without any breakpoint I can see that my buffer doesn't have any information and because of it, It seems to me that I haven't configured the correct baud rate (is it configured to 4800?).

    Regarding the baud rate I really don't know what the observed baud rate.

    Thanks,

    Shimon.

     

  • Shimon Shamsiyan said:
    *pNMEA_Buffer = UCA0RXBUF;                // Read the info
      pNMEA_Buffer++;                           // update the address

    What purpose does it server? You don't have the USCI configured yet, let alone received something, but you read the content of the RX buffer and increment the receive buffer pointer? It makes no sense.

    Also, your ISR makes no sense. It is called when somethign has been received, moves the inptu to th eoutput and exits. A simple echo. Is htis what you want?
    BTW: the busy-waiting loop inside the ISR is nonsense, unless you stuff TXBUF outside the ISR. WHen you received for echoing, it is 100% sure that the previously echoed byte has been sent, since both directions run on the same speed. Yes, I know this is copied form the TI example.

    However, the setup seems to be okay.

  • Hi All,

     

    I've tried to do the following but it seems to be not falling on the Interrupt,

    So what's the problem? What shall I change?

     

    Thanks,

    Shimon

     

     

    void UART_function (void)

    {

    WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

      PMAPPWD = 0x02D52;                        // Get write-access to port mapping regs

      P1MAP6 = PM_UCA0TXD;                      // Map UCA0TXD output to P1.6

      P1MAP7 = PM_UCA0RXD;                      // Map UCA0RXD output to P1.7

      PMAPPWD = 0;                              // Lock port mapping registers

      P1DIR |= BIT6;                            // Set P1.6 as TX output

      P1SEL |= BIT6 + BIT7;                     // Select P1.6 & P1.7 to UART function

     

      UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**

      UCA0CTL1 |= UCSSEL_1;                     // CLK = ACLK

      UCA0BR0 = 0x06;                           // 4800

      UCA0BR1 = 0x00;                           //

      UCA0MCTL |= UCBRS_7+UCBRF_0;              // Modulation UCBRSx=6, UCBRFx=0

      UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

      UCA0IE |= UCRXIE;                         // Enable USCI_A1 RX interrupt

    }

    // Echo back RXed character, confirm TX buffer is ready first

    #pragma vector=USCI_A0_VECTOR

    __interrupt void USCI_A0_ISR(void)

    {

     

      switch(__even_in_range(UCA0IV,4))

      {

      case 0:break;                             // Vector 0 - no interrupt

      case 2:                                   // Vector 2 - RXIFG

        while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?

        UCA0TXBUF = UCA0RXBUF;                  // TX -> RXed character

       *pNMEA_Buffer = UCA0RXBUF;                // Read the info

        pNMEA_Buffer++;                           // update the address

        break;

      case 4:break;                             // Vector 4 - TXIFG

      default: break;

      }

    }

    Thanks,

    Shimon.

  • Shimon Shamsiyan said:
    What shall I change?

    Oen thing you could do is changing from partially to fully posting your code.
    I tis possible that you never globally enable interrupts, btu I cannto tell because you didn't post your main funciton. Maybe you never call UART_function? I cannot know.

    And of course ther eis always a chance of a hardware error. RX and TX swapped, improper connection of the MSP with the PC (do you have anexternal level shifter? TTL UART signals are not RS232/COMx signals even though the protocol is the same. But the voltage levels and polarity are different.

  • Hi all,

     

    Regarding the last request attach the last request the main function...

     

    volatile char *pNMEA_Buffer;

    volatile char NMEA_Buffer[200];

     

    int main(void)

    {

      i = 0;

      P1DIR |= BIT6;                            // Set P1.6 as TX output

      P1SEL |= BIT6 + BIT7;                     // Select P1.6 & P1.7 to UART function

     

      while (1)

      {

          __bis_SR_register(GIE);  

         __enable_interrupt();

        asm("EINT");

        UART_function ();

        if (i >= 199)

          break;

      }

      i = 0;

    }

     

    I hope that it could help you all find my problem...

    Thanks,

    Shimon.

    P.S. I've also tried to add the following lines:

      __bis_SR_register(GIE);  

    __enable_interrupt();

    On the while (1) that is located on the main, because it seems that when I'm runnig the program and inputing to the MSP the UART information the unit doesn't reach the

    #pragma vector=USCI_A0_VECTOR

    __interrupt void USCI_A0_ISR(void) 

    .

    .

    .

    I thought that it's a problem with the GIE bit... but it didn't help...:-(

     

    I need to add another odd info when I'm running the program without any breakpoint it never falls on the: __interrupt void USCI_A0_ISR(void) but when I'm putting any breakpoint on the:  

    void UART_function (void)

    {

    .

    .

    .

    }

    And run it from that step it falls into the interrupt.

    Why does is occur?

     

    Shimon. 

  • Shimon Shamsiyan said:
    while (1)
      {
          __bis_SR_register(GIE); 
         __enable_interrupt();
        asm("EINT");
        UART_function ();
        if (i >= 199)
          break;
      }
    i = 0;
    }

    And here we go.

    What your code does:
    It enables global interrupts. Three times in a row. The first three lines are equivalent (compile to the same processor instrucitons), so two are superfluous. But no harm done here.
    But then...
    You init the UART.
    Then you check whether I is >199 (which isn't, as it is still 0 and never changes), then you loop, enable the itnerrupts gain three times and re-init the UART. So oyu reset the UART every few CPU cycles, never giving it a chance to receive anything (except if you break between two inits).

    What is I intended to do? It is initialized to 0, never incremented and checked whether it is >199.

    Restructure your program as follows:

    [...]
    UART_function();
    __enable_interrupt();
    while(1){
    // do something here while data is received and echoed in the background
    }

    Be sure to never leave main() (stay in the while loop or enter low power mode 0), because depending on compiler, exiting main may put the device into deep sleep, disabling everything.

  • Jens-Michael Gross said:
    [...]
    UART_function();
    __enable_interrupt();
    while(1){
    // do something here while data is received and echoed in the background
    }

    Thanks a lot for your reply can you please expand your reply...

    I.e. I'm building on that chip only the UART information and I've did the following

     

     

    // system

    #include "project.h"

    #include <string.h>

     

    void UART_function (void);

    volatile char NMEA_Buffer[200];

    volatile char *pNMEA_Buffer;

     

    volatile int Read_Data = 0, Starting_Flag = 1;

    volatile int i;

     

    int main(void)

    {

      i = 0;

      P1DIR |= BIT6;                            // Set P1.6 as TX output

      P1SEL |= BIT6 + BIT7;                     // Select P1.6 & P1.7 to UART function

      UART_function ();

      __enable_interrupt();

     

      while (1)

      {

        if (i >= 199)

         break;

      }

      i = 0;

    }

     

    void UART_function (void)

    {

      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

     

      PMAPPWD = 0x02D52;                        // Get write-access to port mapping regs

      P1MAP6 = PM_UCA0TXD;                      // Map UCA0TXD output to P1.6

      P1MAP7 = PM_UCA0RXD;                      // Map UCA0RXD output to P1.7

      PMAPPWD = 0;                              // Lock port mapping registers

     

      P1DIR |= BIT6;                            // Set P1.6 as TX output

      P1SEL |= BIT6 + BIT7;                     // Select P1.6 & P1.7 to UART function

     

      UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**

      UCA0CTL1 |= UCSSEL_1;                     // CLK = ACLK

      UCA0BR0 = 0x06;                           // 4800

      UCA0BR1 = 0x00;                           //

      UCA0MCTL |= UCBRS_7+UCBRF_0;              // Modulation UCBRSx=6, UCBRFx=0

      UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

      UCA0IE |= UCRXIE;                         // Enable USCI_A1 RX interrupt

    }

     

    // Echo back RXed character, confirm TX buffer is ready first

    #pragma vector=USCI_A0_VECTOR

    __interrupt void USCI_A0_ISR(void)

    {

      switch(__even_in_range(UCA0IV,4))

      {

      case 0:break;                             // Vector 0 - no interrupt

      case 2:                                   // Vector 2 - RXIFG

        while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?

        UCA0TXBUF = UCA0RXBUF;                  // TX -> RXed character

       *pNMEA_Buffer = UCA0RXBUF;                // Read the info

        pNMEA_Buffer++;                           // update the address

        i++;

        break;

      case 4:break;                             // Vector 4 - TXIFG

      default: break;

      }

    }

    And it seems to me that I need to do/check/insert a few more code on the while (1) loop.

    Can you please help me with it?

     

    Thanks a lot again,

    Shimon.

     

     

  • Shimon Shamsiyan said:
    And it seems to me that I need to do/check/insert a few more code on the while (1) loop.

    Well, you probably want to do something with what you receive.

    But first, you should init pNMEA_Buffer. (e.g. volatile char * pNMEA_Buffer = pNMEA_Buffer;). You also might want to make your  buffer (and the pointer) unsigned char instead of [signed] char.

    Now the loop should first calculate the 'fill level' of your buffer:

    i = pNMEA_Buffer - NMEA_Buffer; This gives the current 'count'.

    if i is >199 it means your input buffer overflows next byte. So reset the buffer pointer:

    pNMEA_Buffer = pNMEA_Buffer;

    You might also check whether the byte at *pNMEA_Buffer is a CR. If so you might want to process the buffer and rese the pointer to beginning, even if less than 200 bytes have been received yet. It depends of the type of data you transmit.

    I'd also put the threshold one or two bytes less than the array length, jsu tto be sure you don't miss the correct point. Or do a check in the ISR (drop any surplus data and don't echo it). If teh write pointer isn't reset befor eit points behind the array, you start overwriting other variables, maybe even the pointer itself, with incoming data. Strange things iwll happen then.

    You may also light an LED when the user hits ENTER, or toggle it on every incoming character or on certain charactrers.
    The current code is not really suited for sending a text back, as incoming and outgoing text would interfere (the ISR is echoing incoming data).

  • Hi Jens and all,

    1st: Thanks a lot for your reply answer.

    2nd: There seems to be right now a problem on the code, because of on that stage although the code is opened there seems to be a problem that it never gets to the breakpoint that is located on the interrupt.

    3rd: There is something missing on it.

    Moreover, I wanted to thank you all for the received help.

    Waiting for you all help,

    Shimon

  • Shimon Shamsiyan said:
    there seems to be a problem that it never gets to the breakpoint that is located on the interrupt.

    Two things i can think of: first, the baudrate is off. As I already said, the ratio of USCI clock and baudrate is very low, so a high bit error occurs. Worst case, this may cause a framing error and incoming data is discarded and no interrupt is triggered.

    The other reason could be a hardware problem. RX and TX twisted, or a wrong level converter for the RS232 signal (if coming from a PC COM port).

    Also, In a different thread, someone reported a problem that he doesn't get any clock pulses form an attached 32768Hz crystal even though LFXT1OFFG is clear. There is no fallback to REFO too (as it should be). He was not using the CC6137 but rather an F67xx (IIRC), but maybe it's the same problem. Check your ACLK speed (output ACLK to ACLK output pin and use a scope)

    Anoteh ridea: do you use any library functions in your main function? It might be possible that they use the port mapping feeature too, wnd since the por tmapping cano only be changed once per power cycle, your mapping of the pins might be ignored.

    What happens if you actually write something to TXBUF in a loop instead of waiting for incoming data and echoing it? Do you see it on the TX pin? Do you see it on the attached terminal screen? IF you see it on teh pin but not teh terminal screen, check baudrate and signal waveform with a scope.

**Attention** This is a public forum