[PIC] CAN RX buffer full flag not set?

Status
Not open for further replies.

flukeco

Junior Member level 1
Joined
Apr 25, 2014
Messages
16
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
180
Hi,

I'm using PIC18F2580 and MCP2551 CAN transceiver. My goal is to implement basic CAN bus monitoring program to capture CAN's frame ID,
data length and data bytes.

I use logic analyzer and can see that CANRX pin on PIC is continuously receiving data. However, the RXFUL bit of RXBnCON register
has never been set in my program.

The following is my CAN initialize function and CAN receive function. I want to capture all valid standard and extended CAN frames.

If you find anything wrong in the code, please give me some suggestion. Your help will be highly appreciated.

Best Regards,
Pat

Code:
void CAN_init(void) {
    TRISB = 0b00001000;       /* CANRX(RB3) is input, CANTX(RB2) is output*/
    PORTB = 0b00000000;

    CANCON = 0b10000000;      /* Request configuration mode (CANCON<7:5> = 0b1xx) */
    /* Wait until op mode is configuration mode (CANSTAT<7:5> = 0b100) */
    while ((CANSTAT & 0b11100000) != 0b100) {
        Nop();
    }

    /* Set up baud rate registers */
    /*  500 Kbps @ 40MHz */
    BRGCON1 = 0b01000001;         /* SWJ = 2TQ BPS = 1 */
    BRGCON2 = 0b10111010;         /* SEG2PHTS = 1, sampled once,  PS1 = 8TQ,  PropagationT  = 3TQ */
    BRGCON3 = 0b00000111;         /* Wake-up disabled, PS2 = 8Tq */

    /* Receive all valid messages, double buffer enabled */
    RXB0CON = 0b00000100;
    RXB1CON = 0b00000000;

    /* Set masks */
    RXM0SIDH = 0;
    RXM0SIDL = 0;
    RXM0EIDH = 0;
    RXM0EIDL = 0;

    RXM1SIDH = 0;
    RXM1SIDL = 0;
    RXM1EIDH = 0;
    RXM1EIDL = 0;

    /* Set filters */
    RXF0SIDH = 0;
    RXF0SIDL = 0;
    RXF0EIDH = 0;
    RXF0EIDL = 0;

    RXF1SIDH = 0;
    RXF1SIDL = 0;
    RXF1EIDH = 0;
    RXF1EIDL = 0;

    RXF2SIDH = 0;
    RXF2SIDL = 0b00001000;
    RXF2EIDH = 0;
    RXF2EIDL = 0;

    RXF3SIDH = 0;
    RXF3SIDL = 0b00001000;
    RXF3EIDH = 0;
    RXF3EIDL = 0;

    RXF4SIDH = 0;
    RXF4SIDL = 0b00001000;
    RXF4EIDH = 0;
    RXF4EIDL = 0;

    RXF5SIDH = 0;
    RXF5SIDL = 0b00001000;
    RXF5EIDH = 0;
    RXF5EIDL = 0;

    CANCON = 0x00;      /* Request normal mode (CANCON<7:5> = 0b000) */
    /* Wait until op mode is normal mode (CANSTAT<7:5> = 0b000) */
    while ((CANSTAT & 0b11100000) != 0b000) {
        Nop();
    }
}

char CAN_read(struct _CANframe *frame) {
    unsigned char RXflag, hi, lo;

    RXflag = 0;

    /* Check RXB0 */
    if (RXB0CONbits.RXFUL) {
        if (RXB0SIDLbits.EXID == 0) {
            /* Standard ID */
            /* SID low byte = RXBnSIDH<4:0> (high 5 bits), RXBnSIDL<7:5> (low 3 bits)
             * SID high byte = 0b00000 (high 5 bits), RXBnSIDH<7:5> (low 3 bits)
             */
            lo = ((RXB0SIDH & 0b00011111) << 3) | ((RXB0SIDL & 0b11100000) >> 5);
            hi = (RXB0SIDH & 0b11100000) >> 5;
            frame->ID = (unsigned long)MAKEWORD(lo, hi);
        } else {
            /* Extended ID
             * EID low word = RXBnEIDH:RXBnEIDL
             * EID high word:
             *  MSB => 0b000 (high 3 bits), RXBnSIDH<7:3> (low 5 bits)
             *  LSB => RXBnSIDH<2:0> (high 3 bits), RXBnSIDL<7:5> (middle 3 bits), RXBnSIDL<1:0> (low 2 bits)
             */
            lo = ((RXB0SIDH & 0b00000111) << 5) | ((RXB0SIDL & 0b11100000) >> 3) | (RXB0SIDL & 0b00000011);
            hi = (RXB0SIDH & 0b11111000) >> 3;
            frame->ID = MAKELONG(MAKEWORD(RXB0EIDL, RXB0EIDH), MAKEWORD(lo, hi));
        }

        frame->length = RXB0DLC & 0b00000111;

        frame->data[0] = RXB0D0;
        frame->data[1] = RXB0D1;
        frame->data[2] = RXB0D2;
        frame->data[3] = RXB0D3;
        frame->data[4] = RXB0D4;
        frame->data[5] = RXB0D5;
        frame->data[6] = RXB0D6;
        frame->data[7] = RXB0D7;

        RXB0CONbits.RXFUL = 0;
        RXflag = 1;
    }
    /* Check RXB1 */
    else if (RXB1CONbits.RXFUL) {
        if (RXB1SIDLbits.EXID == 0) {
            /* Standard ID */
            /* SID low byte = RXBnSIDH<4:0> (high 5 bits), RXBnSIDL<7:5> (low 3 bits)
             * SID high byte = 0b00000 (high 5 bits), RXBnSIDH<7:5> (low 3 bits)
             */
            lo = ((RXB1SIDH & 0b00011111) << 3) | ((RXB1SIDL & 0b11100000) >> 5);
            hi = (RXB1SIDH & 0b11100000) >> 5;
            frame->ID = (unsigned long)MAKEWORD(lo, hi);
        } else {
            /* Extended ID
             * EID low word = RXBnEIDH:RXBnEIDL
             * EID high word:
             *  MSB => 0b000 (high 3 bits), RXBnSIDH<7:3> (low 5 bits)
             *  LSB => RXBnSIDH<2:0> (high 3 bits), RXBnSIDL<7:5> (middle 3 bits), RXBnSIDL<1:0> (low 2 bits)
             */
            lo = ((RXB1SIDH & 0b00000111) << 5) | ((RXB1SIDL & 0b11100000) >> 3) | (RXB1SIDL & 0b00000011);
            hi = (RXB1SIDH & 0b11111000) >> 3;
            frame->ID = MAKELONG(MAKEWORD(RXB1EIDL, RXB1EIDH), MAKEWORD(lo, hi));
        }
        frame->length = RXB1DLC & 0b00000111;

        frame->data[0] = RXB1D0;
        frame->data[1] = RXB1D1;
        frame->data[2] = RXB1D2;
        frame->data[3] = RXB1D3;
        frame->data[4] = RXB1D4;
        frame->data[5] = RXB1D5;
        frame->data[6] = RXB1D6;
        frame->data[7] = RXB1D7;

        RXB1CONbits.RXFUL = 0;
        RXflag = 1;
    }

    if  (RXflag == 1) {
        RXflag = 0x00;
        PIR3bits.RXB0IF = 0;
        PIR3bits.RXB1IF = 0;
        return 1;
    } else {
        return 0;
    }
}
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…