Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] CAN RX buffer full flag not set?

Status
Not open for further replies.

flukeco

Junior Member level 1
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

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top