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; } } }