FlexCAN_T4 - FlexCAN for Teensy 4

Greetings --

New to the board. Is there a more detailed programming document for this library available other than what is posted on GitHub?
Thanks

It's a great library; although, I do wish the documentation was more detailed. Especially with how many tuning knobs and options there are. Of course, we're all free to submit pull requests with additions to the README...
 
I've run into another stumbling block. I'm trying to receive CAN-FD messages in an interrupt context.

Example sender code is:

Code:
#include <FlexCAN_T4.h>
#include <elapsedMillis.h>

FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_128> can;
elapsedMillis t_ms;
CANFD_message_t msg;

void setup() {
  can.begin();
  CANFD_timings_t cfg;
  cfg.clock = CLK_80MHz;
  cfg.baudrate = 1000000;
  cfg.baudrateFD = 8000000;
  cfg.propdelay = 190;
  cfg.bus_length = 1;
  cfg.sample = 70;
  can.setRegions(64);
  can.setBaudRate(cfg);
  msg.id = 0x01;
  msg.len = 5;
  Serial.begin(115200);
  delay(1000);
}

void loop() {
  if (t_ms >= 1000) {
    t_ms = 0;
    msg.buf[0]++;
    can.write(msg);
  }
}

Receiver code is:

Code:
#include <FlexCAN_T4.h>
FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_64> can;
CANFD_message_t msg;

void setup(void) {
  Serial.begin(115200);
  delay(400);
  can.begin();
  CANFD_timings_t cfg;
  cfg.clock = CLK_80MHz;
  cfg.baudrate = 1000000;
  cfg.baudrateFD = 8000000;
  cfg.propdelay = 190;
  cfg.bus_length = 1;
  cfg.sample = 70;
  can.setRegions(64);
  can.setBaudRate(cfg);
  can.setMBFilter(REJECT_ALL);
  can.enableMBInterrupts();
  can.onReceive(MB0, isr);
  can.setMBFilterRange(MB0, 0x00, 0xFF);
  can.mailboxStatus();
}

void isr(const CANFD_message_t &msg) {
  Serial.println("RECEIVED INT");
}

void loop() {
  if (can.read(msg)) {
    Serial.println("RECEIVED LOOP");
  }
}

My expectation is that I would see "RECEIVED INT" in the serial monitor, but I don't. I don't really care to do anything fancy with the mailboxes, I just want to receive all of the messages in the interrupt context because I plan to use the loop to do some other tasks. I would use the FIFO, but my understanding is that CAN-FD doesn't have a FIFO buffer (even though there is an enableFIFO method, so maybe my assumption is wrong). What do I need to do to make this work?

If I comment the following lines from setup, then I can receive the message in loop with "RECEIVED LOOP" printed to the serial monitor, which shows that my hardware setup is correct.

Code:
  can.setMBFilter(REJECT_ALL);
  can.enableMBInterrupts();
  can.onReceive(MB0, isr);
  can.setMBFilterRange(MB0, 0x00, 0xFF);
  can.mailboxStatus();
 
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;

#define NUM_TX_MAILBOXES 2
#define NUM_RX_MAILBOXES 6
void setup(void) {
Serial.begin(115200); delay(400);
Can0.begin();
Can0.setBaudRate(250000);
Can0.setMaxMB(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES);
for (int i = 0; i<NUM_RX_MAILBOXES; i++){
Can0.setMB(i,RX,EXT);
}
for (int i = NUM_RX_MAILBOXES; i<(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES); i++){
Can0.setMB(i,TX,EXT);
}
Can0.setMBFilter(REJECT_ALL);
Can0.enableMBInterrupts();
Can0.onReceive(MB0,canSniff);
Can0.onReceive(MB1,canSniff);
Can0.onReceive(MB2,canSniff);
Can0.setMBFilterProcessing(MB0,0x00,0xFF);
Can0.setMBFilterProcessing(MB1,0x03,0xFF);
Can0.setMBFilterProcessing(MB2,0x0B,0xFF);
Can0.mailboxStatus();
}

void canSniff(const CAN_message_t &msg) {
Serial.print("MB "); Serial.print(msg.mb);
Serial.print(" OVERRUN: "); Serial.print(msg.flags.overrun);
Serial.print(" LEN: "); Serial.print(msg.len);
Serial.print(" EXT: "); Serial.print(msg.flags.extended);
Serial.print(" TS: "); Serial.print(msg.timestamp);
Serial.print(" ID: "); Serial.print(msg.id, HEX);
Serial.print(" Buffer: ");
for ( uint8_t i = 0; i < msg.len; i++ ) {
Serial.print(msg.buf, HEX); Serial.print(" ");
} Serial.println();
}

void loop() {
Can0.events();
}
 
Hello,

Haven't hit this issue yet. Perhaps some ideas on making this code work could be found in the example code:

mailbox_filtering_example_with_interrupts

Thanks, I saw that and it works for CAN 2.0. I think there must be something with CAN-FD and the mailboxes / interrupts that I'm not understanding.
 
I've run into another stumbling block. I'm trying to receive CAN-FD messages in an interrupt context.

Example sender code is:

Code:
void isr(const CANFD_message_t &msg) {
  Serial.println("RECEIVED INT");
}

My expectation is that I would see "RECEIVED INT" in the serial monitor, but I don't. I don't really care to do anything fancy with the mailboxes, I just want to receive all of the messages in the interrupt context because I plan to use the loop to do some other tasks. I would use the FIFO, but my understanding is that CAN-FD doesn't have a FIFO buffer (even though there is an enableFIFO method, so maybe my assumption is wrong). What do I need to do to make this work?

This may not be related to your problem but I have experienced extremely weird behaviour when trying to call Serial.println() from an ISR. You might try toggling a LED instead to see if the ISR is being called.
 
It's my understanding the MCP2517FD chip logic controller code has and SPI command interface in the FlexCAN SPI code that sets the FD message send and recieve processing by mailboxes and interrupts.

Interrupts are intended to control and signal the mailbox events as they occor and are processed and the priorities of those send and recieve chip events for the mailboxes connevted to the FD CAN message bus.

FIFO processing is handled at the chip level (see the Microchip documentation) where the chip logic stages and controls the internal messaging buffers are used by send and recieve message commands. FIFO mailboxes for FD CAN 2.0B is recommended in most automotive CAN Bus designs.
 
Just FYI --

According to the FLEXCAN docs on GitHub..

Note that there is no FIFO support in CANFD for Teensy 4.0. FIFO is only supported in CAN2.0 mode on Teensy 3.x and Teensy 4.0
 
Code:
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;

#define NUM_TX_MAILBOXES 2
#define NUM_RX_MAILBOXES 6
void setup(void) {
	Serial.begin(115200); delay(400);
	Can0.begin();
	Can0.setBaudRate(250000);
	Can0.setMaxMB(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES);
	for (int i = 0; i < NUM_RX_MAILBOXES; i++) {
		Can0.setMB(i, RX, EXT);
	}
	for (int i = NUM_RX_MAILBOXES; i < (NUM_TX_MAILBOXES + NUM_RX_MAILBOXES); i++) {
		Can0.setMB(i, TX, EXT);
	}
	Can0.setMBFilter(REJECT_ALL);
	Can0.enableMBInterrupts();
	Can0.onReceive(MB0, canSniff);
	Can0.onReceive(MB1, canSniff);
	Can0.onReceive(MB2, canSniff);
	Can0.setMBFilterProcessing(MB0, 0x00, 0xFF);
	Can0.setMBFilterProcessing(MB1, 0x03, 0xFF);
	Can0.setMBFilterProcessing(MB2, 0x0B, 0xFF);
	Can0.mailboxStatus();
}

void canSniff(const CAN_message_t& msg) {
	Serial.print("MB "); Serial.print(msg.mb);
	Serial.print(" OVERRUN: "); Serial.print(msg.flags.overrun);
	Serial.print(" LEN: "); Serial.print(msg.len);
	Serial.print(" EXT: "); Serial.print(msg.flags.extended);
	Serial.print(" TS: "); Serial.print(msg.timestamp);
	Serial.print(" ID: "); Serial.print(msg.id, HEX);
	Serial.print(" Buffer: ");
	for (uint8_t i = 0; i < msg.len; i++) {
		Serial.print(msg.buf[i], HEX); Serial.print(" ");
	} Serial.println();
}

void loop() {
	Can0.events();
}
Can you please enclose any posted code between CODE tags using the # button at the top of the post form.
It presents your work in a much more readable and understandable manner making it much easier for people to help you.
 
I've run into another stumbling block. I'm trying to receive CAN-FD messages in an interrupt context.

Example sender code is:

Code:
#include <FlexCAN_T4.h>
#include <elapsedMillis.h>

FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_128> can;
elapsedMillis t_ms;
CANFD_message_t msg;

void setup() {
  can.begin();
  CANFD_timings_t cfg;
  cfg.clock = CLK_80MHz;
  cfg.baudrate = 1000000;
  cfg.baudrateFD = 8000000;
  cfg.propdelay = 190;
  cfg.bus_length = 1;
  cfg.sample = 70;
  can.setRegions(64);
  can.setBaudRate(cfg);
  msg.id = 0x01;
  msg.len = 5;
  Serial.begin(115200);
  delay(1000);
}

void loop() {
  if (t_ms >= 1000) {
    t_ms = 0;
    msg.buf[0]++;
    can.write(msg);
  }
}

Receiver code is:

Code:
#include <FlexCAN_T4.h>
FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_64> can;
CANFD_message_t msg;

void setup(void) {
  Serial.begin(115200);
  delay(400);
  can.begin();
  CANFD_timings_t cfg;
  cfg.clock = CLK_80MHz;
  cfg.baudrate = 1000000;
  cfg.baudrateFD = 8000000;
  cfg.propdelay = 190;
  cfg.bus_length = 1;
  cfg.sample = 70;
  can.setRegions(64);
  can.setBaudRate(cfg);
  can.setMBFilter(REJECT_ALL);
  can.enableMBInterrupts();
  can.onReceive(MB0, isr);
  can.setMBFilterRange(MB0, 0x00, 0xFF);
  can.mailboxStatus();
}

void isr(const CANFD_message_t &msg) {
  Serial.println("RECEIVED INT");
}

void loop() {
  if (can.read(msg)) {
    Serial.println("RECEIVED LOOP");
  }
}

My expectation is that I would see "RECEIVED INT" in the serial monitor, but I don't. I don't really care to do anything fancy with the mailboxes, I just want to receive all of the messages in the interrupt context because I plan to use the loop to do some other tasks. I would use the FIFO, but my understanding is that CAN-FD doesn't have a FIFO buffer (even though there is an enableFIFO method, so maybe my assumption is wrong). What do I need to do to make this work?

If I comment the following lines from setup, then I can receive the message in loop with "RECEIVED LOOP" printed to the serial monitor, which shows that my hardware setup is correct.

Code:
  can.setMBFilter(REJECT_ALL);
  can.enableMBInterrupts();
  can.onReceive(MB0, isr);
  can.setMBFilterRange(MB0, 0x00, 0xFF);
  can.mailboxStatus();

FYI, I just wanted to follow up that I've been working this issue on GitHub here:
https://github.com/tonton81/FlexCAN_T4/issues/56

Just in case someone runs into a similar problem and is looking for a solution. I'm suspecting that it's a bug in the library and issued a pull request with a fix.
 
Hi!

I'm trying to use can bus FD on my Teensy 4.0 thriple can bus board to send frames to rsp3, but it doesn't show any message while I use candump can0 on my rsp3. Can you help me out? Thx!!
I'm using the demo code below:

#include <FlexCAN_T4.h>

FlexCAN_T4FD<CAN3, RX_SIZE_256, TX_SIZE_16> FD; // can3 port



IntervalTimer timer;
uint8_t d=0;

void setup(void) {

Serial.begin(115200); delay(1000);
Serial.println("Teensy 4.0 Triple CAN test");

FD.begin();
CANFD_timings_t config;
config.clock = CLK_24MHz;
config.baudrate = 500000; // 500kbps arbitration rate
config.baudrateFD = 2000000; // 2000kbps data rate
config.propdelay = 190;
config.bus_length = 1;
config.sample = 75;
FD.setRegions(64);
FD.setBaudRateAdvanced(config, 1, 1);
FD.onReceive(canSniff);
FD.setMBFilter(ACCEPT_ALL);
FD.setMBFilter(MB13, 0x1);
FD.setMBFilter(MB12, 0x1, 0x3);
FD.setMBFilterRange(MB8, 0x1, 0x04);
FD.enableMBInterrupt(MB8);
FD.enableMBInterrupt(MB12);
FD.enableMBInterrupt(MB13);
FD.enhanceFilter(MB8);
FD.enhanceFilter(MB10);
FD.distribute();
FD.mailboxStatus();


timer.begin(sendframe, 500000); // Send frame every 500ms
}

void sendframe()
{
CANFD_message_t msg;
msg.len = 64;
msg.id = 0x4fd;
msg.seq = 1;
for ( uint8_t i = 0; i < 64; i++ ) {
msg.buf = i + 1;
//Serial.println(i);
}
msg.buf[0] = d;
FD.write(msg); // write to can3
//Serial.println();
}


void canSniff(const CANFD_message_t &msg) {
Serial.print("ISR - MB "); Serial.print(msg.mb);
Serial.print(" OVERRUN: "); Serial.print(msg.flags.overrun);
Serial.print(" LEN: "); Serial.print(msg.len);
Serial.print(" EXT: "); Serial.print(msg.flags.extended);
Serial.print(" TS: "); Serial.print(msg.timestamp);
Serial.print(" ID: "); Serial.print(msg.id, HEX);
Serial.print(" Buffer: ");
for ( uint8_t i = 0; i < msg.len; i++ ) {
Serial.print(msg.buf, HEX); Serial.print(" ");
} Serial.println();
}

void loop() {

CANFD_message_t msg;

FD.events(); /* needed for sequential frame transmit and callback queues */
if ( FD.readMB(msg) ) {
Serial.print("MB: "); Serial.print(msg.mb);
Serial.print(" OVERRUN: "); Serial.print(msg.flags.overrun);
Serial.print(" ID: 0x"); Serial.print(msg.id, HEX );
Serial.print(" EXT: "); Serial.print(msg.flags.extended );
Serial.print(" LEN: "); Serial.print(msg.len);
Serial.print(" BRS: "); Serial.print(msg.brs);
Serial.print(" EDL: "); Serial.print(msg.edl);
Serial.print(" DATA: ");
for ( uint8_t i = 0; i <msg.len ; i++ ) {
Serial.print(msg.buf); Serial.print(" ");
}
Serial.print(" TS: "); Serial.println(msg.timestamp);
}
}
 
Hi All,

I have been doing searching and haven't managed to find it anywhere so thought I would ask here. I have a Teensy 4.1 that I am using as a body/chassis ECU that sends data to a Raspberry Pi for a digital dash in my car. I am switching from an OEM ECU using OBD to an aftermarket ECU. The new ECU uses Haltech CAN bus protocol. Does anyone know how I alter the code so that the Teensy will read the Haltech CAN bus messages? I have added the code from Arduino IDE below. Many Thanks in advance

Code:
 #ifndef CANBUS_H
#define CANBUS_H

#include <FlexCAN_T4.h>
#include "values.h"

extern FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
extern Values values;

void canSend(uint8_t activeByte){
  CAN_message_t msgTx;
  msgTx.len = 3; // number of bytes in request
  msgTx.id = 0x7E0; // Request Header
  //  msgTx.flags.extended = 0; // 11 bit header, not 29 bit
  //  msgTx.flags.remote = 0;
  msgTx.buf[0] = 0x02; // Number of bytes in request
  msgTx.buf[1] = 0x01; // Mode of request (0x01 = OBD2)
  msgTx.buf[2] = activeByte;
  msgTx.buf[4] = 0x00;
  msgTx.buf[5] = 0x00; 
  msgTx.buf[6] = 0x00;
  msgTx.buf[7] = 0x00;
  can1.write(msgTx); 
}

void canReceive(const CAN_message_t &msg){
//  Serial.print("MB: ");
//  Serial.print(msg.mb);
//  Serial.print("  ID: 0x");
//  Serial.print(msg.id, HEX);
//  Serial.print("  EXT: ");
//  Serial.print(msg.flags.extended);
//  Serial.print("  LEN: ");
//  Serial.print(msg.len);
//  Serial.print(" DATA: ");
//  for (uint8_t i = 0; i < 8; i++) {
//    Serial.print(msg.buf[i], HEX);
//    Serial.print(" ");
//  }
//  Serial.println("");

  // Handle mode 41 messages
  if (msg.id == 0x7E8 && msg.buf[1] == 0x41) {
    switch (msg.buf[2]) {

      // RPM
      case 0x0c: {
        if (msg.buf[0] == 4) {
          values.rpm = ((msg.buf[3] * 256 + msg.buf[4]) / 4);
        }
      }
      break;

      // Coolant
      case 0x05: {
        if (msg.buf[0] == 3) {
          values.coolantTemp = (int)((((float)msg.buf[3] - 40.0f) * 1.8f) + 32.0f);
        }
      }
      break;

      // MAP
      case 0x0B: {
        if (msg.buf[0] == 3) {
          values.boostPressure = ((float)msg.buf[3] * 0.145038f) - values.barometricPressure;
        }
      }
      break;

      // Barometric pressure
      case 0x33: {
        if (msg.buf[0] == 3) {
          values.barometricPressure = (float)msg.buf[3] * 0.145038f;
        }
      }
      break;
      
    }
  }

  // Engine Fluid Level/Pressure 1
  if (msg.id == 0x18FEEF00) {
    // Oil pressure
    values.oilPressure = (float)msg.buf[3] * 4.0f * 0.145038f;
  }
}

void canInit() {
  can1.begin();
  can1.setBaudRate(500000);
  can1.enableFIFO();
  can1.enableFIFOInterrupt();
  can1.onReceive(canReceive);
}

#endif

Some info on Haltech:
Key Information
The Haltech CAN bus operates at 1MBit and uses 11-bit IDs. IDs are expressed in Hexadecimal.
The first byte in a packet is considered byte 0, and the 8th byte is byte 7. The most significant bit in a byte is considered bit 7 and the least significant bit is
bit 0.
Data is encoded as big endian.
haltech example.JPG
 
Last edited:
Hi All,

I have been doing searching and haven't managed to find it anywhere so thought I would ask here. I have a Teensy 4.1 that I am using as a body/chassis ECU that sends data to a Raspberry Pi for a digital dash in my car. I am switching from an OEM ECU using OBD to an aftermarket ECU. The new ECU uses Haltech CAN bus protocol. Does anyone know how I alter the code so that the Teensy will read the Haltech CAN bus messages? I have added the code from Arduino IDE below. Many Thanks in advance

Code:
 #ifndef CANBUS_H
#define CANBUS_H

#include <FlexCAN_T4.h>
#include "values.h"

extern FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
extern Values values;

void canSend(uint8_t activeByte){
  CAN_message_t msgTx;
  msgTx.len = 3; // number of bytes in request
  msgTx.id = 0x7E0; // Request Header
  //  msgTx.flags.extended = 0; // 11 bit header, not 29 bit
  //  msgTx.flags.remote = 0;
  msgTx.buf[0] = 0x02; // Number of bytes in request
  msgTx.buf[1] = 0x01; // Mode of request (0x01 = OBD2)
  msgTx.buf[2] = activeByte;
  msgTx.buf[4] = 0x00;
  msgTx.buf[5] = 0x00; 
  msgTx.buf[6] = 0x00;
  msgTx.buf[7] = 0x00;
  can1.write(msgTx); 
}

void canReceive(const CAN_message_t &msg){
//  Serial.print("MB: ");
//  Serial.print(msg.mb);
//  Serial.print("  ID: 0x");
//  Serial.print(msg.id, HEX);
//  Serial.print("  EXT: ");
//  Serial.print(msg.flags.extended);
//  Serial.print("  LEN: ");
//  Serial.print(msg.len);
//  Serial.print(" DATA: ");
//  for (uint8_t i = 0; i < 8; i++) {
//    Serial.print(msg.buf[i], HEX);
//    Serial.print(" ");
//  }
//  Serial.println("");

  // Handle mode 41 messages
  if (msg.id == 0x7E8 && msg.buf[1] == 0x41) {
    switch (msg.buf[2]) {

      // RPM
      case 0x0c: {
        if (msg.buf[0] == 4) {
          values.rpm = ((msg.buf[3] * 256 + msg.buf[4]) / 4);
        }
      }
      break;

      // Coolant
      case 0x05: {
        if (msg.buf[0] == 3) {
          values.coolantTemp = (int)((((float)msg.buf[3] - 40.0f) * 1.8f) + 32.0f);
        }
      }
      break;

      // MAP
      case 0x0B: {
        if (msg.buf[0] == 3) {
          values.boostPressure = ((float)msg.buf[3] * 0.145038f) - values.barometricPressure;
        }
      }
      break;

      // Barometric pressure
      case 0x33: {
        if (msg.buf[0] == 3) {
          values.barometricPressure = (float)msg.buf[3] * 0.145038f;
        }
      }
      break;
      
    }
  }

  // Engine Fluid Level/Pressure 1
  if (msg.id == 0x18FEEF00) {
    // Oil pressure
    values.oilPressure = (float)msg.buf[3] * 4.0f * 0.145038f;
  }
}

void canInit() {
  can1.begin();
  can1.setBaudRate(500000);
  can1.enableFIFO();
  can1.enableFIFOInterrupt();
  can1.onReceive(canReceive);
}

#endif

Some info on Haltech:
Key Information
The Haltech CAN bus operates at 1MBit and uses 11-bit IDs. IDs are expressed in Hexadecimal.
The first byte in a packet is considered byte 0, and the 8th byte is byte 7. The most significant bit in a byte is considered bit 7 and the least significant bit is
bit 0.
Data is encoded as big endian.
View attachment 30082

The general idea is to replace your canRecieve function with code that just checks for IDs you want. If ID matches 0x361 (for example), grab the correct bytes and join them, then convert to physical units. Also, be sure to correct the baud rate in canInit.

Here's an example of how to get oilPressure:
Code:
void canReceive(const CAN_message_t &msg){
  // Handle 0x361 messages (~50Hz)
  if (msg.id == 0x361) {
	  
	// Oil Pressure
	values.oilPressure = (float)(msg.buf[2]<<8 + msg.buf[3])/10.0f - 101.3f;
  }
}

*Note: I haven't checked or tested this code in any way*

If the numbers you are receiving don't make sense, try switching the byte order.
 
Hi, I have been succesfully using Teensy 4.0's as the can bridges based on modified code of the samples. Works great with 500k speed. But now I am struggling with the same software and hardware but using 83.3k speed. I have tried different clock speeds, bu no difference. by plugging in the device, seem to halt the canbus traffic.

Code:
#include <FlexCAN_T4.h>

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> can2;
CAN_message_t msg;

void setup(void) {
  Serial.begin(115200); delay(400);
  pinMode(2, OUTPUT); digitalWrite(2, LOW); /* optional tranceiver enable pin */
  pinMode(3, OUTPUT); digitalWrite(3, LOW); /* optional tranceiver enable pin */
  can1.begin();
  can1.setClock(CLK_60MHz);
//  can1.setBaudRate(500000);
  can1.setBaudRate(83330);
  can2.begin();
  can2.setClock(CLK_60MHz);
//  can2.setBaudRate(500000);
  can2.setBaudRate(83330);
}

void loop() {
    if ( can1.read(msg) ) {
      Serial.print("CAN1 "); 
      Serial.print("MB: "); Serial.print(msg.mb);
      Serial.print("  ID: 0x"); Serial.print(msg.id, HEX );
      Serial.print("  EXT: "); Serial.print(msg.flags.extended );
      Serial.print("  LEN: "); Serial.print(msg.len);
      Serial.print(" DATA: ");
      for ( uint8_t i = 0; i < 8; i++ ) {
        Serial.print(msg.buf[i]); Serial.print(" ");
      }
      Serial.print("  TS: "); Serial.println(msg.timestamp);
      can2.write(msg); // echo to can2
  }
  else if ( can2.read(msg) ) {
    Serial.print("CAN2 "); 
    Serial.print("MB: "); Serial.print(msg.mb);
    Serial.print("  ID: 0x"); Serial.print(msg.id, HEX );
    Serial.print("  EXT: "); Serial.print(msg.flags.extended );
    Serial.print("  LEN: "); Serial.print(msg.len);
    Serial.print(" DATA: ");
    for ( uint8_t i = 0; i < 8; i++ ) {
      Serial.print(msg.buf[i]); Serial.print(" ");
    }
    Serial.print("  TS: "); Serial.println(msg.timestamp);
  }
}

Any tips, what is it I am missing here?

Thanks!
 
Hi not sure if this is the right place, but I set up a CAN logger, but I want to start and stop with a pushbutton. I've been able to start it on command, but it won't shut off. How would I deconstruct/disable the CAN object?
 
There are a couple functions that could be considered. The CAN.reset() function resets the module, so you'd have to reconfigure every time you start logging.
FLEXCAN_EnterFreezeMode() and FLEXCAN_ExitFreezeMode() might be useful, but I can't say if any other steps would be required to fully disable or enable the module.
 
There are a couple functions that could be considered. The CAN.reset() function resets the module, so you'd have to reconfigure every time you start logging.
FLEXCAN_EnterFreezeMode() and FLEXCAN_ExitFreezeMode() might be useful, but I can't say if any other steps would be required to fully disable or enable the module.

Thanks, I did this, but kind of a kluge fix, I think.

Can1.disableFIFO();
Can1.disableFIFOInterrupt();
 
Greetings:

I was looking through some of the documentation, and I'm wondering if this library can catch errors like bus overload, bit stuffing errors, bus off conditions, and other error frame causes. Any ideas?
 
Yeah, check out the structure
Code:
typedef struct CAN_error_t
in FlexCAN_T4.h and the function
Code:
bool error(CAN_error_t &error, bool printDetails);
in FlexCAN_T4.tpp
 
OK, not a great coder. How would I actually invoke and print out the errors to console? I pass it a pointer to the structure and it populates it?
 
In your program, when you want to check if errors exist, you should be able to do something like this:
Code:
void loop() {
  ... some other code ...

  static uint32_t timeout = millis();
  if ( millis() - timeout > 1000 ) {  // Check for errors every 1000 ms
    CAN_error_t err;
    if CAN0.error(err, true) {
      // the "err" structure will be populated with the current errors.
      // Second argument set to true tells the error() function to ...
      // serial.print() the current errors. 
      ... some code to handle errors here ...
    }
  }
  ... some other code ...
}
 
Back
Top