Skip to content

Commit

Permalink
Using with no interrupt pin
Browse files Browse the repository at this point in the history
pierremolinaro committed Jan 31, 2019
1 parent 78eba45 commit 34ab8b8
Showing 6 changed files with 311 additions and 11 deletions.
127 changes: 127 additions & 0 deletions examples/LoopBackDemoESP32NoInt/LoopBackDemoESP32NoInt.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//——————————————————————————————————————————————————————————————————————————————
// ACAN2517FD Demo in loopback mode, for ESP32, no interrupt pin
//——————————————————————————————————————————————————————————————————————————————

#ifndef ARDUINO_ARCH_ESP32
#error "Select an ESP32 board"
#endif

//——————————————————————————————————————————————————————————————————————————————

#include <ACAN2517FD.h>
#include <SPI.h>

//——————————————————————————————————————————————————————————————————————————————
// For using SPI on ESP32, see demo sketch SPI_Multiple_Buses
// Two SPI busses are available in Arduino, HSPI and VSPI.
// By default, Arduino SPI use VSPI, leaving HSPI unused.
// Default VSPI pins are: SCK=18, MISO=19, MOSI=23.
// You can change the default pin with additional begin arguments
// SPI.begin (MCP2517_SCK, MCP2517_MISO, MCP2517_MOSI)
// CS input of MCP2517 should be connected to a digital output port
// Notes:
// - GPIOs 34 to 39 are GPIs – input only pins. These pins don’t have internal pull-ups or
// pull-down resistors. They can’t be used as outputs.
// - some pins do not support INPUT_PULLUP (see https://www.esp32.com/viewtopic.php?t=439)
// See https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
//——————————————————————————————————————————————————————————————————————————————

static const byte MCP2517_SCK = 26 ; // SCK input of MCP2517
static const byte MCP2517_MOSI = 19 ; // SDI input of MCP2517
static const byte MCP2517_MISO = 18 ; // SDO output of MCP2517

static const byte MCP2517_CS = 16 ; // CS input of MCP2517

//——————————————————————————————————————————————————————————————————————————————
// ACAN2517FD Driver object
//——————————————————————————————————————————————————————————————————————————————

ACAN2517FD can (MCP2517_CS, SPI, 255) ; // Last argument is 255 -> no interrupt pin

//——————————————————————————————————————————————————————————————————————————————
// SETUP
//——————————————————————————————————————————————————————————————————————————————

void setup () {
//--- Switch on builtin led
pinMode (LED_BUILTIN, OUTPUT) ;
digitalWrite (LED_BUILTIN, HIGH) ;
//--- Start serial
Serial.begin (115200) ;
//--- Wait for serial (blink led at 10 Hz during waiting)
while (!Serial) {
delay (50) ;
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
}
//----------------------------------- Begin SPI
SPI.begin (MCP2517_SCK, MCP2517_MISO, MCP2517_MOSI) ;
//--- Configure ACAN2517FD
Serial.print ("sizeof (ACAN2517FDSettings): ") ;
Serial.print (sizeof (ACAN2517FDSettings)) ;
Serial.println (" bytes") ;
Serial.println ("Configure ACAN2517FD") ;
ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_4MHz10xPLL, 125 * 1000, ACAN2517FDSettings::DATA_BITRATE_x1) ;
settings.mRequestedMode = ACAN2517FDSettings::InternalLoopBack ; // Select loopback mode
//--- RAM Usage
Serial.print ("MCP2517FD RAM Usage: ") ;
Serial.print (settings.ramUsage ()) ;
Serial.println (" bytes") ;
//--- Begin
const uint32_t errorCode = can.begin (settings, NULL) ; // Second argument is NULL -> no interrupt service routine
if (errorCode == 0) {
Serial.print ("Bit Rate prescaler: ") ;
Serial.println (settings.mBitRatePrescaler) ;
Serial.print ("Arbitration Phase segment 1: ") ;
Serial.println (settings.mArbitrationPhaseSegment1) ;
Serial.print ("Arbitration Phase segment 2: ") ;
Serial.println (settings.mArbitrationPhaseSegment2) ;
Serial.print ("Arbitration SJW:") ;
Serial.println (settings.mArbitrationSJW) ;
Serial.print ("Actual Arbitration Bit Rate: ") ;
Serial.print (settings.actualArbitrationBitRate ()) ;
Serial.println (" bit/s") ;
Serial.print ("Exact Arbitration Bit Rate ? ") ;
Serial.println (settings.exactArbitrationBitRate () ? "yes" : "no") ;
Serial.print ("Arbitration Sample point: ") ;
Serial.print (settings.arbitrationSamplePointFromBitStart ()) ;
Serial.println ("%") ;
}else{
Serial.print ("Configuration error 0x") ;
Serial.println (errorCode, HEX) ;
}
}

//——————————————————————————————————————————————————————————————————————————————
// LOOP
//——————————————————————————————————————————————————————————————————————————————

static unsigned gBlinkLedDate = 0 ;
static unsigned gReceivedFrameCount = 0 ;
static unsigned gSentFrameCount = 0 ;

//——————————————————————————————————————————————————————————————————————————————

void loop () {
can.poll () ; // Call can.poll as often as possible
CANFDMessage frame ;
if (gBlinkLedDate < millis ()) {
gBlinkLedDate += 2000 ;
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
const 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) ;
}
}

//——————————————————————————————————————————————————————————————————————————————
140 changes: 140 additions & 0 deletions examples/LoopBackDemoTeensy3xNoInt/LoopBackDemoTeensy3xNoInt.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//——————————————————————————————————————————————————————————————————————————————
// ACAN2517FD Demo in loopback mode, using hardware SPI1, with no external interrupt
//——————————————————————————————————————————————————————————————————————————————

#include <ACAN2517FD.h>

//——————————————————————————————————————————————————————————————————————————————
// MCP2517 connections: adapt theses settings to your design
// As hardware SPI is used, you should select pins that support SPI functions.
// This sketch is designed for a Teensy 3.5, using SPI1
// But standard Teensy 3.5 SPI1 pins are not used
// SCK input of MCP2517 is connected to pin #32
// SDI input of MCP2517 is connected to pin #0
// SDO output of MCP2517 is connected to pin #1
// CS input of MCP2517 should be connected to a digital output port
//——————————————————————————————————————————————————————————————————————————————

static const byte MCP2517_SCK = 32 ; // SCK input of MCP2517
static const byte MCP2517_SDI = 0 ; // SDI input of MCP2517
static const byte MCP2517_SDO = 1 ; // SDO output of MCP2517

static const byte MCP2517_CS = 31 ; // CS input of MCP2517

//——————————————————————————————————————————————————————————————————————————————
// ACAN2517FD Driver object
//——————————————————————————————————————————————————————————————————————————————

ACAN2517FD can (MCP2517_CS, SPI1, 255) ; // Last argument is 255 -> no interrupt pin

//——————————————————————————————————————————————————————————————————————————————
// SETUP
//——————————————————————————————————————————————————————————————————————————————

void setup () {
//--- Switch on builtin led
pinMode (LED_BUILTIN, OUTPUT) ;
digitalWrite (LED_BUILTIN, HIGH) ;
//--- Start serial
Serial.begin (38400) ;
//--- Wait for serial (blink led at 10 Hz during waiting)
while (!Serial) {
delay (50) ;
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
}
//--- Define alternate pins for SPI1 (see https://www.pjrc.com/teensy/td_libs_SPI.html)
Serial.print ("Using pin #") ;
Serial.print (MCP2517_SDI) ;
Serial.print (" for MOSI: ") ;
Serial.println (SPI1.pinIsMOSI (MCP2517_SDI) ? "yes" : "NO!!!") ;
Serial.print ("Using pin #") ;
Serial.print (MCP2517_SDO) ;
Serial.print (" for MISO: ") ;
Serial.println (SPI1.pinIsMISO (MCP2517_SDO) ? "yes" : "NO!!!") ;
Serial.print ("Using pin #") ;
Serial.print (MCP2517_SCK) ;
Serial.print (" for SCK: ") ;
Serial.println (SPI1.pinIsSCK (MCP2517_SCK) ? "yes" : "NO!!!") ;
SPI1.setMOSI (MCP2517_SDI) ;
SPI1.setMISO (MCP2517_SDO) ;
SPI1.setSCK (MCP2517_SCK) ;
//----------------------------------- Begin SPI1
SPI1.begin () ;
//--- Configure ACAN2517FD
Serial.println ("Configure ACAN2517FD") ;
ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_4MHz10xPLL, 125 * 1000, ACAN2517FDSettings::DATA_BITRATE_x1) ;
settings.mRequestedMode = ACAN2517FDSettings::InternalLoopBack ; // Select loopback mode
//--- RAM Usage
Serial.print ("MCP2517FD RAM Usage: ") ;
Serial.print (settings.ramUsage ()) ;
Serial.println (" bytes") ;
//--- Begin
const uint32_t errorCode = can.begin (settings, NULL) ; // Second argument is NULL -> no interrupt service routine
if (errorCode == 0) {
Serial.print ("Bit Rate prescaler: ") ;
Serial.println (settings.mBitRatePrescaler) ;
Serial.print ("Arbitration Phase segment 1: ") ;
Serial.println (settings.mArbitrationPhaseSegment1) ;
Serial.print ("Arbitration Phase segment 2: ") ;
Serial.println (settings.mArbitrationPhaseSegment2) ;
Serial.print ("Arbitration SJW:") ;
Serial.println (settings.mArbitrationSJW) ;
Serial.print ("Actual Arbitration Bit Rate: ") ;
Serial.print (settings.actualArbitrationBitRate ()) ;
Serial.println (" bit/s") ;
Serial.print ("Exact Arbitration Bit Rate ? ") ;
Serial.println (settings.exactArbitrationBitRate () ? "yes" : "no") ;
Serial.print ("Arbitration Sample point: ") ;
Serial.print (settings.arbitrationSamplePointFromBitStart ()) ;
Serial.println ("%") ;
}else{
Serial.print ("Configuration error 0x") ;
Serial.println (errorCode, HEX) ;
}
}

//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

static unsigned gBlinkLedDate = 0 ;
static unsigned gReceivedFrameCount = 0 ;
static unsigned gSentFrameCount = 0 ;

//——————————————————————————————————————————————————————————————————————————————

void loop() {
can.poll () ; // Call can.poll as often as possible
CANFDMessage frame ;
if (gBlinkLedDate < millis ()) {
gBlinkLedDate += 2000 ;
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
frame.len = 64 ;
for (uint8_t i=0 ; i<frame.len ; i++) {
frame.data [i] = i ;
}
const 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) ;
bool ok = frame.len == 64 ;
if (!ok) {
Serial.println ("length error") ;
}
for (uint8_t i=0 ; (i<frame.len) && ok ; i++) {
ok = frame.data [i] == i ;
}
gReceivedFrameCount ++ ;
Serial.print ("Received: ") ;
Serial.print (gReceivedFrameCount) ;
Serial.print (", ") ;
Serial.println (ok ? "ok" : "error") ;
}
}

//——————————————————————————————————————————————————————————————————————————————
Binary file modified extras/acan2517FD.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ version=1.1.0
author=Pierre Molinaro
maintainer=Pierre Molinaro <Pierre.Molinaro@pcmolinaro.name>
sentence=Driver for MCP2517FD CAN Controller (CAN FD mode)
paragraph=This library is an Arduino CAN network driver for the MCP2517FD CAN Controller, in CAN FD mode. Compatible with ACAN, ACAN2515, ACAN2517 libraries. Default configuration sends and receives any frame – no default filter to provide. Reception filters (up to 32) can be easily defined.
paragraph=This library is an Arduino CAN network driver for the MCP2517FD CAN Controller, in CAN FD mode. Compatible with ACAN, ACAN2515, ACAN2517 libraries. Default configuration sends and receives any frame – no default filter to provide. Reception filters (up to 32) can be easily defined. Compatible with ESP32 from version 1.1.0.
category=Communication
url=https://github.com/pierremolinaro/acan2517FD
architectures=*
46 changes: 36 additions & 10 deletions src/ACAN2517FD.cpp
Original file line number Diff line number Diff line change
@@ -181,17 +181,17 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
}
//----------------------------------- Check mINT has interrupt capability
const int8_t itPin = digitalPinToInterrupt (mINT) ;
if (itPin == NOT_AN_INTERRUPT) {
if ((mINT != 255) && (itPin == NOT_AN_INTERRUPT)) {
errorCode = kINTPinIsNotAnInterrupt ;
}
//----------------------------------- Check isr is not NULL
if (inInterruptServiceRoutine == NULL) {
errorCode |= kISRIsNull ;
}
//----------------------------------- Check interrupt service routine is not null
if (inInterruptServiceRoutine == NULL) {
if ((mINT != 255) && (inInterruptServiceRoutine == NULL)) {
errorCode |= kISRIsNull ;
}
//----------------------------------- Check consistency between ISR and INT pin
if ((mINT == 255) && (inInterruptServiceRoutine != NULL)) {
errorCode |= kISRNotNullAndNoIntPin ;
}
//----------------------------------- Check TXQ size is <= 32
if (inSettings.mControllerTXQSize > 32) {
errorCode |= kControllerTXQSizeGreaterThan32 ;
@@ -446,11 +446,15 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
}
#ifdef ARDUINO_ARCH_ESP32
xTaskCreate (myESP32Task, "ACAN2517Handler", 1024, this, 256, NULL) ;
attachInterrupt (itPin, inInterruptServiceRoutine, FALLING) ;
#else
attachInterrupt (itPin, inInterruptServiceRoutine, LOW) ;
mSPI.usingInterrupt (itPin) ; // usingInterrupt is not implemented in Arduino ESP32
#endif
if (mINT != 255) { // 255 means interrupt is not used
#ifdef ARDUINO_ARCH_ESP32
attachInterrupt (itPin, inInterruptServiceRoutine, FALLING) ;
#else
attachInterrupt (itPin, inInterruptServiceRoutine, LOW) ;
mSPI.usingInterrupt (itPin) ; // usingInterrupt is not implemented in Arduino ESP32
#endif
}
}
//---
return errorCode ;
@@ -675,6 +679,28 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
return hasReceived ;
}

//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// POLLING (ESP32)
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

#ifdef ARDUINO_ARCH_ESP32
void ACAN2517FD::poll (void) {
xSemaphoreGive (mISRSemaphore) ;
}
#endif

//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// POLLING (other than ESP32)
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

#ifndef ARDUINO_ARCH_ESP32
void ACAN2517FD::poll (void) {
noInterrupts () ;
while (isr_core ()) {}
interrupts () ;
}
#endif

//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// INTERRUPT SERVICE ROUTINE (ESP32)
// https://stackoverflow.com/questions/51750377/how-to-disable-interrupt-watchdog-in-esp32-or-increase-isr-time-limit
7 changes: 7 additions & 0 deletions src/ACAN2517FD.h
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@ class ACAN2517FD {
public: static const uint32_t kRequestedModeTimeOut = 1 << 16 ;
public: static const uint32_t kX10PLLNotReadyWithin1MS = 1 << 17 ;
public: static const uint32_t kReadBackErrorWithFullSpeedSPIClock = 1 << 18 ;
public: static const uint32_t kISRNotNullAndNoIntPin = 1 << 19 ;

//······················································································································
// Send a message
@@ -146,6 +147,12 @@ class ACAN2517FD {
private: bool enterInTransmitBuffer (const CANFDMessage & inMessage) ;
private: void appendInControllerTxFIFO (const CANFDMessage & inMessage) ;

//······················································································································
// Polling
//······················································································································

public: void poll (void) ;

//······················································································································
// Interrupt service routine
//······················································································································

0 comments on commit 34ab8b8

Please sign in to comment.