diff --git a/FlexCAN.cpp b/FlexCAN.cpp index 7ad1312..2081f53 100644 --- a/FlexCAN.cpp +++ b/FlexCAN.cpp @@ -1,6 +1,6 @@ // ------------------------------------------------------------- // a simple Arduino Teensy3.1 CAN driver -// by teachop +// by teachop, modified by xboxpro1 // #include "FlexCAN.h" #include "kinetis_flexcan.h" @@ -10,7 +10,7 @@ static const int txBuffers = 8; static const int rxb = 0; // ------------------------------------------------------------- -FlexCAN::FlexCAN(uint32_t baud) +FlexCAN::FlexCAN(void) { // set up the pins, 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX CORE_PIN3_CONFIG = PORT_PCR_MUX(2); @@ -23,62 +23,209 @@ FlexCAN::FlexCAN(uint32_t baud) // enable CAN FLEXCAN0_MCR |= FLEXCAN_MCR_FRZ; FLEXCAN0_MCR &= ~FLEXCAN_MCR_MDIS; - while(FLEXCAN0_MCR & FLEXCAN_MCR_LPM_ACK) - ; + while(FLEXCAN0_MCR & FLEXCAN_MCR_LPM_ACK); + + // Default mask is allow everything + defaultMask.rtr = 0; + defaultMask.ext = 0; + defaultMask.id = 0; +} + +// ------------------------------------------------------------- +void FlexCAN::end(void) +{ + // enter freeze mode + FLEXCAN0_MCR |= (FLEXCAN_MCR_HALT); + while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)); +} + +void FlexCAN::reset(void) +{ // soft reset FLEXCAN0_MCR ^= FLEXCAN_MCR_SOFT_RST; - while(FLEXCAN0_MCR & FLEXCAN_MCR_SOFT_RST) - ; + while(FLEXCAN0_MCR & FLEXCAN_MCR_SOFT_RST); + // wait for freeze ack - while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)) - ; + while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)); + // disable self-reception FLEXCAN0_MCR |= FLEXCAN_MCR_SRX_DIS; //enable RX FIFO FLEXCAN0_MCR |= FLEXCAN_MCR_FEN; + + //enable TIMER SYNC + FLEXCAN0_CTRL1 |= FLEXCAN_CTRL_TSYNC; + + //enable Remote Request Storing + FLEXCAN0_CTRL2 |= FLEXCAN_CTRL2_RRS; +} + + +// ------------------------------------------------------------- +void FlexCAN::begin(uint8_t _baud) +{ + // soft reset can bus + reset(); + // 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)); - } 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)); - } 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)); - } 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)); - } 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)); - } else { // 125000 - FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) - | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); + switch (_baud){ + + case (CAN_5KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(199)); // 5000 baud Prescaler -> 199 Tq -> 16 + break; + + case (CAN_10KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(99)); // 10000 baud Prescaler -> 99 Tq -> 16 + break; + + case (CAN_20KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(49)); // 20000 baud Prescaler -> 49 Tq -> 16 + break; + + case (CAN_25KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(39)); // 25000 baud Prescaler -> 39 Tq -> 16 + break; + + case (CAN_31K25BPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(31)); // 31250 baud Prescaler -> 31 Tq -> 16 + break; + + case (CAN_33KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(29)); // 33333 baud Prescaler -> 29 Tq -> 16 + break; + + case (CAN_40KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(24)); // 40000 baud Prescaler -> 24 Tq -> 16 + break; + + case (CAN_50KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(19)); // 50000 baud Prescaler -> 19 Tq -> 16 + break; + + case (CAN_80KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1) + | FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(1) | FLEXCAN_CTRL_PRESDIV(19)); // 80000 baud Prescaler -> 19 !!Tq -> 10!! + break; + + case (CAN_83K3BPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(11)); // 83333 baud Prescaler -> 11 Tq -> 16 + break; + + case (CAN_95KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) + | FLEXCAN_CTRL_PSEG1(4) | FLEXCAN_CTRL_PSEG2(2) | FLEXCAN_CTRL_PRESDIV(13)); // 95000 baud Prescaler -> 13 !!Tq -> 12!! + break; + + case (CAN_100KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(9)); // 100000 baud Prescaler -> 9 Tq -> 16 + break; + + case (CAN_125KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); // 125000 baud Prescaler -> 7 Tq -> 16 + break; + + case (CAN_200KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(4)); // 200000 baud Prescaler -> 4 Tq -> 16 + break; + + case (CAN_250KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(3)); // 250000 baud Prescaler -> 3 Tq -> 16 + break; + + case (CAN_500KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(1)); // 500000 baud Prescaler -> 1 Tq -> 16 + break; + + case (CAN_666KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) + | FLEXCAN_CTRL_PSEG1(4) | FLEXCAN_CTRL_PSEG2(2) | FLEXCAN_CTRL_PRESDIV(1)); // 666666 baud Prescaler -> 1 !!Tq -> 12!! + break; + + case (CAN_1000KBPS): + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(0)); // 100000 baud Prescaler -> 0 Tq -> 16 + break; + + default: // 125000 + FLEXCAN0_CTRL1 = (FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2) + | FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(3) | FLEXCAN_CTRL_PRESDIV(7)); // 125000 baud Prescaler -> 7 Tq -> 16 + break; } + + //enable reception of all messages + FLEXCAN0_RXMGMASK = 0; + FLEXCAN0_RXFGMASK = ((defaultMask.rtr?1:0) << 31) | ((defaultMask.ext?1:0) << 30) | (FLEXCAN_MB_ID_IDSTD(defaultMask.id) << 1); + + // start the CAN + FLEXCAN0_MCR &= ~(FLEXCAN_MCR_HALT); + // wait till exit of freeze mode + while(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK); - // Default mask is allow everything - defaultMask.rtr = 0; - defaultMask.ext = 0; - defaultMask.id = 0; -} + // wait till ready + while(FLEXCAN0_MCR & 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); + } +} // ------------------------------------------------------------- -void FlexCAN::end(void) +int FlexCAN::connect(int _speed, int _check) // auto connect with speed test, speed index 1 - 18 , Error ---> 255 { - // enter freeze mode - FLEXCAN0_MCR |= (FLEXCAN_MCR_HALT); - while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)) - ; + int _speedindex = 255; + + if (_speed == 0){ // if _speed = 0 --> check the bus speed from 1 to 18 + for (int _x = 1; _x <= 18; _x ++){ + begin(_x); + delay(100); + if(1 == available()){ // if frame available speed is correct + _speedindex = _x; + break; + } + } + } + else { // if _speed from 1 to 18 use given bus speed + begin(_speed); + if(_check == 1){ // if _check = 1 check the given bus speed + delay(100); + if(1 == available()){ // if frame available speed is correct + _speedindex = _speed; + } + } + else { + _speedindex = _speed; // return the given bus speed index without speed test + } + } + if(_speedindex == 255){ // enter freeze mode if speed is incorrect + end(); + } + return _speedindex; // return the bus speed index 1 - 18 , Error ---> 255 } - // ------------------------------------------------------------- -void FlexCAN::begin(const CAN_filter_t &mask) +void FlexCAN::setMask(const CAN_filter_t &mask) { + // enter freeze mode + FLEXCAN0_MCR |= (FLEXCAN_MCR_HALT); + while(!(FLEXCAN0_MCR & FLEXCAN_MCR_FRZ_ACK)); + FLEXCAN0_RXMGMASK = 0; //enable reception of all messages that fit the mask @@ -100,13 +247,14 @@ void FlexCAN::begin(const CAN_filter_t &mask) for (int i = txb; i < txb + txBuffers; i++) { FLEXCAN0_MBn_CS(i) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE); } + } // ------------------------------------------------------------- void FlexCAN::setFilter(const CAN_filter_t &filter, uint8_t n) { - if ( 8 > n ) { + if ( n < 8) { 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); } else { @@ -115,7 +263,20 @@ void FlexCAN::setFilter(const CAN_filter_t &filter, uint8_t n) } } +// ------------------------------------------------------------- +void FlexCAN::clearFilter(void) +{ + for (int _x = 0; _x < 8; _x ++){ + setFilter(defaultMask, _x); + } +} +// ------------------------------------------------------------- +void FlexCAN::clearMask(void) +{ + setMask(defaultMask); +} + // ------------------------------------------------------------- int FlexCAN::available(void) { @@ -123,6 +284,12 @@ int FlexCAN::available(void) return (FLEXCAN0_IFLAG1 & FLEXCAN_IMASK1_BUF5M)? 1:0; } +int FlexCAN::synchron(void) +{ + //Check if synchronized with the can bus + return (FLEXCAN0_ESR1 & FLEXCAN_ESR_SYNCH)? 1:0; +} + // ------------------------------------------------------------- int FlexCAN::read(CAN_message_t &msg) @@ -141,8 +308,10 @@ int FlexCAN::read(CAN_message_t &msg) // get identifier and dlc msg.len = FLEXCAN_get_length(FLEXCAN0_MBn_CS(rxb)); + msg.req = (FLEXCAN0_MBn_CS(rxb) & FLEXCAN_MB_CS_RTR)? 1:0; msg.ext = (FLEXCAN0_MBn_CS(rxb) & FLEXCAN_MB_CS_IDE)? 1:0; msg.id = (FLEXCAN0_MBn_ID(rxb) & FLEXCAN_MB_ID_EXT_MASK); + if(!msg.ext) { msg.id >>= FLEXCAN_MB_ID_STD_BIT_NO; } @@ -169,8 +338,9 @@ int FlexCAN::read(CAN_message_t &msg) for( int loop=msg.len; loop<8; ++loop ) { msg.buf[loop] = 0; } - + //notify FIFO that message has been read + msg.timestamp = (FLEXCAN0_MBn_CS(rxb) & FLEXCAN_MB_CS_TIMESTAMP_MASK); FLEXCAN0_IFLAG1 = FLEXCAN_IMASK1_BUF5M; return 1; @@ -214,13 +384,22 @@ int FlexCAN::write(const CAN_message_t &msg) 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]; if(msg.ext) { - FLEXCAN0_MBn_CS(buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) + if(msg.req){ + 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 | FLEXCAN_MB_CS_RTR; + } else { + 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; + } } else { - FLEXCAN0_MBn_CS(buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) + if(msg.req){ + FLEXCAN0_MBn_CS(buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) + | FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_RTR; + } else { + FLEXCAN0_MBn_CS(buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) | FLEXCAN_MB_CS_LENGTH(msg.len); + } } return 1; -} - +} \ No newline at end of file diff --git a/FlexCAN.h b/FlexCAN.h index 19e92e8..e7a7bd9 100644 --- a/FlexCAN.h +++ b/FlexCAN.h @@ -6,11 +6,14 @@ #define __FLEXCAN_H__ #include +#include "kinetis_flexcan.h" typedef struct CAN_message_t { uint32_t id; // can identifier uint8_t ext; // identifier is extended + uint8_t req; // message is request uint8_t len; // length of data + uint16_t timestamp; // receive frame timestamp uint16_t timeout; // milliseconds, zero will disable waiting uint8_t buf[8]; } CAN_message_t; @@ -28,15 +31,17 @@ class FlexCAN struct CAN_filter_t defaultMask; public: - FlexCAN(uint32_t baud = 125000); - void begin(const CAN_filter_t &mask); - inline void begin() - { - begin(defaultMask); - } + FlexCAN(); + void begin(uint8_t _baud = CAN_125KBPS); + int connect(int _speed = 0, int _check = 0); + void setMask(const CAN_filter_t &mask); void setFilter(const CAN_filter_t &filter, uint8_t n); + void clearFilter(void); + void clearMask(void); void end(void); + void reset(void); int available(void); + int synchron(void); int write(const CAN_message_t &msg); int read(CAN_message_t &msg); diff --git a/README.md b/README.md index e94ffd8..862fc5a 100644 --- a/README.md +++ b/README.md @@ -11,27 +11,44 @@ Even though the Teensy is operating on 3.3V, use of 5V transceivers may be an op 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. -Supported baud rates are 50000, 100000, 125000, 250000, 500000, and 1000000 bits per second. If the baud rate is not specified it will default to 125000. - +Supported baud rates are 5000, 10000, 20000, 25000, 31250, 33333, 40000, 50000, 80000, 83333, 95000, 100000, 125000, 200000, 250000, 500000, 666666, and 1000000 bits per second. If the baud rate is not specified it will default to 125000. Use given speedindex in: +###bus-speed-definitions.txt +If you want to add another speed, use the Excel sheet +###can-timing.xls +![Can Timing](/can-timing.png) ###CAN Transceiver Options Please add parts you are using successfully with Teensy 3.1 to this list. - TI SN65HVD230D on 3.3V (1MBPS) - TI SN65HVD232D / SN65HVD232QDQ1 on 3.3V (1MBPS) - NXP TJA1050T/VM,118 on the same 5V supply as the Teensy. (1MBPS) -- Microchip MCP2551 on 5V (reported at 500KBPS) +- Microchip MCP2551/2 on 5V (1MBPS) - Linear LT1796 on 5V (not speedtested) ###Driver API -**begin()** -Enable the CAN to start actively participating on the CANbus. +**begin(speedindex)** +Enable the CAN to start actively participating on the CANbus. Default speedindex is CAN_125KBPS. + +**connect(speedindex, check)** +Enable the CAN to start actively participating on the CANbus with given speedindex. If check = 1 the device checks if there is a frame available. If speedindex = 0, the device try an Auto Connect on the CANbus. Default (0, 0). See autoconnect.ino. +Returns speedindex 1 - 18, 255 -> Error, CANbus not connected or speed is not available. **end()** Disable the CAN from participating on the CANbus. Pins remain assigned to the alternate function CAN0. +**reset()** +Softreset the device and enter freeze mode. + **write(message)** Send a frame of up to 8 bytes using the given identifier. **write()** will return 0 if no buffer was available for sending (see "Caller blocking" below). message is a **CAN_message_t** type buffer structure. +- uint32_t id; // can identifier +- uint8_t ext; // identifier is extended +- uint8_t req; // message is request +- uint8_t len; // length of data +- uint16_t timestamp; // receive frame timestamp +- uint16_t timeout; // milliseconds, zero will disable waiting +- uint8_t buf[8]; // 8 byte data buffer **read(message)** Receive a frame into "message" if available. **read()** will return 1 if a frame was copied into the callers buffer, or 0 if no frame is available (see "Caller blocking" below). @@ -39,14 +56,26 @@ Receive a frame into "message" if available. **read()** will return 1 if a fram **available()** Returns 1 if at least one receive frame is waiting, or 0 if no frame is available. +**synchron()** +Returns 1 if the device is synchron with CANbus, or 0 if not synchron. + ###Use of Optional RX Filtering -**begin(mask)** -Enable the CAN to start actively participating on the CANbus. Enable reception of all messages that fit the mask. This is a global mask that applies to all the receive filters. +**setMask(mask)** +Enable reception of all messages that fit the mask. This is a global mask that applies to all the receive filters. **setFilter(filter, number)** Set the receive filter selected by number, 0-7. When using filters it is required to set them all. If the application uses less than 8 filters, duplicate one filter for the unused ones. The mask and filter are **CAN_filter_t** type structures. +- uint8_t rtr; // request can identifier +- uint8_t ext; // extended can identifier +- uint32_t id; // can identifier + +**clearMask()** +Enable reception of all messages. + +**clearFilter()** +Clear filter from 0 - 7. ###Caller Blocking Support Support has been included for wait / blocking in both the **read()** and **write()** calls. diff --git a/bus-speed-definitions.txt b/bus-speed-definitions.txt new file mode 100644 index 0000000..7e40f49 --- /dev/null +++ b/bus-speed-definitions.txt @@ -0,0 +1,21 @@ +Bus speed definitions + +Const Speed Index +CAN_5KBPS 1 +CAN_10KBPS 2 +CAN_20KBPS 3 +CAN_25KBPS 4 +CAN_31K25BPS 5 +CAN_33KBPS 6 +CAN_40KBPS 7 +CAN_50KBPS 8 +CAN_80KBPS 9 +CAN_83K3BPS 10 +CAN_95KBPS 11 +CAN_100KBPS 12 +CAN_125KBPS 13 +CAN_200KBPS 14 +CAN_250KBPS 15 +CAN_500KBPS 16 +CAN_666KBPS 17 +CAN_1000KBPS 18 diff --git a/can-timing.png b/can-timing.png new file mode 100644 index 0000000..8cff0c2 Binary files /dev/null and b/can-timing.png differ diff --git a/can-timing.xls b/can-timing.xls new file mode 100644 index 0000000..57beabc Binary files /dev/null and b/can-timing.xls differ diff --git a/examples/CANtest/CANtest.ino b/examples/CANtest.ino similarity index 51% rename from examples/CANtest/CANtest.ino rename to examples/CANtest.ino index 4cb566f..656d4c7 100644 --- a/examples/CANtest/CANtest.ino +++ b/examples/CANtest.ino @@ -8,18 +8,17 @@ // Serial is used to print the ongoing status. // -#include -#include +#include "Metro.h" +#include "FlexCAN.h" Metro sysTimer = Metro(1);// milliseconds int led = 13; -FlexCAN CANbus(500000); -static CAN_message_t msg,rxmsg; +FlexCAN CANbus; +static CAN_message_t rxmsg; static uint8_t hex[17] = "0123456789abcdef"; -int txCount,rxCount; -unsigned int txTimer,rxTimer; +unsigned int rxTimer; // ------------------------------------------------------------- @@ -44,9 +43,10 @@ void setup(void) digitalWrite(led, 1); delay(1000); - Serial.println(F("Hello Teensy 3.1 CAN Test.")); + Serial.println(F("Hello Teensy 3.2 CAN Test.")); sysTimer.reset(); + rxTimer = 3; //milliseconds } @@ -55,49 +55,18 @@ void loop(void) { // service software timers based on Metro tick if ( sysTimer.check() ) { - if ( txTimer ) { - --txTimer; - } - if ( rxTimer ) { - --rxTimer; - } + --rxTimer; } - // if not time-delayed, read CAN messages and print 1st byte + // if not time-delayed, read CAN messages and print if ( !rxTimer ) { while ( CANbus.read(rxmsg) ) { - //hexDump( sizeof(rxmsg), (uint8_t *)&rxmsg ); - Serial.write(rxmsg.buf[0]); - rxCount++; - } - } - - // insert a time delay between transmissions - if ( !txTimer ) { - // if frames were received, print the count - if ( rxCount ) { - Serial.write('='); - Serial.print(rxCount); - rxCount = 0; - } - txTimer = 100;//milliseconds - msg.len = 8; - msg.id = 0x222; - for( int idx=0; idx<8; ++idx ) { - msg.buf[idx] = '0'+idx; - } - // send 6 at a time to force tx buffering - txCount = 6; - digitalWrite(led, 1); - Serial.println("."); - while ( txCount-- ) { - CANbus.write(msg); - msg.buf[0]++; + hexDump( sizeof(rxmsg), (uint8_t *)&rxmsg ); + //Serial.write(rxmsg.buf[0]); + rxTimer = 3; //milliseconds } - digitalWrite(led, 0); - // time delay to force some rx data queue use - rxTimer = 3;//milliseconds } + } diff --git a/examples/autoconnect.ino b/examples/autoconnect.ino new file mode 100644 index 0000000..2969cfb --- /dev/null +++ b/examples/autoconnect.ino @@ -0,0 +1,84 @@ +// ------------------------------------------------------------- +// FlexCan auto connect +// by xboxpro1 +// + +#include "FlexCAN.h" + +String dataIN = ""; +String crIN; +short CR = 10; +int led = 13; +int cbindex = 255; +boolean rx = false; +FlexCAN can; +static CAN_message_t rxmsg; + + +// ------------------------------------------------------------- + +void setup(void) +{ + pinMode(led, OUTPUT); + Serial.begin(115200); + Serial.println("Teensy 3.2 CAN Auto Connect Test."); + Serial.println("Press -> c <- for Auto Connect Test"); + Serial.println("Press -> r <- for Can RX Test"); + } + + +// ------------------------------------------------------------- +void loop(void) +{ + if (Serial.available() > 0) { + dataIN = Serial.readStringUntil(CR); + crIN = Serial.readString(); + if(dataIN == 'c'){ + cbindex = can.connect(); // connect can bus default (0, 0) return speed index + Serial.print("Speed Index -> "); + Serial.println(cbindex); + if(cbindex != 255){ + digitalWrite(led, 1); + } + else { + digitalWrite(led, 0); + } + } + + else if(dataIN == 'r'){ + rx = true; + } + else{ + Serial.println("Press -> c <- for Auto Connect Test"); + Serial.println("Press -> r <- for Can RX Test"); + digitalWrite(led, 0); + rx = false; + } + } + if (rx == true && cbindex != 255){ + if(1 == can.available()){ + can.read(rxmsg); + Serial.print("PID: "); + Serial.print(rxmsg.id, HEX); + Serial.print(" Data:"); + for (int x = 0; x < rxmsg.len; x ++){ + Serial.print(" "); + if(rxmsg.req == 0){ + if(rxmsg.buf[x] < 10){ + Serial.print("0"); + } + Serial.print(rxmsg.buf[x], HEX); + } + else { + Serial.print("00"); + } + } + Serial.print(" Request: "); + Serial.print(rxmsg.req); + Serial.print(" Timestamp: "); + Serial.println(rxmsg.timestamp); + } + } + +} + diff --git a/keywords.txt b/keywords.txt index 3ef5764..88ebd6a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,7 +1,13 @@ FlexCAN KEYWORD1 begin KEYWORD2 +connect KEYWORD2 +setMask KEYWORD2 setFilter KEYWORD2 +clearFilter KEYWORD2 +clearMask KEYWORD2 +reset KEYWORD2 +synchron KEYWORD2 end KEYWORD2 read KEYWORD2 write KEYWORD2 diff --git a/kinetis_flexcan.h b/kinetis_flexcan.h index 0040048..49b724f 100644 --- a/kinetis_flexcan.h +++ b/kinetis_flexcan.h @@ -8,6 +8,27 @@ #include +/* Bus speed definition */ +#define CAN_5KBPS 1 +#define CAN_10KBPS 2 +#define CAN_20KBPS 3 +#define CAN_25KBPS 4 +#define CAN_31K25BPS 5 +#define CAN_33KBPS 6 +#define CAN_40KBPS 7 +#define CAN_50KBPS 8 +#define CAN_80KBPS 9 +#define CAN_83K3BPS 10 +#define CAN_95KBPS 11 +#define CAN_100KBPS 12 +#define CAN_125KBPS 13 +#define CAN_200KBPS 14 +#define CAN_250KBPS 15 +#define CAN_500KBPS 16 +#define CAN_666KBPS 17 +#define CAN_1000KBPS 18 + + /* Common bit definition */ #define BIT0 (1L) #define BIT1 (BIT0<<1) @@ -397,6 +418,7 @@ typedef volatile uint32_t vuint32_t; #define FLEXCAN_ESR_BIT1_ERR (0x00008000) #define FLEXCAN_ESR_RWRN_INT (0x00010000) #define FLEXCAN_ESR_TWRN_INT (0x00020000) +#define FLEXCAN_ESR_SYNCH (0x00040000) #define FLEXCAN_ESR_get_fault_code(esr) (((esr) & FLEXCAN_ESR_FLT_CONF_MASK)>>4) #define CAN_ERROR_ACTIVE 0 #define CAN_ERROR_PASSIVE 1