UART framing error and over run error - pic18f65k40

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Hi guys

Did you guys come across this, I need to receive a packet from another MCU, but only the first 2-3 bytes are correct. But the remaining bytes are wrong. Any thought on this?

my packet is start with \r, and stop with \n. Baud = 19200.
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
This is how I initial the uart:
Code:
    // from other part of the code
    // locking and unlocking code are removed.
    RX5PPS = 0x23;          // UART5 RX map to RE3
    RE2PPS = 0x14;          // UART5 TX map to RE2

void InitUART5(void){

    TRISEbits.TRISE2 = 0;      // TX
    TRISEbits.TRISE3 = 1;      // RX
 
    // 19200 baud rate
    SP5BRGL = 0;
    //SP5BRGL = 25;
    SP5BRGL = 103;
    BAUD5CONbits.BRG16 = 0;
 
    TX5STAbits.BRGH = 1;
 
    TX5STAbits.SYNC = 0;        // asnyc mode
    RC5STAbits.SPEN = 1;        // enable serial port
    TX5STAbits.TX9D = 0;        // 8 bit mode
    BAUD5CONbits.SCKP = 0;      // none inverted transmit
    TX5STAbits.TXEN = 1;        // enable transmission
 
    PIR4bits.TX5IF = 0;         // clear TX interrupt flag
 
    PIE4bits.RC5IE = 1;         // enable RX interrupt
 
    RC5STAbits.CREN = 1;        // enable reception
}
 

Picbuster

Joined Dec 2, 2013
1,047
This is how I initial the uart:
Code:
    // from other part of the code
    // locking and unlocking code are removed.
    RX5PPS = 0x23;          // UART5 RX map to RE3
    RE2PPS = 0x14;          // UART5 TX map to RE2

void InitUART5(void){

    TRISEbits.TRISE2 = 0;      // TX
    TRISEbits.TRISE3 = 1;      // RX

    // 19200 baud rate
    SP5BRGL = 0;
    //SP5BRGL = 25;
    SP5BRGL = 103;
    BAUD5CONbits.BRG16 = 0;

    TX5STAbits.BRGH = 1;

    TX5STAbits.SYNC = 0;        // asnyc mode
    RC5STAbits.SPEN = 1;        // enable serial port
    TX5STAbits.TX9D = 0;        // 8 bit mode
    BAUD5CONbits.SCKP = 0;      // none inverted transmit
    TX5STAbits.TXEN = 1;        // enable transmission

    PIR4bits.TX5IF = 0;         // clear TX interrupt flag

    PIE4bits.RC5IE = 1;         // enable RX interrupt

    RC5STAbits.CREN = 1;        // enable reception
}
We need more information on the int routine.
It looks like a buffer overflow using two chars \r \n takes time the uart can handle two chars max.
when you send stop it takes 2 chars time plus interpretation time to stop transmitting.
I guess that you did not build an input buffer allowing chars after the stop transmit command.

Picbuster
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
We need more information on the int routine.
It looks like a buffer overflow using two chars \r \n takes time the uart can handle two chars max.
when you send stop it takes 2 chars time plus interpretation time to stop transmitting.
I guess that you did not build an input buffer allowing chars after the stop transmit command.

Picbuster
These are all of my initial routine, the RX is in a interrupt, with a buffer. I will post my RX interrupt tomorrow when I am at work, but mean time, it looks something like this:
Code:
void interrupt ISR(void){
  if (uart5_interrupt_flag){
     // clear flag
     // check framing error and over run error
     // read data
     // put data out from another UART @ 57600 baud, this is a test code
  }
}
 

danadak

Joined Mar 10, 2018
4,057
Normally UART approach is to use a circular buffer and pointers in
order to meet speed of data handling. Be careful in ISR to handle
min f() calls to minimize stack push and wasted time. Not unusual
to just set a flag then process outside ISR.

Google "uart circular buffer", lots of general and specific resources.

Regards, Dana.
 
Last edited:

Picbuster

Joined Dec 2, 2013
1,047
These are all of my initial routine, the RX is in a interrupt, with a buffer. I will post my RX interrupt tomorrow when I am at work, but mean time, it looks something like this:
Code:
void interrupt ISR(void){
  if (uart5_interrupt_flag){
     // clear flag
     // check framing error and over run error
     // read data
     // put data out from another UART @ 57600 baud, this is a test code
  }
}
Line 6 is not a good way to send data to a port in an input interrupt.
Leaving an interrupt to take action somewhere else could f**k-up the stack.
( each char an int and a routine somewhere else to send it. That routine takes time but the next
char (int) is popping in.
Xmit should be done in the main or under a separate interrupt.

Picbuster
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Line 6 is not a good way to send data to a port in an input interrupt.
Leaving an interrupt to take action somewhere else could f**k-up the stack.
( each char an int and a routine somewhere else to send it. That routine takes time but the next
char (int) is popping in.
Xmit should be done in the main or under a separate interrupt.

Picbuster
I think my last reply wasn't clearly state what I my code is actually doing. I hope my following code can be better show how I am testing it. In the interrupt, I am only assigning the data from byte by byte from the RX register (RC5REG) of UART5 to TX resister (TX3REG) of UART3.

The reason I do this is I wan to check the data I am receiving is correct, before implementing a buffer.

And this is a direct assignment, not throught printf() or any thing, this should be even faster than putting the data into a buffer.

And my RX data is @ 19200, and my TX data is @ 57600, the TX should always done before the next RX byte come in. And that's the only data need outputting.

Code:
// check for UART5 RX interrupt flag 
if (PIR4bits.RC5IF){
        // clear flag
        PIR4bits.RC5IF = 0;
     
        // check for framing error and set flag to
        // to do something about it in main loop
        if (RC5STAbits.FERR){
            state.isFramingError = 1;
        }
     
        // check for over run error and clear it
        if (RC5STAbits.OERR){
            state.isOverRunError = 1;
            // clear over run error
            RC5STAbits.CREN = 0;
            RC5STAbits.CREN = 1;
        }

        // store data from RX
        uint8_t data;
        // read data
        data = RC5REG;
     
        // send data to another port for debugging only
        // a buffer will be implement after confirming data
        // received is correct
        // data coming in from UART5 is @ 19200, data going out
        // is @ 57600
        TX3REG = data;
}
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Normally UART approach is to use a circular buffer and pointers in
order to meet speed of data handling. Be careful in ISR to handle
min f() calls to minimize stack push and wasted time. Not unusual
to just set a flag then process outside ISR.

Google "uart circular buffer", lots of general and specific resources.

Regards, Dana.
A buffer was implemented, but the data received was not correct, hence I am reducing my code to minimum to find the problem. My reply from yesterday may not necessary show exactly how was I testing it. Hope my actual code above show my intention better.
 

nsaspook

Joined Aug 27, 2009
13,270
Just a WAG here.

I think that chip has a two char input buffer. It's possible (if the initial receiver interrupt service call is delayed by close to one transmission time period) to have back to back receive interrupt calls faster than the unbuffered transmitter can shift them out if you don't check the xmit shift register status before writing data in the receive ISR.
The FIFO buffering allows reception of two complete characters and the start of a third character before software must start servicing the EUSART receiver. The FIFO and RSR registers are not directly accessible by software. Access to the received data is via the RCxREG register.
 
Last edited:

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Just a WAG here.

I think that chip has a two char input buffer. It's possible (if the initial receiver interrupt service call is delayed by close to one transmission time period) to have back to back receive interrupt calls faster than the unbuffered transmitter can shift them out if you don't check the xmit shift register status before writing data in the receive ISR.
Duh!

I think I found the problem. Your logic is correct, the ISR call is delayed by my stupidity, wah wah wah...

I have a 1ms timer interrupt in the same ISR as system tick, my incoming data is @ 19200, that translate into 520us for one byte and 1040us for two bytes. Because I just enable the global interrupt bit, but forgot to enable the peripheral interrupt bit. Every time an interrupt is fired, it's only the timer 1ms interrupt, but not the uart RX interrupt.

But the timer interrupt and the uart RX interrupt are in the same ISR, so my uart RX only is checked every 1ms. Depending on timing and the 2 bytes RX buffer, 2-3 bytes will be received correctly.

All I need is to add this to fix it, somehow I remember I did this to myself before, duh!!
Code:
// enable peripheral interrupt
INTCONbits.PEIE = 1;
Thanks guys for helping out!!
 

nsaspook

Joined Aug 27, 2009
13,270
Duh!

I think I found the problem. Your logic is correct, the ISR call is delayed by my stupidity, wah wah wah...

I have a 1ms timer interrupt in the same ISR as system tick, my incoming data is @ 19200, that translate into 520us for one byte and 1040us for two bytes. Because I just enable the global interrupt bit, but forgot to enable the peripheral interrupt bit. Every time an interrupt is fired, it's only the timer 1ms interrupt, but not the uart RX interrupt.

But the timer interrupt and the uart RX interrupt are in the same ISR, so my uart RX only is checked every 1ms. Depending on timing and the 2 bytes RX buffer, 2-3 bytes will be received correctly.

All I need is to add this to fix it, somehow I remember I did this to myself before, duh!!
Code:
// enable peripheral interrupt
INTCONbits.PEIE = 1;
Thanks guys for helping out!!
Cool! Glad you were pointed in the right direction to find the problem. Don't forget the mini-master switch again.
 
Top