Longan-Labs / Arduino_CAN_BUS_MCP2515

Arduino CAN Bus library, MCP2515/MCP2551
https://www.longan-labs.cc/
MIT License
126 stars 372 forks source link

attachInterrupt() not working? #37

Open JohnKozell opened 1 month ago

JohnKozell commented 1 month ago

Using the set_mask_filter_recv.ino example with CANBUS RP2040 board, I do not see the interrupt callback being fired, despite relaxing the receive filters. However, if I modify the loop to use the checkReceive() instead, I can detect the message and process it with the readMsgBuf().

Is there some other pre-condition or configuration I need to perform, prior to attachInterrupt()?

// receive a frame from can bus with mask and filter setting

#include <SPI.h>
#include "mcp_can.h"

#include <SPI.h>
#include "mcp_can.h"

const int SPI_CS_PIN = 17;              // CANBed V1
// const int SPI_CS_PIN = 3;            // CANBed M0
// const int SPI_CS_PIN = 9;            // CAN Bus Shield

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[8];
char str[20];

void setup()
{
    Serial.begin(115200);
    while(!Serial);
    while (CAN_OK != CAN.begin(CAN_500KBPS))    // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS FAIL!");
        delay(100);
    }
    Serial.println("CAN BUS OK!");

    attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt

    /*
     * set mask, set both the mask to 0x3ff
     */
    CAN.init_Mask(0, 0, 0x3ff);                         // there are 2 mask in mcp2515, you need to set both of them
    CAN.init_Mask(1, 0, 0x3ff);

    /*
     * set filter, we can receive id from 0x04 ~ 0x09
     */
    CAN.init_Filt(0, 0, 0x04);                          // there are 6 filter in mcp2515
    CAN.init_Filt(1, 0, 0x05);                          // there are 6 filter in mcp2515

    CAN.init_Filt(2, 0, 0x06);                          // there are 6 filter in mcp2515
    CAN.init_Filt(3, 0, 0x07);                          // there are 6 filter in mcp2515
    CAN.init_Filt(4, 0, 0x08);                          // there are 6 filter in mcp2515
    CAN.init_Filt(5, 0, 0x09);                          // there are 6 filter in mcp2515

}

void MCP2515_ISR()
{
    flagRecv = 1;
}

void loop()
{
    if(flagRecv)                   // check if get data
    {

        flagRecv = 0;                // clear flag
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        Serial.println("\r\n------------------------------------------------------------------");
        Serial.print("Get Data From id: ");
        Serial.println(CAN.getCanId());
        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print("0x");
            Serial.print(buf[i], HEX);
            Serial.print("\t");
        }
        Serial.println();

    }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/
coryjfowler commented 1 month ago

I my experience, I have not had luck using hardware interrupts with the MCP2515 and an ATmega328. The issue I run into is the MCP2515 will hold /INT active until the receive buffers are empty. That means the interrupt routine would need to check the state of /INT before exiting. I have also experienced issues with the edge based triggering some interrupt peripherals want instead of an explicit state to trigger the interrupt. The RP2040 has more than enough speed over the ATmega328 I use with the MCP2515, so I would expect a well written interrupt routine to be possible with it.