oops forgot to post the code running on the RP2040 pico
// ACAN2515 Demo in LoopBackMode mode, for the Raspberry Pi Pico
// based on a code from Duncan Greenwood
#ifndef ARDUINO_ARCH_RP2040
#error "Select a Raspberry Pi Pico board"
#endif
#include <ACAN2515.h>
unsigned long MyTestTimer = 0; // Timer-variables MUST be of type unsigned long
const byte OnBoard_LED = 25; // onboard-LED Raspberry Pi pico
// The Pico has two SPI peripherals, SPI-0 and SPI-1. Either (or both) can be used.
// The are no default pin assignments so they must be set explicitly.
// According to the RP2040 data sheet, section 1.4.3 ”GPIO Functions” page 13,
// you have the following choices for SPI pins:
// SPI-0_SCK IO-Pins: 2, 6, 18, 22
// SPI-0_MOSI (SPI0 TX) IO-Pins: 3, 7, 19, 23
// SPI-0_MISO (SPI0 RX) IO-Pins: 0, 4, 16, 20
// SPI-0 CS IO-Pins: 1, 5, 17, 21
// SPI-1_SCK IO-Pins: 10, 14, 26
// SPI-1_MOSI (SPI1 TX) IO-Pins: 11, 15, 27
// SPI-1_MISO (SPI1 RX) IO-Pins: 8, 12, 24, 28
// SPI-1_CS IO-Pins: 9, 13, 25, 29
// Testing was done with Earle Philhower's arduino-pico core:
// https://github.com/earlephilhower/arduino-pico
// SPI-Interface Pin-abbreviations
// SCK, SCLK, CLK, SCL
// MO_SI, (Master sends Data Out) SDO, DO, DOUT
// MI_SO, (Master receives Data In) SDI, DI, DIN, SI
static const byte MCP2515_INT = 1; // INT output of MCP2515 (adapt to your design)
static const byte MCP2515_SCK = 2; // connected to SCK input of MCP2515
static const byte MCP2515_MOSI = 3; // master out is SI input of MCP2515
static const byte MCP2515_MISO = 4; // master in is SO output of MCP2515
static const byte MCP2515_CS = 5; // CS input of MCP2515 (adapt to your design)
// MCP2515 Driver object
ACAN2515 can (MCP2515_CS, SPI, MCP2515_INT);
// MCP2515 Quartz: adapt to your design look on the housing of the quarzt
// if there is printed for example 8.000 this means 8 MHz = 8UL * 1000UL * 1000UL
static const uint32_t QUARTZ_FREQUENCY = 8UL * 1000UL * 1000UL; // 8 MHz
void setup () {
pinMode(OnBoard_LED, OUTPUT);
Serial.begin (115200);
while (!Serial) {
delay (50);
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN));
}
Serial.println("Setup-Start");
PrintFileNameDateTime();
// There are no default SPI pins so they must be explicitly assigned
// ATTENTION ! Make sure to only assign IO-pins that can be used
// According to the RP2040 data sheet, section 1.4.3 ”GPIO Functions” page 13,
SPI.setSCK(MCP2515_SCK);
SPI.setTX(MCP2515_MOSI);
SPI.setRX(MCP2515_MISO);
SPI.setCS(MCP2515_CS);
SPI.begin();
Serial.println("SPI.begin();; done");
Serial.println ("Configuring ACAN2515");
//ACAN2515Settings settings (QUARTZ_FREQUENCY, 125UL * 1000UL);// CAN bit rate 125 kb/s
ACAN2515Settings settings (QUARTZ_FREQUENCY, 500UL * 1000UL);// CAN bit rate 500 kb/s
//settings.mRequestedMode = ACAN2515Settings::LoopBackMode;// Select loopback mode
settings.mRequestedMode = ACAN2515Settings::NormalMode;
const uint16_t errorCode = can.begin (settings, [] { can.isr (); });
if (errorCode == 0) {
Serial.print ("Bit Rate prescaler: ");
Serial.println (settings.mBitRatePrescaler);
Serial.print ("Propagation Segment: ");
Serial.println (settings.mPropagationSegment);
Serial.print ("Phase segment 1: ");
Serial.println (settings.mPhaseSegment1);
Serial.print ("Phase segment 2: ");
Serial.println (settings.mPhaseSegment2);
Serial.print ("SJW: ");
Serial.println (settings.mSJW);
Serial.print ("Triple Sampling: ");
Serial.println (settings.mTripleSampling ? "yes" : "no");
Serial.print ("Actual bit rate: ");
Serial.print (settings.actualBitRate ());
Serial.println (" bit/s");
Serial.print ("Exact bit rate ? ");
Serial.println (settings.exactBitRate () ? "yes" : "no");
Serial.print ("Sample point: ");
Serial.print (settings.samplePointFromBitStart ());
Serial.println ("%");
}
else {
Serial.print ("Configuration error 0x");
Serial.println (errorCode, HEX);
}
}
static uint32_t gBlinkLedDate = 0;
static uint32_t gReceivedFrameCount = 0;
static uint32_t gSentFrameCount = 0;
void loop () {
CANMessage frame;
//BlinkHeartBeatLED(OnBoard_LED, 250);
if ( TimePeriodIsOver(MyTestTimer, 500) ) {
bool ok = can.tryToSend (frame);
if (ok) {
gSentFrameCount += 1;
Serial.print ("Sent: ");
Serial.println (gSentFrameCount);
}
else {
Serial.println ("Send failure");
}
}
if (can.available ()) {
can.receive (frame);
gReceivedFrameCount ++;
Serial.print ("Received: ");
Serial.println (gReceivedFrameCount);
}
}
// helper-functions
void PrintFileNameDateTime() {
Serial.println("Code running comes from file ");
Serial.println(__FILE__);
Serial.print(" compiled ");
Serial.print(__DATE__);
Serial.print(" ");
Serial.println(__TIME__);
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
//pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}