This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

UART1 issue at 115k baud on LPC2368?

Hi all,

I am trying to get a simple pass thru of data at 115k from uart 1 to
uart 0 on an lpc2368. Both are enabled (powered) and if I use 9600 baud
rates, everything is fine. I'm running the unit off the 4MHz IRC. I
then bumped uart0 up to 115k, had to switch the fractional baud rate
settings. No problem, have 9600 baud message coming in UART1, shooting
out UART0 at 115k.

Then, I tried getting UART1 up to 115k. Should have just been setting
the same values for the fractional baud rate and I'd be in good shape,
right? Not so much. The data coming in is all garbled as if the
fractional change isn't taking.

The UART code is running with receive and transmit interrupts enabled.
I'm running a 1 millisecond timer on timer 0, PWM is active in the
background as well. In addition, I have UART2 running and accepting 1 Hz messages at 9600 baud.

The problem is UART1. Again, at 9600 baud on UART1, the code is all
functioning correctly. But when I bump it to 115k, it cis not receiving correctly.

For what it is worth, here is the init code for UART1:

/***********************************************************************\ 
******/
void uart1Init(uint16_t baud, UCHAR mode, UCHAR fmode)
{
U1IER = 0x00; // disable all interrupts
U1IIR; // clear interrupt ID
U1RBR; // clear receive register
U1LSR; // clear line status register

// set the baudrate
U1LCR = ULCR_DLAB_ENABLE; // select divisor latches
U1DLL = (UCHAR)baud; // set for baud low
byte
U1DLM = (UCHAR)(baud >> 8); // set for baud high byte

if((baud == B115200) || (baud == B57600)) //Fractional baud rate
needed here!!! 115k and 57.6k are 8.51% error otherwise
{
U1FDR |= (1 << U1FDR_DIVADDVAL_BIT); //DivAddVal = 1
U1FDR |= (12 << U1FDR_MULVAL_BIT); //MulVal = 12
}

// set the number of characters and other user specified operating
parameters
U1LCR = (mode & ~ULCR_DLAB_ENABLE);
U1FCR = fmode;

#ifdef UART1_TX_INT_MODE
uart1_tx_extract_idx = uart1_tx_insert_idx = 0;
uart1_tx_running = 0;
#endif

#ifdef UART1_RX_INT_MODE
// initialize data queues
uart1_rx_extract_idx = uart1_rx_insert_idx = 0;

// enable receiver interrupts
U1IER |= UIER_ERBFI;
#endif
}

Does anyone have any ideas / suggestions to look at on this? I have
electrically scoped the system when it is running at 115k and verified
that the same test data is coming into the port electrically at the
higher baud rate. I just can't seem to get the LPC to suck in the bits
at 115k vs. 9600.

Thanks!

  • More information -

    I had debug code in on UART0, and was incorrect. It does not read characters correctly at 115k either. Both ports are outputting at 115k correctly, and both can input/output at 9600 (so pin selections, modes seem to be o.k.).

    Any suggestions where to look to see why the ISR isn't reading right at 115k on either UART0 or UART1?

  • Have you verified your baudrates with an oscilloscope? Both the baudrate of the data sent to the uC, and the baudrate of the data it sends out.

  • Hello, thanks for the response.

    I have verified both with a scope.

    Also, I have a separate uC module sending and receiving on UART1. If I pull that module off and attach it to the PC via an FTDI level converter, it operates correctly in both directions.

    The ARM is sending 115k data correctly out (so it seems that the timing is correct), but is not triggering and / or is showing corrupt data on the receive buffer.

    Here is a snip of my UART1 ISR routine. Both TX and RX interrupt defines are defined...

    void uart1ISR(void)
    {
      UCHAR iid;
    
      // loop until not more interrupt sources
      while (((iid = U1IIR) & UIIR_NO_INT) == 0)
        {
        // identify & process the highest priority interrupt
        switch (iid & UIIR_ID_MASK)
          {
          case UIIR_RLS_INT:                // Receive Line Status
            U1LSR;                          // read LSR to clear
            break;
    
    #ifdef UART1_RX_INT_MODE
          case UIIR_CTI_INT:                // Character Timeout Indicator
          case UIIR_RDA_INT:                // Receive Data Available
            do
              {
              uint16_t temp;
    
              // calc next insert index & store character
              temp = (uart1_rx_insert_idx + 1) % UART1_RX_BUFFER_SIZE;
              uart1_rx_buffer[uart1_rx_insert_idx] = U1RBR;
    
              // check for more room in queue
              if (temp != uart1_rx_extract_idx)
                uart1_rx_insert_idx = temp; // update insert index
              }
            while (U1LSR & ULSR_RDR);
    
            break;
    #endif
    
    #ifdef UART1_TX_INT_MODE
          case UIIR_THRE_INT:               // Transmit Holding Register Empty
            while (U1LSR & ULSR_THRE)
              {
              // check if more data to send
              if (uart1_tx_insert_idx != uart1_tx_extract_idx)
                {
                U1THR = uart1_tx_buffer[uart1_tx_extract_idx++];
                uart1_tx_extract_idx %= UART1_TX_BUFFER_SIZE;
                }
              else
                {
                // no
                uart1_tx_running = 0;       // clear running flag
                break;
                }
              }
    
            break;
    #endif // UART1_TX_INT_MODE
    
          case UIIR_MS_INT:                 // MODEM Status
            U1MSR;                          // read MSR to clear
            break;
    
          default:                          // Unknown
            U1LSR;
            U1RBR;
            U1MSR;
            break;
          }
        }
    }