Teensy 4.0 CAN2 (CRX2/CTX2) Not Working

andy123

Member
Hello, I'm having issues with my Teensy 4.0. I'm running the following code and successfully reading messages on CAN1 and CAN3 using the `can_rx_print()` function. I'm transmitting standard CAN 2.0 messages:
  • CAN1 is connected to CRX1 (Teensy pin 23) and CTX1 (Teensy pin 22)
  • CAN3 is connected to CRX3 (Teensy pin 30) and CTX3 (Teensy pin 31)

However, I'm unable to read/write any messages on CAN2, which is connected to CRX2 (Teensy pin 0) and CTX2 (Teensy pin 1).

I'm using the same transceiver and signal source that works with CAN1 and CAN3, I'm simply using jumper cables to hop between the teensy inputs. I've tested 2 teensy boards with the same results, making hardware issues unlikely. Pins were professionally soldered and have clean connections to the transceiver. I also tested CAN TX code which saw the same issue where I can read CAN1 and CAN3 via an off-the-shelf can reader fine but CAN2 is silent.


C++:
#include <Arduino.h>
#include <FlexCAN_T4.h>
#include "can.h"

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

void can_init() {
  can1.begin();
  can1.setBaudRate(500000);
  can2.begin();
  can2.setBaudRate(500000);
  can3.begin();
  can3.setBaudRate(500000);
}

void can_rx_print() {
  if (can1.read(msg)) {
    Serial.print(F("CAN1  MB: ")); Serial.print(msg.mb);
    Serial.print(F("  ID: 0x"));  Serial.print(msg.id, HEX);
    Serial.print(F("  EXT: "));   Serial.print(msg.flags.extended);
    Serial.print(F("  LEN: "));   Serial.print(msg.len);
    Serial.print(F(" DATA: "));
    for (uint8_t i = 0; i < msg.len; i++) {
      Serial.print(msg.buf[i], HEX); Serial.print(F(" "));
    }
    Serial.print(F("  TS: "));    Serial.println(msg.timestamp);
  }
  else if (can2.read(msg)) {
    Serial.print(F("CAN2  MB: ")); Serial.print(msg.mb);
    Serial.print(F("  ID: 0x"));  Serial.print(msg.id, HEX);
    Serial.print(F("  EXT: "));   Serial.print(msg.flags.extended);
    Serial.print(F("  LEN: "));   Serial.print(msg.len);
    Serial.print(F(" DATA: "));
    for (uint8_t i = 0; i < msg.len; i++) {
      Serial.print(msg.buf[i], HEX); Serial.print(F(" "));
    }
    Serial.print(F("  TS: "));    Serial.println(msg.timestamp);
  }
  else if (can3.read(msg)) {
    Serial.print(F("CAN3  MB: ")); Serial.print(msg.mb);
    Serial.print(F("  ID: 0x"));  Serial.print(msg.id, HEX);
    Serial.print(F("  EXT: "));   Serial.print(msg.flags.extended);
    Serial.print(F("  LEN: "));   Serial.print(msg.len);
    Serial.print(F(" DATA: "));
    for (uint8_t i = 0; i < msg.len; i++) {
      Serial.print(msg.buf[i], HEX); Serial.print(F(" "));
    }
    Serial.print(F("  TS: "));    Serial.println(msg.timestamp);
  }
}
bool can_send(uint8_t channel, uint32_t id, uint8_t len, const uint8_t *buf) {
  CAN_message_t tx;
  tx.id             = id;
  tx.flags.extended = 0;       // force 11-bit ID
  tx.len            = len;
  memcpy(tx.buf, buf, len);
  switch (channel) {
    case 2: return can2.write(tx);
    case 3: return can3.write(tx);
    default: return can1.write(tx);
  }
}


I also tried the following example code. I connected CANTX to CTX1(Teensy pin 22) and CANRX to CRX1(Teensy pin 23) via jumper cables, then reconnected CANTX to CTX2(Teensy pin 1) and CANRX to CRX2(Teensy pin 0). Shown at the very bottom, I only read CAN1.
C++:
#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);

  can1.begin();
  can1.setBaudRate(500000);
  can2.begin();
  can2.setBaudRate(500000);
}

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);
  }
  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);
  }
}

Serial Output: 
[QUOTE]
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 25604
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 953
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 42323
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 18309
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 59795
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 35546
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 11435
CAN1 MB: 0  ID: 0x614  EXT: 0  LEN: 8 DATA: 0 0 0 16 0 0 44 146   TS: 52781
[/QUOTE]
 
Your second sketch works fine. I can see printf from can1 and can2 like this:

Code:
CAN1 MB: 0  ID: 0x65  EXT: 0  LEN: 8 DATA: 85 52 66 50 50 86 87 89   TS: 869
CAN1 MB: 0  ID: 0x65  EXT: 0  LEN: 8 DATA: 85 52 66 50 50 86 87 89   TS: 30325
CAN1 MB: 0  ID: 0x65  EXT: 0  LEN: 8 DATA: 85 52 66 50 50 86 87 89   TS: 34418
CAN1 MB: 0  ID: 0x65  EXT: 0  LEN: 8 DATA: 85 52 66 50 50 86 87 89   TS: 49829
CAN2 MB: 0  ID: 0x65  EXT: 0  LEN: 8 DATA: 85 52 66 50 50 86 87 89   TS: 35710
CAN2 MB: 0  ID: 0x65  EXT: 0  LEN: 8 DATA: 85 52 66 50 50 86 87 89   TS: 49772
CAN2 MB: 0  ID: 0x65  EXT: 0  LEN: 8 DATA: 85 52 66 50 50 86 87 89   TS: 41116

Your first sketch doesn't compile. There is no setup or loop function.
You also don't need to include the "can.h"
 
It did compile, can.h is custom header, setup() and loop() are in a separate file. When I call can_rx_print() I can read CAN1 and CAN3 fine so it not a build issue. Please just focus on the second sketch if you're anxious about custom code issues. Thank you!
 
The second sketch works. It can display the frames from can1 and can2.
Check your wiring.
Make sure you have two 120R terminator on each end of your CAN network.
Using a scope, check you can see pulses on pin CRX2 of the Teensy.
 
It seems it may have been a breadboard issue. I tried a new breadboard with the same software and hardware setup, and it worked fine. Thank you for helping me narrow down the issue!
 
Back
Top