• AVR Freaks

Interrupt not triggering on UART2RX PIC24FV16KM202

Author
Weffel
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2017/09/01 03:09:33
  • Location: 51.958486, 5.969618
  • Status: offline
2017/12/15 02:35:11 (permalink)
0

Interrupt not triggering on UART2RX PIC24FV16KM202

Hi,
 
I am trying to talk to a RN2483 module through UART 2, and I use UART 1 for debugging (using cutecom on pc)
What happens is that I send a command to the module, the module responds (I see the response on the line using a scope), but the UART2RX interrupt doesn't go off. This is strange because when I use the same code (except for UART 1) the interrupt does work and I can receive my response. As the initialization for both UART are the same, I have no clue what the problem is.
 
EDIT:
I noticed now the interrupt does trigger, but it exits the interrupt right away because the U2STAbits.FERR is set. On the scope i can decode the message like normal, all bits seem to be here, so the question really turns into: Why is U2STAbits.FERR set for ALL BYTES i receive? Not a single byte comes through.
This only occurs on the received messages from the RN2483 module from Microchip. This doesn't occur when I send messages to the device from my PC on uart 1.
END OF EDIT
 
I am using both UART2 and UART 1 on the PIC24FV16KM202 controller. The PIC24 is connected with my PC through the programmer found http://www.microchip.com/...aspx?PartNO=DM240013-2 here.
 
The code i use for initializing my I/O:

 
ANSA = 0x0000; // set pin mode to digital
TRISA = 0x0000; // set pin function all to output
ANSAbits.ANSA2 = 1; // RA2 = OSCI
TRISAbits.TRISA2 = 1; // RA2 = OSCI
 
LATBbits.LATB0 = 1; // master TX
LATBbits.LATB7 = 1; // Diver TX
 
// set pin function PORT B (input = 1 / output = 0) //
 
ANSB = 0x0000; // set pin mode to digital
 

HLVDCONbits.HLSIDL = 1;
 
//TRISB = 0xFFFF; // set pin function all to output
TRISBbits.TRISB0 = 0;
TRISBbits.TRISB7 = 0;
TRISBbits.TRISB13 = 0; // RB13 = reset pin (Output)
 
IFS1 = 0x0000; // Reset all interrupts
IFS2 = 0x0000; // Reset all interrupts
IFS3 = 0x0000; // Reset all interrupts
IFS4 = 0x0000; // Reset all interrupts
IFS5 = 0x0000; // Reset all interrupts
IFS6 = 0x0000; // Reset all interrupts
INTTREG = 0b0000000000000000;
 

 
Now I initialize both my uarts respectively with the code:

 
void init_rn2483_uart()
 
{
 
U2MODEbits.UARTEN = 1; // Enable UART
U2MODEbits.STSEL = 0; // 1-stop bit
U2MODEbits.PDSEL = 0; // No Parity, 8-data bits
U2MODEbits.ABAUD = 0; // Auto-Baud disabled
U2MODEbits.BRGH = 0; // Standard-Speed mode
U2MODEbits.WAKE = 0; // Wake up after start bit
U2BRG = BAUD_TO_BRG(9600);
U2MODEbits.USIDL = 1; // Stop in idle mode
U2MODEbits.UEN = 0; // Only use TX and RX
U2STAbits.URXISEL = 1; // Interrupt after a RX character is received;
U2STAbits.UTXISEL0 = 1; // UARTx Transmission Interrupt Mode = Interrupt when the last character is shifted out of the Transmit Shift Register;
U2STAbits.UTXISEL1 = 0;
IEC1bits.U2TXIE = 0; // Disable UART TX interrupt
IEC1bits.U2RXIE = 1; // Enable UART RX interrupt
IPC7bits.U2TXIP = 5; // UART interrupt priority (0 = lowest, 7 = highest)
U2STAbits.UTXEN = 1; // Enable UART TX
 
}
 
 
 
void init_debug_uart()
 
{
 
U1MODEbits.STSEL = 0; // 1-stop bit
U1MODEbits.PDSEL = 0; // No Parity, 8-data bits
U1MODEbits.ABAUD = 0; // Auto-Baud disabled
U1MODEbits.BRGH = 0; // Standard-Speed mode
U1MODEbits.WAKE = 0; // Wake up after start bit
U1BRG = BAUD_TO_BRG(baudrate);
U1MODEbits.USIDL = 1; // ???? in idle mode
U1MODEbits.UEN = 0; // Only use TX and RX
U1STAbits.URXISEL = 1; // Interrupt after a RX character is received;
U1STAbits.UTXISEL0 = 1; // UARTx Transmission Interrupt Mode = Interrupt when the last character is shifted out of the Transmit Shift Register;
U1STAbits.UTXISEL1 = 0;
IEC0bits.U1TXIE = 0; // Disable UART TX interrupt
IEC0bits.U1RXIE = 1; // Enable UART RX interrupt
IPC3bits.U1TXIP = 5; // UART interrupt priority (0 = lowest, 7 = highest)
U1MODEbits.UARTEN = 1; // Enable UART
U1STAbits.UTXEN = 1; // Enable UART TX
 
}
 

 
The interrupt is exactly the same for both uarts, see below;

 
void _ISR __attribute__((no_auto_psv)) _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0; // Clear Interrupt flag
 
if(U1STAbits.FERR == 1) { // Framing error
U1STAbits.FERR = 0;
return;
}
 
rx_in_debug = (U1RXREG & 0xFF); // Store char in buffer
 
if(U1STAbits.OERR == 1) {
U1STAbits.OERR = 0; // Reset error
}
}
 
 
 
void _ISR __attribute__((no_auto_psv)) _U2RXInterrupt(void)
{
IFS1bits.U2RXIF = 0; // Clear RX Interrupt flag
if(U2STAbits.FERR == 1) { // Framing error
U2STAbits.FERR = 0;
return;
}
 
rx_in = (U2RXREG & 0xFF); // Store char in buffer
 
if(U2STAbits.OERR == 1) {
U2STAbits.OERR = 0; // Reset error
}
}
 

 
post edited by Weffel - 2017/12/15 08:15:42
#1

4 Replies Related Threads

    davekw7x
    Entropy++
    • Total Posts : 1768
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Left Coast, USA
    • Status: offline
    Re: Interrupt not triggering on UART2RX PIC24FV16KM202 2017/12/16 09:47:09 (permalink)
    0
    Code from Weffe with augmented comment by davekw7x
    ...
    I noticed now the interrupt does trigger, but it exits the interrupt right away because the U2STAbits.FERR is set.
    ...
    Why is U2STAbits.FERR set for ALL BYTES i receive? Not a single byte comes through.
    ...
     

    void _ISR __attribute__ ((no_auto_psv)) _U2RXInterrupt(void)
    {
        IFS1bits.U2RXIF = 0;        // Clear RX Interrupt flag
        if (U2STAbits.FERR == 1) {  // Framing error
            U2STAbits.FERR = 0; //<---From davekw7x: This does not clear FERR!
            return;
        }

        rx_in = (U2RXREG & 0xFF);   // Store char in buffer

        if (U2STAbits.OERR == 1) {
            U2STAbits.OERR = 0;     // Reset error
        }
    }


    Unlike OERR, which must be cleared by software, FERR is read-only.
     
    In other words...
    You must read the RXREG to clear FERR, otherwise once FERR is set, it remains set forever. 
     
    Reference: Description in REGISTER 15-2 of the data sheet.
     
    So, maybe the ISRs can go something like this...
    1. Read the RX Register into a temporary variable.
    2. Then check and handle error conditions.
    3. If no errors, then do whatever you need to do with the received char in the temporary variable.
     
    Anyhow...
     
    How does FERR get set in the first place?  Depends on what is connected to the UART RX pin, and how (and when) the Other End is initialized to drive that RX pin.
     
    Perhaps it gets set when the UART is initialized.  (The U2RX pin is shared with PGEC1.  Maybe that affects it.)  My initialization code usually does a dummy read and clears whatever errors can be cleared by software.
     
    Or maybe the received signal logic level is zero before the "Other End" gets enabled and starts sending.  This can cause framing errors and overrun errors.
     
    Or something else...
     
     
    Regards,

    Dave
     
    post edited by davekw7x - 2017/12/16 10:06:25

    Sometimes I just can't help myself...
    #2
    RISC
    Super Member
    • Total Posts : 5376
    • Reward points : 0
    • Status: offline
    Re: Interrupt not triggering on UART2RX PIC24FV16KM202 2017/12/16 16:35:11 (permalink)
    0
    Hi,
    As you are using the Microstick for PIC24F16KM202, the schematic shows that U2RX is shared with PGEC1 and U2TX shared with PGED1 : http://ww1.microchip.com/downloads/en/DeviceDoc/50002142a.pdf
    So, if you need to use U2 change the switch S3 to use PGEC3 and PGED3 (you will however lose the pins RB5 and RB6).
    NB : you will also need to change the configuration bits to use PGEC3/PGED3 otherwise you will not be able to debug...
    Regards
    #3
    Weffel
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2017/09/01 03:09:33
    • Location: 51.958486, 5.969618
    • Status: offline
    Re: Interrupt not triggering on UART2RX PIC24FV16KM202 2017/12/18 03:51:11 (permalink)
    0
     
    Hi,
     
    Thanks for the responses, I made a lot of progress now. 
    davekw7x
    Unlike OERR, which must be cleared by software, FERR is read-only.
     
    In other words...
    You must read the RXREG to clear FERR, otherwise once FERR is set, it remains set forever. 
     
    Reference: Description in REGISTER 15-2 of the data sheet.
     
    So, maybe the ISRs can go something like this...
    1. Read the RX Register into a temporary variable.
    2. Then check and handle error conditions.
    3. If no errors, then do whatever you need to do with the received char in the temporary variable.
     

    I did indeed notice that the error is read-only, that is specifies the error for the character currently in the RXREG register. I forgot to remove it however. I also tested my code without the return and everything seemed to work fine, except for the FERR register being set. I think however that your step 1, 2, 3 will go wrong since you clear the error at step 1, resulting in step 2 never finding an error? But i get the idea.
     
    RISC
    Hi,
    As you are using the Microstick for PIC24F16KM202, the schematic shows that U2RX is shared with PGEC1 and U2TX shared with PGED1 : http://ww1.microchip.com/downloads/en/DeviceDoc/50002142a.pdf
    So, if you need to use U2 change the switch S3 to use PGEC3 and PGED3 (you will however lose the pins RB5 and RB6).

    yes, I'm using the PGEx3
     
    davekw7x
    How does FERR get set in the first place?  Depends on what is connected to the UART RX pin, and how (and when) the Other End is initialized to drive that RX pin.
     
    Perhaps it gets set when the UART is initialized.  (The U2RX pin is shared with PGEC1.  Maybe that affects it.)  My initialization code usually does a dummy read and clears whatever errors can be cleared by software.
     
    Or maybe the received signal logic level is zero before the "Other End" gets enabled and starts sending.  This can cause framing errors and overrun errors.
     
    Or something else...

    I think it is due to the RN2483 module (connected to UART2) start-up message. I reset the module right after  initializing the UART. Then there follows a start-up message (on 57600 baud, which i totally forgot) after which I send an autobaud message to switch the baudrate to 9600, after which i no longer seem te get Frame errors.
    Am i correct to assume this is caused by the startup message and can I safely ignore the frame error?
     
    Regards,
     
    Weffel
    #4
    davekw7x
    Entropy++
    • Total Posts : 1768
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Left Coast, USA
    • Status: offline
    Re: Interrupt not triggering on UART2RX PIC24FV16KM202 2017/12/18 06:38:16 (permalink)
    0
    Weffel
    ...I think however that your step 1, 2, 3 will go wrong since you clear the error at step 1, resulting in step 2 never finding an error?...

    You are, of course, correct.  Sorry.  I'm glad you were able to overcome.
     
    Weffel
    ... Then there follows a start-up message (on 57600 baud, which i totally forgot) after which I send an autobaud message to switch the baudrate to 9600, after which i no longer seem te get Frame errors.
    Am i correct to assume this is caused by the startup message

    Surely.
    Weffel
    and can I safely ignore the frame error?

    If you can't operate at 57600 initially, I don't know what else you can do. If you don't get errors after you send the autobaud message, you are in business, and that's the best it's going to get.
     
     
    Regards,
     
    Dave
     
    post edited by davekw7x - 2017/12/18 06:39:26

    Sometimes I just can't help myself...
    #5
    Jump to:
    © 2019 APG vNext Commercial Version 4.5