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.

MSP430F249: 3019066632

Part Number: MSP430F249

Good day,

I am using the following initialization but continue to get errors:

UCA0CTL0 |= 0x00; // No parity, LSB first, 8-bit character, one stop bit,UART mode, Asynchronous mode
UCA0CTL1 |= 0x40; // ACLK
UCA0CTL1 |= UCSWRST; // Disable the UART.
UCA0MCTL |= UCBRF_4 + UCBRS_7 + UCOS16; // 230,400 baud.
// UCA0MCTL |= UCBRF_3 + UCBRS_5 + UCOS16; // 230,400 baud (original).
UCA0BR0 |= 0x05; // Upper byte of baud rate prescalar, 230,400 baud.
UCA0BR1 |= 0x00; // Lower byte of baud rate prescalar.

UCA0CTL1 &= ~UCSWRST; //Enable the UART.

The ACLK is 16 MHz and appears to be stable and clean.

I have tried various values for UCA0MCTL but can't find a combination that correctly collects data from the incoming RX. The line that is commented out previously worked but does no longer.

Please advise.

  • What errors are you getting? An occasional bit error? Missed Characters? or complete lack of response.

  • Show the code where you read the receive register.

  • All three error bits in UCA0STAT are consistently set and UCA1RXBUF often contains a 0x5F. The incoming packet header (first byte) is 0x5A but is never detected.

  • //& UART Read****************************************************************************************
    //
    // Read a packet of data from the UART into the Upstream_Data[] array.?????
    //
    //**************************************************************************************************
    switch(Serial_Rd_State) // ***** Beginning of the UART read packet state machine *****
    {

    case Ser_Rd_Start: // Wait for Host to send a packet header.
    if(UCA0RXIFG == ( UCA0RXIFG & IFG2 ) ) {
    P3OUT &= ~LED1n; // Turn on led
    Packet_Header = UCA0RXBUF; // Read a byte from the serial port.
    IFG2 &= ~UCA0RXIFG;
    CmpChecksum = Packet_Header; // Initialize checksum.
    System_Flags |= UART_RX_BUSY; // Set the busy flag.
    UART_timer = 0; // Reset timer

    if( Packet_Header == 0X5A ) { // If the packet header has been received, then...
    Upstream_Pointer = 0; // ...initialize the array index, and...
    Upstream_Data[Upstream_Pointer] = Packet_Header; // Write data to buffer memory.
    Upstream_Pointer++;

    Serial_Rd_State = Ser_Rd_Cmd; // ...collect the rest of the packet.
    }
    P3OUT |= LED1n; // Turn off led
    }
    break;

    case Ser_Rd_Cmd: // Wait for Host to send a packet header.
    if(UCA0RXIFG == ( UCA0RXIFG & IFG2 ) ) {
    Packet_Command = UCA0RXBUF; // Read the next byte from the serial port.
    IFG2 &= ~UCA0RXIFG;

    Serial_Port_Data = Packet_Command; // Parse command.
    Upstream_Data[Upstream_Pointer] = Packet_Command; // Write data to buffer memory.
    Upstream_Pointer++;
    CmpChecksum += Packet_Command; // Add next byte to checksum.

    Serial_Rd_State = Ser_Rd_BNum;
    }
    break;

    case Ser_Rd_BNum: //
    if(UCA0RXIFG == ( UCA0RXIFG & IFG2 ) ) {
    Brick_Num = UCA0RXBUF; // Read the next byte from the serial port.
    IFG2 &= ~UCA0RXIFG;

    Upstream_Data[Upstream_Pointer] = Brick_Num; // Write data to buffer memory.
    Upstream_Pointer++;
    CmpChecksum += Brick_Num; // Add next byte to checksum.

    if( Brick_Num > 5 ) { Serial_Rd_State = Ser_Rd_CSum; }

    else if( Packet_Command == 0x42 ) {
    System_Flags |= DNSTREAM_TX_START; // Start the next transfer to the Master.

    Serial_Rd_State = Ser_Rd_Data;
    }

    else{
    Error_CountA++;
    Serial_Rd_State = Ser_Rd_Start;
    }
    }
    break;

    case Ser_Rd_Data: //
    if(UCA0RXIFG == ( UCA0RXIFG & IFG2 ) ) {
    Upstream_Data[Upstream_Pointer] = UCA0RXBUF; // Write data to buffer memory.
    IFG2 &= ~UCA0RXIFG;

    CmpChecksum += Upstream_Data[Upstream_Pointer]; // Add next byte to checksum.
    Upstream_Pointer++;

    if( Upstream_Pointer >= Rx_Packet_Length - 1 ) { Serial_Rd_State = Ser_Rd_CSum; }
    }
    break;

    case Ser_Rd_CSum: //
    if(UCA0RXIFG == ( UCA0RXIFG & IFG2 ) ) {
    PktChecksum = UCA0RXBUF; // Read the next byte from the serial port.
    IFG2 &= ~UCA0RXIFG;

    Upstream_Data[Upstream_Pointer] = PktChecksum; // Write data to buffer memory.
    Upstream_Pointer++;
    Packet_Count++;
    System_Flags &= ~UART_RX_BUSY; // Clear the busy flag.
    System_Flags |= NEW_PKT_RDY; // Set the new packet flag.

    // if( PktChecksum != CmpChecksum ) {
    // P3OUT &= ~LED0n; // Turn LED on. ***** Test Code! *****
    // P3OUT |= LED0n; // Turn LED off. ***** Test Code! *****
    // }

    Serial_Rd_State = Ser_Rd_Start;
    }
    break;

    case Ser_Rd_Timeout: // Reset the UART and restart state machine
    UCA0CTL1 |= UCSWRST; //Disable the UART.
    System_Flags &= ~UART_RX_BUSY; // Clear the busy flag.
    Serial_Rd_State = Ser_Rd_Start;
    UCA0CTL1 &= ~UCSWRST; //Enable the UART.
    break;

    } // ***** End of the UART read packet state machine *****

    } // Endif the Brick_Col is == zero.


    if( Brick_Col > 0 ) {
    //& Upstream Read*****************************************************************************************
    //
    // Read a packet of data from the Upstream Port into the Upstream_Data[] array.?????
    //
    //*************************************************************************************************

    switch(Upstream_Pkt_Rd_State) // ***** Beginning of the Upstream packet read state machine *****
    {

    case Upstr_Read_Start: // If Upstream port has data, start up the read state machine.
    if(( INPUT_DIR & ~P6IN ) && ~(MASTER_TX_BUSY == ( MASTER_TX_BUSY & System_Flags ))) { // see if INPUT_DIR is low and Master TX not busy
    if (ATTN_INn & ~P2IN) { // Wait for Attention signal from up stream card.
    // Set UpStream port to receive
    P2DIR = ACK_INn + RDY_IN; // Set output pins.
    P2OUT &= ~RDY_IN; // Deassert RDY_IN.
    P2OUT &= ~ACK_INn; // Send an acknowledge to the upstream card.

    Upstream_Pointer = 0; // Initialize array index.
    System_Flags |= UPSTREAM_RX_BUSY; // Set the busy flag.
    Upstr_timer = 0;

    Upstream_Pkt_Rd_State = Upstr_Rd_Wait_OE_Low; // Go wait for output enable from the upstream card.
    }
    }
    break;

    case Upstr_Rd_Wait_OE_Low: // Wait for the output enable to come true.
    if (ATTN_INn & ~P2IN) { // Check to be sure the transmission was not terminated prematurely.
    if( OE_INn & ~P2IN ) { // If the output enable is low then...
    Upstream_Pkt_Rd_State = Upstr_Read_Data; // Go start collecting data from the port.
    }
    }
    else{ Upstream_Pkt_Rd_State = Upstr_Rd_Error; } // Transmission was terminated
    break;

    case Upstr_Read_Data: // Read a byte of data and store into Upstream_Data.
    if (ATTN_INn & ~P2IN) { // Check to be sure the transmission was not terminated prematurely.
    if( OE_INn & P2IN ) { // If packet is complete, then exit.
    P2OUT |= ACK_INn; // Remove the acknowledge to the upstream card.
    Upstream_Pkt_Rd_State = Upstr_Rd_Check_OE; // Rearm state machine.
    }
    else if( CLK_IN & P2IN ) {
    Temp_DataA = P1IN; // Read data from the port.
    Upstream_Data[Upstream_Pointer] = Temp_DataA; // Read data from the port.
    P2OUT |= RDY_IN; // The error signal is being used as a ready line.

    // if( Upstream_Pointer < Rx_Packet_Length ) { CmpChecksum += Temp_DataA; }

    Upstream_Pointer++; // Increment the byte count/array index.

    Upstream_Pkt_Rd_State = Upstr_Rd_Wait_CLK_Low;
    }
    }
    else{ Upstream_Pkt_Rd_State = Upstr_Rd_Error; } // Transmission terminated
    break;

    case Upstr_Rd_Wait_CLK_Low: // Wait for CLK in to go low, then clear ready line.
    if (ATTN_INn & ~P2IN) { // Check to be sure the transmission was not terminated prematurely.
    if( CLK_IN & ~P2IN ) {
    P2OUT &= ~RDY_IN; // Clear the ready line.
    Upstream_Pkt_Rd_State = Upstr_Read_Data;
    }
    }
    else{ Upstream_Pkt_Rd_State = Upstr_Rd_Error; } // Transmission terminated
    break;

    case Upstr_Rd_Check_OE: // Exit if output enable is false, otherwise get next byte.
    if (ATTN_INn & P2IN) { // Check to be sure the transmission was not terminated prematurely.
    System_Flags &= ~UPSTREAM_RX_BUSY; // Clear the busy flag.
    // TBD for testing using test data and Up to Dnstream loopback remove the next line
    System_Flags |= NEW_PKT_RDY; // Set the new packet flag.
    Upstream_Pkt_Rd_State = Upstr_Read_Start; // Rearm state machine.

    // Set UpDtream port to idle state
    P2DIR = 0x00; // All inputs.
    P2REN = 0xFF; // Enable pullups.
    P2OUT = ATTN_INn + ACK_INn + OE_INn + SP1_INn + SP2_INn; // Signals pulled high, not listed pulled low.

    }
    break;

    case Upstr_Rd_Error: // Upstream packet error, shutdown and exit state machine.
    // Set UpDtream port to idle state
    // P2SEL = 0x00; // Set port all GPIO.
    P2DIR = 0x00; // All inputs.
    P2REN = 0xFF; // Enable pullups.
    P2OUT = ATTN_INn + ACK_INn + OE_INn + SP1_INn + SP2_INn; // Signals pulled high, not listed pulled low.

    System_Flags &= ~UPSTREAM_RX_BUSY; // Clear the busy flag.
    Upstream_Pkt_Rd_State = Upstr_Read_Start; // Initialize the state machine for the next start sequence.
    break;
    } // ***** End of the Upstream packet read state machine *****
    } // Endif the Brick_Col is > zero.

  • UCA0BR0 |= 0x05; // Upper byte of baud rate prescalar, 230,400 baud.

    User Guide (SLAU144J) Table 15-5 seems to recommend UCBR=4, rather than =5 (with UCBRS=5, UCBRF=3, UCOS16=1), for 230400bps with BRCLK=16MHz. Have you tried that?

  • Better but only receiving 1 or 2 characters. It is finding the 0x5A packet header! Still getting UCOE and UCRXERR after capturing the 0x5A.

  • This seems awfully complicated. Have you considered an interrupt?

    http://www.simplyembedded.org/tutorials/msp430-uart/

    You can also check out the examples in the Resource Explorer.

  • UCOE would be something different. It means you didn't fetch RXBUF quickly enough, so it takes (at least) one full byte time (43usec at 230.4kbps) to happen (whether the byte is correct or not).

    First guess is that you're spending too long in your state machine. I don't see code to check OE/RXERR; are you looking at UCA0STAT at a breakpoint? (Debugger interactions are quite slow.)

    [Edit: Fixed wording -- as Keith pointed out, there was no mention of an ISR.]

  • Where can I find good examples of C code for ISR and data management routines for the UARTs in the MSP430FXXX microcontrollers?

  • The TI Examples are here:

    https://dev.ti.com/tirex/explore/node?node=A__ABSUuF.BG8myJ5a9tne2iA__msp430ware__IOGqZri__LATEST

    These focus mostly on exercising the peripherals (including interrupts), not on higher-level functions.

    5-minutes-with-Google ("msp430 uart github") turned up some candidates. I haven't tried it, but from a brief skim,  pepyakin's "msp430-uart" example has a ring-buffer implementation which might be useful, and appears to be (a) fairly simple and (b) written with the F2 series in mind. 

  • I agree that this is overly complicated. It must be if you are getting overrun errors with ~700 MCLKs between received bytes.

    Here is a packet receive routine written for the F249 some time ago. It uses a timer to reset the state machine in the event of a timeout. Intended for a 9500 bps link but simple enough so operation in your case should be fine. Best used as an example rather than used literally.

     
    __attribute__((interrupt(USCIAB0RX_VECTOR))) void rxISR(void)
    {
      static int i, count;
      int c;
    
      if(IFG2 & UCA0RXIFG)
        {
          if(UCA0STATW & UCRXERR)         // receive error flag set?
            {
              c = UCA0RXBUF;   // drop the received character
              return;
            }
          c = UCA0RXBUF;   // get the received character
          switch(rx_state)
            {
            case 0:     // Drop all received characters in state 0
              break;         
            case 1:     // scanning for SYNC character
              if(c == PSYNC)
                {
                  LED2_ON;
                  TBCCR1 = TBR + CHAR_TIMEOUT;  // reset timeout timer
                  i = 0;
                  rx_state = 2;
                }
              break;
            case 2:
              TBCCR1 = TBR + CHAR_TIMEOUT;  // reset timeout timer
              RPacketBuf[i++] = c;
              if(i == 3)         // this should be the count of bytes in the data packet
                {
                  count = c+5;       // Don't forget the header and CRC
                  rx_state = 3;
                }
              break;
            case 3:
              TBCCR1 = TBR + CHAR_TIMEOUT;  // reset timeout timer
              if(i < BUFSIZE)     // Drop all characters that don't fit buffer
                RPacketBuf[i++] = c;
              if(i >= count)
                {
                  LED2_OFF;
                  P3OUT &= ~TXDEN;          // Disable RS-485 transmitter 
                  rx_state = 0;
                  recv_flag = RECV_OK;
                  TBCCTL1 &= ~CCIE;  // disable compare interrupt
                  add_event(RPACKET);  // add received packet event
                  WAKEUP;
                }
              break;
            default:
              P3OUT &= ~TXDEN;          // Disable RS-485 transmitter
              rx_state = 0;
              recv_flag = RECV_IDLE;
            }
        }
      //  else
      // B0 interrupt
    }
    
    

    Simpler would be an ISR filling a FIFO buffer so allow for a slower foreground task to assemble packets.

**Attention** This is a public forum