Hello. I am currently trying to do CAN communication using an ESP32-WROOM-32E and an MCP2515.
I would appreciate it if someone could tell me more about the inability to process interrupts when receiving CAN.
We are currently using the library listed in the link above. The development environment is Arduino IDE.
The pin layout of MCP2515 and ESP32 is as follows.
MISO 19
MOSI 23
SCK 18
CS 5
INT 16
The code used is based on the READ.ME description on GitHub.
The code for CAN reception is as follows.
#include "mcp2515.h"
#include "esp_system.h"
#include "driver/spi_master.h"
struct can_frame frame;
spi_device_handle_t spi;
MCP2515 canbus(&spi);
void setup() {
Serial.begin(9600);
while (!Serial) {};
canbus.setBitrate(CAN_500KBPS, MCP_8MHZ);
canbus.setNormalMode();
}
void loop() {
if (canbus.readMessage(&frame) == MCP2515::ERROR_OK) {
//if (frame.can_id == 0xE8) {
Serial.println(" ");
Serial.print("DATA: ");
for (int i = 0; i < frame.can_dlc; i++) {
Serial.print(frame.data[i], HEX);
Serial.print(" ");
}
// }
}
delay(10);
}
Where I was able to reflect the settings,
canbus.setBitrate(CAN_500KBPS, MCP_8MHZ);
canbus.setNormalMode();
These are two.
When I ran this program, I received the data without any problems.
However, there is a problem with this program. It uses a polling method, which often means that data cannot be retrieved completely. So I tried to do an interrupt process.
#include "mcp2515.h"
#include "esp_system.h"
#include "driver/spi_master.h"
bool interrupt = true;
void irqHandler(){
interrupt = true;//ISR
}
struct can_frame frame;
spi_device_handle_t spi;
MCP2515 canbus(&spi);
void setup() {
Serial.begin(9600);
while(!Serial){};
//pinMode(16,INPUT_PULLDOWN);
canbus.setBitrate(CAN_500KBPS, MCP_8MHZ);
canbus.setNormalMode();
//canbus.setFilter(MCP2515::RXF0, false, 0xE8);
//canbus.setFilter(MCP2515::RXF1, false, 0xE8);
attachInterrupt(digitalPinToInterrupt(16), irqHandler ,FALLING);
}
void loop() {
if (interrupt){
Serial.print("IRQ Flags: 0x");
interrupt = false;
uint8_t irq = canbus.getInterrupts();
if (irq & MCP2515::CANINTF_RX0IF){
if (canbus.readMessage(MCP2515::RXB0, &frame) == MCP2515::ERROR_OK){
//受信したメッセージをシリアルモニタに表示
Serial.println(" ");
Serial.print("DATA RXB0IF");
for (int i = 0 ; i < frame.can_dlc; i++){
Serial.print(frame.data[i], HEX);
Serial.print(" ");
}
}
}
if (irq & MCP2515::CANINTF_RX1IF){
if (canbus.readMessage(MCP2515::RXB1, &frame) == MCP2515::ERROR_OK){
Serial.println(" ");
Serial.print("DATA RBXIF");
for (int i = 0 ; i < frame.can_dlc; i++){
Serial.print(frame.data[i],HEX);
Serial.print(" ");
}
}
}
}
}
The program above is how the interrupt process is received.
The main problem with this program is that the interrupts do not respond, so if and below are not processed and are not displayed on the serial monitor at all.
We confirmed that the interrupt pin was set to pin 16 and that there were no wiring errors. We also confirmed from the datasheet that ESP32 can handle interrupts on all GPIO pins.
Also, if I commented out the if (interrupt){ part, CAN reception started without any problem and it was displayed on the serial monitor.
Next, I checked the MCP2515 datasheet and found that the INT pin changes from 5V to 0V when data accumulates in buffer 0 or 1.
I found the following configuration item at line 82 in the MCP2515.cpp source.
setRegister(MCP_CANINTE, CANINTF_RX0IF | CANINTF_RX1IF | CANINTF_ERRIF | CANINTF_MERRF);
This configuration item is supposed to be enabled at one point. (Maybe it is not).
Assuming that the settings are valid, I attached an oscilloscope to the INT pin and checked it, and it remained at 5V all the time and I could not see where it dropped to 0V.
The fact that the INT pin does not change is definitely the cause of the lack of interrupt processing.
However, although I have spent quite a bit of time on it, I can't figure out where to set it up to make it work. I would appreciate any and all advice from any great people who are familiar with this.
Thank you for your cooperation.