diff --git a/FlexCAN.cpp b/FlexCAN.cpp index 7ad1312..5c3e614 100644 --- a/FlexCAN.cpp +++ b/FlexCAN.cpp @@ -1,6 +1,7 @@ // ------------------------------------------------------------- -// a simple Arduino Teensy3.1 CAN driver +// a simple Arduino Teensy 3.1/3.2/3.6 CAN driver // by teachop +// dual CAN support for MK66FX1M0 by Pawelsky // #include "FlexCAN.h" #include "kinetis_flexcan.h" @@ -9,54 +10,95 @@ static const int txb = 8; // with default settings, all buffers before this are static const int txBuffers = 8; static const int rxb = 0; +#define FLEXCANb_MCR(b) (*(vuint32_t*)(b)) +#define FLEXCANb_CTRL1(b) (*(vuint32_t*)(b+4)) +#define FLEXCANb_RXMGMASK(b) (*(vuint32_t*)(b+0x10)) +#define FLEXCANb_IFLAG1(b) (*(vuint32_t*)(b+0x30)) +#define FLEXCANb_RXFGMASK(b) (*(vuint32_t*)(b+0x48)) +#define FLEXCANb_MBn_CS(b, n) (*(vuint32_t*)(b+0x80+n*0x10)) +#define FLEXCANb_MBn_ID(b, n) (*(vuint32_t*)(b+0x84+n*0x10)) +#define FLEXCANb_MBn_WORD0(b, n) (*(vuint32_t*)(b+0x88+n*0x10)) +#define FLEXCANb_MBn_WORD1(b, n) (*(vuint32_t*)(b+0x8C+n*0x10)) +#define FLEXCANb_IDFLT_TAB(b, n) (*(vuint32_t*)(b+0xE0+(n*4))) + // ------------------------------------------------------------- -FlexCAN::FlexCAN(uint32_t baud) +FlexCAN::FlexCAN(uint32_t baud, uint8_t id, uint8_t txAlt, uint8_t rxAlt) { - // set up the pins, 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX - CORE_PIN3_CONFIG = PORT_PCR_MUX(2); - CORE_PIN4_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS; + flexcanBase = FLEXCAN0_BASE; +#ifdef __MK66FX1M0__ + if(id > 0) flexcanBase = FLEXCAN1_BASE; +#endif + + // set up the pins + if(flexcanBase == FLEXCAN0_BASE) + { +#ifdef __MK66FX1M0__ + // 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX (default) + // 29=PTB18=CAN0_TX, 30=PTB19=CAN0_RX (alternative) + if(txAlt == 1) CORE_PIN29_CONFIG = PORT_PCR_MUX(2); else CORE_PIN3_CONFIG = PORT_PCR_MUX(2); + if(rxAlt == 1) CORE_PIN30_CONFIG = PORT_PCR_MUX(2); else CORE_PIN4_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS; +#else + // 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX (default) + // 32=PTB18=CAN0_TX, 25=PTB19=CAN0_RX (alternative) + if(txAlt == 1) CORE_PIN32_CONFIG = PORT_PCR_MUX(2); else CORE_PIN3_CONFIG = PORT_PCR_MUX(2); + if(rxAlt == 1) CORE_PIN25_CONFIG = PORT_PCR_MUX(2); else CORE_PIN4_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS; +#endif + } +#ifdef __MK66FX1M0__ + else if(flexcanBase == FLEXCAN1_BASE) + { + // 33=PTE24=CAN1_TX, 34=PTE25=CAN1_RX (default) + // NOTE: Alternative CAN1 pins are not broken out on Teensy 3.6 + CORE_PIN33_CONFIG = PORT_PCR_MUX(2); + CORE_PIN34_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS; + } +#endif + // select clock source 16MHz xtal OSC0_CR |= OSC_ERCLKEN; - SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0; - FLEXCAN0_CTRL1 &= ~FLEXCAN_CTRL_CLK_SRC; + if(flexcanBase == FLEXCAN0_BASE) SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0; +#ifdef __MK66FX1M0__ + else if(flexcanBase == FLEXCAN1_BASE) SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1; +#endif + FLEXCANb_CTRL1(flexcanBase) &= ~FLEXCAN_CTRL_CLK_SRC; // enable CAN - FLEXCAN0_MCR |= FLEXCAN_MCR_FRZ; - FLEXCAN0_MCR &= ~FLEXCAN_MCR_MDIS; - while(FLEXCAN0_MCR & FLEXCAN_MCR_LPM_ACK) + FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_FRZ; + FLEXCANb_MCR(flexcanBase) &= ~FLEXCAN_MCR_MDIS; + while(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_LPM_ACK) ; // soft reset - FLEXCAN0_MCR ^= FLEXCAN_MCR_SOFT_RST; - while(FLEXCAN0_MCR & FLEXCAN_MCR_SOFT_RST) + FLEXCANb_MCR(flexcanBase) ^= FLEXCAN_MCR_SOFT_RST; + while(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_SOFT_RST) ; // wait for freeze ack - while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)) + while(!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK)) ; // disable self-reception - FLEXCAN0_MCR |= FLEXCAN_MCR_SRX_DIS; + FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_SRX_DIS; //enable RX FIFO - FLEXCAN0_MCR |= FLEXCAN_MCR_FEN; + FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_FEN; // segment splits and clock divisor based on baud rate - if ( 50000 == baud ) { - FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) - | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(19)); + if ( 50000 == baud ) { + FLEXCANb_CTRL1(flexcanBase) = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(19)); } else if ( 100000 == baud ) { - FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) - | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(9)); + FLEXCANb_CTRL1(flexcanBase) = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(9)); } else if ( 250000 == baud ) { - FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) - | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(3)); + FLEXCANb_CTRL1(flexcanBase) = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(3)); } else if ( 500000 == baud ) { - FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) - | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(1)); + FLEXCANb_CTRL1(flexcanBase) = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(1)); } else if ( 1000000 == baud ) { - FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(0) - | FLEXCAN_CTRL_PSEG1(1) | FLEXCAN_CTRL_PSEG2(1) | FLEXCAN_CTRL_PRESDIV(1)); + FLEXCANb_CTRL1(flexcanBase) = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(0) + | FLEXCAN_CTRL_PSEG1(1) | FLEXCAN_CTRL_PSEG2(1) | FLEXCAN_CTRL_PRESDIV(1)); } else { // 125000 - FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) - | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); + FLEXCANb_CTRL1(flexcanBase) = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); } // Default mask is allow everything @@ -70,8 +112,8 @@ FlexCAN::FlexCAN(uint32_t baud) void FlexCAN::end(void) { // enter freeze mode - FLEXCAN0_MCR |= (FLEXCAN_MCR_HALT); - while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)) + FLEXCANb_MCR(flexcanBase) |= (FLEXCAN_MCR_HALT); + while(!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK)) ; } @@ -79,26 +121,26 @@ void FlexCAN::end(void) // ------------------------------------------------------------- void FlexCAN::begin(const CAN_filter_t &mask) { - FLEXCAN0_RXMGMASK = 0; + FLEXCANb_RXMGMASK(flexcanBase) = 0; //enable reception of all messages that fit the mask if (mask.ext) { - FLEXCAN0_RXFGMASK = ((mask.rtr?1:0) << 31) | ((mask.ext?1:0) << 30) | ((mask.id & FLEXCAN_MB_ID_EXT_MASK) << 1); + FLEXCANb_RXFGMASK(flexcanBase) = ((mask.rtr?1:0) << 31) | ((mask.ext?1:0) << 30) | ((mask.id & FLEXCAN_MB_ID_EXT_MASK) << 1); } else { - FLEXCAN0_RXFGMASK = ((mask.rtr?1:0) << 31) | ((mask.ext?1:0) << 30) | (FLEXCAN_MB_ID_IDSTD(mask.id) << 1); + FLEXCANb_RXFGMASK(flexcanBase) = ((mask.rtr?1:0) << 31) | ((mask.ext?1:0) << 30) | (FLEXCAN_MB_ID_IDSTD(mask.id) << 1); } // start the CAN - FLEXCAN0_MCR &= ~(FLEXCAN_MCR_HALT); + FLEXCANb_MCR(flexcanBase) &= ~(FLEXCAN_MCR_HALT); // wait till exit of freeze mode - while(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK); + while(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK); // wait till ready - while(FLEXCAN0_MCR & FLEXCAN_MCR_NOT_RDY); + while(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_NOT_RDY); //set tx buffers to inactive for (int i = txb; i < txb + txBuffers; i++) { - FLEXCAN0_MBn_CS(i) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); + FLEXCANb_MBn_CS(flexcanBase, i) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); } } @@ -108,9 +150,9 @@ void FlexCAN::setFilter(const CAN_filter_t &filter, uint8_t n) { if ( 8 > n ) { if (filter.ext) { - FLEXCAN0_IDFLT_TAB(n) = ((filter.rtr?1:0) << 31) | ((filter.ext?1:0) << 30) | ((filter.id & FLEXCAN_MB_ID_EXT_MASK) << 1); + FLEXCANb_IDFLT_TAB(flexcanBase, n) = ((filter.rtr?1:0) << 31) | ((filter.ext?1:0) << 30) | ((filter.id & FLEXCAN_MB_ID_EXT_MASK) << 1); } else { - FLEXCAN0_IDFLT_TAB(n) = ((filter.rtr?1:0) << 31) | ((filter.ext?1:0) << 30) | (FLEXCAN_MB_ID_IDSTD(filter.id) << 1); + FLEXCANb_IDFLT_TAB(flexcanBase, n) = ((filter.rtr?1:0) << 31) | ((filter.ext?1:0) << 30) | (FLEXCAN_MB_ID_IDSTD(filter.id) << 1); } } } @@ -120,7 +162,7 @@ void FlexCAN::setFilter(const CAN_filter_t &filter, uint8_t n) int FlexCAN::available(void) { //In FIFO mode, the following interrupt flag signals availability of a frame - return (FLEXCAN0_IFLAG1 & FLEXCAN_IMASK1_BUF5M)? 1:0; + return (FLEXCANb_IFLAG1(flexcanBase) & FLEXCAN_IMASK1_BUF5M)? 1:0; } @@ -140,15 +182,16 @@ int FlexCAN::read(CAN_message_t &msg) } // get identifier and dlc - msg.len = FLEXCAN_get_length(FLEXCAN0_MBn_CS(rxb)); - msg.ext = (FLEXCAN0_MBn_CS(rxb) & FLEXCAN_MB_CS_IDE)? 1:0; - msg.id = (FLEXCAN0_MBn_ID(rxb) & FLEXCAN_MB_ID_EXT_MASK); + msg.len = FLEXCAN_get_length(FLEXCANb_MBn_CS(flexcanBase, rxb)); + msg.ext = (FLEXCANb_MBn_CS(flexcanBase, rxb) & FLEXCAN_MB_CS_IDE)? 1:0; + msg.rtr = (FLEXCANb_MBn_CS(flexcanBase, rxb) & FLEXCAN_MB_CS_RTR)? 1:0; + msg.id = (FLEXCANb_MBn_ID(flexcanBase, rxb) & FLEXCAN_MB_ID_EXT_MASK); if(!msg.ext) { msg.id >>= FLEXCAN_MB_ID_STD_BIT_NO; } // copy out message - uint32_t dataIn = FLEXCAN0_MBn_WORD0(rxb); + uint32_t dataIn = FLEXCANb_MBn_WORD0(flexcanBase, rxb); msg.buf[3] = dataIn; dataIn >>=8; msg.buf[2] = dataIn; @@ -157,7 +200,7 @@ int FlexCAN::read(CAN_message_t &msg) dataIn >>=8; msg.buf[0] = dataIn; if ( 4 < msg.len ) { - dataIn = FLEXCAN0_MBn_WORD1(rxb); + dataIn = FLEXCANb_MBn_WORD1(flexcanBase, rxb); msg.buf[7] = dataIn; dataIn >>=8; msg.buf[6] = dataIn; @@ -171,7 +214,7 @@ int FlexCAN::read(CAN_message_t &msg) } //notify FIFO that message has been read - FLEXCAN0_IFLAG1 = FLEXCAN_IMASK1_BUF5M; + FLEXCANb_IFLAG1(flexcanBase) = FLEXCAN_IMASK1_BUF5M; return 1; } @@ -187,7 +230,7 @@ int FlexCAN::write(const CAN_message_t &msg) // find an available buffer int buffer = -1; for ( int index = txb; ; ) { - if ((FLEXCAN0_MBn_CS(index) & FLEXCAN_MB_CS_CODE_MASK) == FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE)) { + if ((FLEXCANb_MBn_CS(flexcanBase, index) & FLEXCAN_MB_CS_CODE_MASK) == FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE)) { buffer = index; break;// found one } @@ -205,20 +248,30 @@ int FlexCAN::write(const CAN_message_t &msg) } // transmit the frame - FLEXCAN0_MBn_CS(buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); + FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); if(msg.ext) { - FLEXCAN0_MBn_ID(buffer) = (msg.id & FLEXCAN_MB_ID_EXT_MASK); + FLEXCANb_MBn_ID(flexcanBase, buffer) = (msg.id & FLEXCAN_MB_ID_EXT_MASK); } else { - FLEXCAN0_MBn_ID(buffer) = FLEXCAN_MB_ID_IDSTD(msg.id); + FLEXCANb_MBn_ID(flexcanBase, buffer) = FLEXCAN_MB_ID_IDSTD(msg.id); } - FLEXCAN0_MBn_WORD0(buffer) = (msg.buf[0]<<24)|(msg.buf[1]<<16)|(msg.buf[2]<<8)|msg.buf[3]; - FLEXCAN0_MBn_WORD1(buffer) = (msg.buf[4]<<24)|(msg.buf[5]<<16)|(msg.buf[6]<<8)|msg.buf[7]; + FLEXCANb_MBn_WORD0(flexcanBase, buffer) = (msg.buf[0]<<24)|(msg.buf[1]<<16)|(msg.buf[2]<<8)|msg.buf[3]; + FLEXCANb_MBn_WORD1(flexcanBase, buffer) = (msg.buf[4]<<24)|(msg.buf[5]<<16)|(msg.buf[6]<<8)|msg.buf[7]; if(msg.ext) { - FLEXCAN0_MBn_CS(buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) - | FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_SRR | FLEXCAN_MB_CS_IDE; + if(msg.rtr) { + FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) + | FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_SRR | FLEXCAN_MB_CS_IDE | FLEXCAN_MB_CS_RTR; + } else { + FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) + | FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_SRR | FLEXCAN_MB_CS_IDE; + } } else { - FLEXCAN0_MBn_CS(buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) - | FLEXCAN_MB_CS_LENGTH(msg.len); + if(msg.rtr) { + FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) + | FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_RTR; + } else { + FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) + | FLEXCAN_MB_CS_LENGTH(msg.len); + } } return 1; diff --git a/FlexCAN.h b/FlexCAN.h index 19e92e8..642c303 100644 --- a/FlexCAN.h +++ b/FlexCAN.h @@ -1,6 +1,7 @@ // ------------------------------------------------------------- -// a simple Arduino Teensy3.1 CAN driver +// a simple Arduino Teensy 3.1/3.2/3.6 CAN driver // by teachop +// dual CAN support for MK66FX1M0 by Pawelsky // #ifndef __FLEXCAN_H__ #define __FLEXCAN_H__ @@ -10,6 +11,7 @@ typedef struct CAN_message_t { uint32_t id; // can identifier uint8_t ext; // identifier is extended + uint8_t rtr; // remote transmission request packet type uint8_t len; // length of data uint16_t timeout; // milliseconds, zero will disable waiting uint8_t buf[8]; @@ -26,9 +28,10 @@ class FlexCAN { private: struct CAN_filter_t defaultMask; + uint32_t flexcanBase; public: - FlexCAN(uint32_t baud = 125000); + FlexCAN(uint32_t baud = 125000, uint8_t id = 0, uint8_t txAlt = 0, uint8_t rxAlt = 0); void begin(const CAN_filter_t &mask); inline void begin() { diff --git a/FlexCAN_pins_36.png b/FlexCAN_pins_36.png new file mode 100644 index 0000000..731707c Binary files /dev/null and b/FlexCAN_pins_36.png differ diff --git a/README.md b/README.md index e94ffd8..214bf84 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,20 @@ -##CANbus Library for Teensy 3.1 +##CANbus Library for Teensy 3.1, 3.2 and 3.6 ###Introduction -FlexCAN is a serial communication driver for the CAN0 peripheral built into the Teensy 3.1 CPU. The driver is organized in the Arduino library format. +FlexCAN is a serial communication driver for the CAN peripherial built into the Teensy CPUs. Versions 3.1 and 3.2 of the board support single CAN0 controller while version 3.6 supports dual CAN0/CAN1 controllers. The driver is organized in the Arduino library format. -When the FlexCAN object is constructed, Arduino pins Digital 3 and Digital 4 are assigned to CAN functions TX and RX. These should be wired to a 3.3V CAN transceiver TXD and RXD respectively to allow connection of the Teensy 3.1 to a CAN network. +When the FlexCAN object is constructed on Teensy 3.1/3.2, Arduino pins Digital 3 and Digital 4 are assigned to CAN functions TX and RX. -![Teensy 3.1 CAN Pins, Digital3=TX, Digital4=RX](/FlexCAN_pins.png) +![Teensy 3.1/3.2 CAN Pins, Digital3=TX, Digital4=RX](/FlexCAN_pins.png) -Even though the Teensy is operating on 3.3V, use of 5V transceivers may be an option if the system has regulated +5V available. The CAN RXD input on the CPU is 5V tolerant and most 5V transceivers will accept the 3V TXD signal. This is a good choice for breadboarding due to availability of thru-hole 5V transceiver parts. +On Teensy 3.6 it is possible to to specify the **id** parameter and select whether CAN0 or CAN1 shall be used. For CAN0 Arduino pins Digital 3 and Digital 4 are assigned to CAN functions TX and RX. For CAN1 Arduino pins Digital 34 and Digital 33 are assigned to CAN functions TX and RX. + +![Teensy 3.6 CAN Pins, CAN0: Digital3=TX and Digital4=RX, CAN1: Digital34=TX and Digital33=RX](/FlexCAN_pins_36.png) + +CAN RX and TX pins should be wired to a 3.3V CAN transceiver TXD and RXD respectively to allow connection of the Teensy 3.1/3.2/3.6 to a CAN network. + +Even though the Teensy 3.1/3.2 is operating on 3.3V, use of 5V transceivers may be an option if the system has regulated +5V available. The CAN RXD input on the CPU is 5V tolerant and most 5V transceivers will accept the 3V TXD signal. This is a good choice for breadboarding due to availability of thru-hole 5V transceiver parts. +**In case of Teensy 3.6 the digital pins are not 5V tolerant, so 3.3V transceivers must be used!** Note that CAN will normally require termination resistors. These are located at the two ends of a CAN bus to prevent reflections. Do not add more terminators when connecting devices to an existing properly terminated CAN bus. @@ -20,6 +27,7 @@ Please add parts you are using successfully with Teensy 3.1 to this list. - NXP TJA1050T/VM,118 on the same 5V supply as the Teensy. (1MBPS) - Microchip MCP2551 on 5V (reported at 500KBPS) - Linear LT1796 on 5V (not speedtested) +- Microchip MCP2562 with VIO on 3.3V (tested on Teensy 3.2 and 3.6) ###Driver API **begin()** diff --git a/examples/dualCANtest/dualCANtest.ino b/examples/dualCANtest/dualCANtest.ino new file mode 100644 index 0000000..f042936 --- /dev/null +++ b/examples/dualCANtest/dualCANtest.ino @@ -0,0 +1,62 @@ +// ------------------------------------------------------------- +// CANtest for Teensy 3.6 dual CAN bus +// by Pawelsky (based on CANtest by teachop) +// +// This test transmits all data coming from CAN0 to CAN1 and vice versa (at 1Mbps) +// + +#include + +#ifndef __MK66FX1M0__ + #error "Teensy 3.6 with dual CAN bus is required to run this example" +#endif + +FlexCAN CANbus0(1000000, 0); +FlexCAN CANbus1(1000000, 1); + +static CAN_message_t msg; +static uint8_t hex[17] = "0123456789abcdef"; + + +// ------------------------------------------------------------- +static void hexDump(uint8_t dumpLen, uint8_t *bytePtr) +{ + uint8_t working; + while( dumpLen-- ) { + working = *bytePtr++; + Serial.write( hex[ working>>4 ] ); + Serial.write( hex[ working&15 ] ); + } + Serial.write('\r'); + Serial.write('\n'); +} + + +// ------------------------------------------------------------- +void setup(void) +{ + CANbus0.begin(); + CANbus1.begin(); + + delay(1000); + Serial.println(F("Hello Teensy 3.6 dual CAN Test.")); +} + + +// ------------------------------------------------------------- +void loop(void) +{ + if(CANbus0.available()) + { + CANbus0.read(msg); +// Serial.print("CAN bus 0: "); hexDump(8, msg.buf); + CANbus1.write(msg); + } + + if(CANbus1.available()) + { + CANbus1.read(msg); +// Serial.print("CAN bus 1: "); hexDump(8, msg.buf); + CANbus0.write(msg); + } +} \ No newline at end of file