* Object Oriented CAN example for Teensy 3.6 with Dual CAN buses
* By Collin Kidder. Based upon the work of Pawelsky and Teachop
*
* Both buses are set to 1 Mbits to show things with a full speed bus.
* The reception of frames in this example is done via callbacks
* to an object rather than polling. Frames are delivered as they come in.
*
* This example sets mailbox Masks and Filters to recieve specific individual
* message ID's and ranges of message ID's for both 11-bit and 29-bit message ID's
*
* The second CAN port (CAN1) sends many messages:- some we want, and some we do not want.
* Messages that we want to recieve are loaded with data bytes that just re-states the ID,
* whereas the messages we do not want are loaded with a 9 9 9 9 9 9 9 9 message to help spot
* these unwanted messages if they somehow get through the masks and filters and are accidentally
* received.
*
* The following message ID's are sent on the Bus, unwanted messages are highlighted thus: ***
* 0xF003D0
* 0xF003C6
* 0xF003D9
* 0xF003B6 ***
* 0xF003E9 ***
* 0x2 ***
* 0x3 ***
* 0x4 ***
* 0x5
* 0x6 ***
* 0x7 ***
* 0x8 ***
* 0x13
* 0x14
* 0x15
* 0x16
* 0x113
* 0x114
* 0x115
* 0x116
*
*/
#include <FlexCAN.h>
#ifndef __MK66FX1M0__
#error "Teensy 3.6 with dual CAN bus is required to run this example"
#endif
static CAN_message_t msg0,msg1;
elapsedMillis RXtimer;
elapsedMillis LEDtimer;
uint32_t RXCount = 0;
boolean displayCAN = true;
const uint8_t redLEDpin = 13;
boolean redLEDstate;
class CANClass : public CANListener
{
public:
void printFrame(CAN_message_t &frame, int mailbox);
void gotFrame(CAN_message_t &frame, int mailbox); //overrides the parent version so we can actually do something
};
void CANClass::printFrame(CAN_message_t &frame, int mailbox)
{
if(displayCAN){
Serial.print(mailbox);
Serial.print(" ID: ");
Serial.print(frame.id, HEX);
Serial.print(" Data: ");
for (int c = 0; c < frame.len; c++)
{
Serial.print(frame.buf[c], HEX);
Serial.write(' ');
}
Serial.println();
}
RXCount++;
}
void CANClass::gotFrame(CAN_message_t &frame, int mailbox)
{
printFrame(frame, mailbox);
}
CANClass CANClass0;
CANClass CANClass1;
// -------------------------------------------------------------
void setup(void)
{
delay(1000);
Serial.println(F("Hello Teensy 3.6 dual CAN Test With Objects."));
pinMode(redLEDpin,OUTPUT);
CAN_filter_t defaultMask_1;
defaultMask_1.rtr=0;
defaultMask_1.ext=0;
// defaultMask_1.id=0x7FF;
defaultMask_1.id=0;
delay(1000);
Can0.begin(1000000,defaultMask_1);
Can1.begin(1000000,defaultMask_1);
Can0.attachObj(&CANClass0);
// Can1.attachObj(&CANClass1);
/////////////////////////////////////////
////////MASK AND FILTER SETTING//////////
// First we set mailboxes 0 through to 4 to use the standard ID blocking Mask & filter,
// this checks all ID bits match the filter for the very last Standard ID.
CAN_filter_t allBlockStandardFilter;
allBlockStandardFilter.id=0x7FF;
allBlockStandardFilter.ext=0;
allBlockStandardFilter.rtr=0;
for (uint8_t filterNum = 0; filterNum < 5;filterNum++){
Can0.setMask(0x7FF<<18,filterNum); // bit shifting the mask 18 bit positions from standard 11bit to extended 29bit position
Can0.setFilter(allBlockStandardFilter,filterNum);
}
CAN_filter_t mailbox_Filter;
// MAILBOX 0
Can0.setMask(0x7F0<<18,0); // Bit-shifting 18 bits left, mask is checking for a match of all but the last 4 bits.
mailbox_Filter.id=0x010; // Filter is looking for zeros in the first 3 bits, ones in the next 4 bits, and the final
mailbox_Filter.ext=0; // 4 bits, while declared zeros by this filter, are just ignored by the mask.
mailbox_Filter.rtr=0; // Mailbox will recieve ID's 0x010 though 0x01F, or as decimals 16 through 31
Can0.setFilter(mailbox_Filter,0);
// MAILBOX 1
Can0.setMask(0x7F0<<18,1); // Duplicate of previous mailbox, this helps capture messages from multiple ID's as a
mailbox_Filter.id=0x010; // single mailbox can appear to 'miss' messages if we do not collect them quickly in our code
mailbox_Filter.ext=0; // before they get over-written with the next accepted message into that mailbox
mailbox_Filter.rtr=0;
Can0.setFilter(mailbox_Filter,1);
// MAILBOX 2
Can0.setMask(0x700<<18,2); // bit shifting 18 bits left, mask is checking for a match of the first 3 bits.
mailbox_Filter.id=0x100; // Filter is looking for 001 as the first 3 bits, the rest of the ID is masked so remaining
mailbox_Filter.ext=0; // 8 bits of the ID can be anything.
mailbox_Filter.rtr=0; // Mailbox will recieve ID's 0x100 though 0x1FF, or as decimals 256 through 511
Can0.setFilter(mailbox_Filter,2);
// MAILBOX 3
Can0.setMask(0x700<<18,3); // Duplicate of previous mailbox.
mailbox_Filter.id=0x100;
mailbox_Filter.ext=0;
mailbox_Filter.rtr=0;
Can0.setFilter(mailbox_Filter,3);
// MAILBOX 4
Can0.setMask(0x7FF<<18,4); // bit shifting 18 bits left, mask is checking for a match of all 11 bits.
mailbox_Filter.id=0x005; // Filter is looking for 0x05, so with a 'full match' requirement defined by the mask,
mailbox_Filter.ext=0; // this will be the only ID received in this mailbox.
mailbox_Filter.rtr=0;
Can0.setFilter(mailbox_Filter,4);
// now we initially block the rest of the mailboxes to check all ID bits with a full mask
// and a filter for the very last extended ID.
CAN_filter_t allBlockExtendedFilter;
allBlockExtendedFilter.id=0x1FFFFFFF;
allBlockExtendedFilter.ext=1; // Notice: Extended bit is toggled to 1 (was 0 for Standard)
allBlockExtendedFilter.rtr=0;
for (uint8_t filterNum = 5; filterNum < 16;filterNum++){
Can0.setMask(0x1FFFFFFF,filterNum); // Notice: no bit-shifting for 29-bit Extended ID's!
Can0.setFilter(allBlockExtendedFilter,filterNum);
}
// Now we open up mailboxes 5-9 for the Extended 29bit ID messages we want to receive
// MAILBOX 5
Can0.setMask(0x1FFFFFE0,5); // No bit-shifting, Mask is hiding the last 5 bits, (or checking the first 24 bits)
mailbox_Filter.id=0xF003C0; // Filter is looking for 1111000000000011110 as the first 24 bits of the ID.
mailbox_Filter.ext=1; // Message ID's 0xF003C0 through 0xF003DF will be acccepted. (DEC:15729600 to 15729631)
mailbox_Filter.rtr=0;
Can0.setFilter(mailbox_Filter,5);
// MAILBOX 6
Can0.setMask(0x1FFFFFE0,6); // Duplicate of previous mailbox to ensure no 'lost' messages
mailbox_Filter.id=0xF003C0;
mailbox_Filter.ext=1;
mailbox_Filter.rtr=0;
Can0.setFilter(mailbox_Filter,6);
// MAILBOX 7
Can0.setMask(0x1FFFFFFF,7); // Mask is 'exposing' all bits to the filter, so an exact match is required in order
mailbox_Filter.id=0xF014DF; // for acceptance. Message ID 0xF014DF (Dec: 15733983) will be the only message received.
mailbox_Filter.ext=1;
mailbox_Filter.rtr=0;
Can0.setFilter(mailbox_Filter,7);
// MAILBOX 8 // This is example of an incorrectly set filter
Can0.setMask(0x1FFFFF00,8); // Mask is exposing all but the last 8 bits to the filter
mailbox_Filter.id=0x10; // Filter is defining: 1000 0000 as last 8 bits, but the mask is ignoring these 8-bits!
mailbox_Filter.ext=1; // The first 21 bits of the ID must still be zeros, but as .ext=1 is defining this filter
mailbox_Filter.rtr=0; // as EXTENDED ID, filter must be 0x800 (Dec=2048) or greater to be valid.
Can0.setFilter(mailbox_Filter,8);
// MAILBOX 9
Can0.setMask(0x1FFFFF00,9); // Mask is exposing all but the last 8 bits to the filter
mailbox_Filter.id=0xA00; // Filter is looking for 1010 in bits 9 through 12, zero's in the higher bits, and anything
mailbox_Filter.ext=1; // in the lower bits.
mailbox_Filter.rtr=0; // This mailbox will accept ID's 0xA00 through 0xAFF (Dec: 2560 through 2815)
Can0.setFilter(mailbox_Filter,9);
///////// END OF FILTER AND MASK SETUP //////////
/////////////////////////////////////////////////
// now we attach the mailbox handler routine for all 16 mailboxes
for (uint8_t filterNum = 0; filterNum < 16;filterNum++){
CANClass0.attachMBHandler(filterNum);
CANClass1.attachMBHandler(filterNum);
}
//CANClass0.attachGeneralHandler();
//CANClass1.attachGeneralHandler();
}
// -------------------------------------------------------------
void loop(void)
{
if (RXtimer > 10000){
Serial.println("Total Received Messages in 10 Sec:");
Serial.println(RXCount);
RXtimer = 0;
RXCount=0;
displayCAN = !displayCAN;
}
if (LEDtimer >250){
LEDtimer = 0;
redLEDstate = !redLEDstate;
digitalWrite(redLEDpin, redLEDstate);
}
/**************** Code for sending messages out from CAN1 **************/
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 15;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 3;
msg1.buf[6] = 13;
msg1.buf[7] = 0;
msg1.ext = 1;
msg1.id = 0xF003D0;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 15;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 3;
msg1.buf[6] = 12;
msg1.buf[7] = 6;
msg1.ext = 1;
msg1.id = 0xF003C6;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 15;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 3;
msg1.buf[6] = 13;
msg1.buf[7] = 9;
msg1.ext = 1;
msg1.id = 0xF003D9;
msg1.len = 8;
Can1.write(msg1);
delay(2);
///////////////////////////////////////////
////// START OF MESSAGES WE DONT WANT /////
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 1;
msg1.id = 0xF003B6;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 1;
msg1.id = 0xF003E9;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 0;
msg1.id = 0x2;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 0;
msg1.id = 0x3;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 0;
msg1.id = 0x4;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 0;
msg1.id = 0x6;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 0;
msg1.id = 0x7;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 9;
msg1.buf[1] = 9;
msg1.buf[2] = 9;
msg1.buf[3] = 9;
msg1.buf[4] = 9;
msg1.buf[5] = 9;
msg1.buf[6] = 9;
msg1.buf[7] = 9;
msg1.ext = 0;
msg1.id = 0x8;
msg1.len = 8;
Can1.write(msg1);
delay(2);
////// END OF MESSAGES WE DONT WANT /////
////////////////////////////////////////
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 0;
msg1.buf[6] = 0;
msg1.buf[7] = 5;
msg1.ext = 0;
msg1.id = 0x5;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 0;
msg1.buf[6] = 1;
msg1.buf[7] = 3;
msg1.ext = 0;
msg1.id = 0x13;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 0;
msg1.buf[6] = 1;
msg1.buf[7] = 4;
msg1.ext = 0;
msg1.id = 0x14;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 0;
msg1.buf[6] = 1;
msg1.buf[7] = 5;
msg1.ext = 0;
msg1.id = 0x15;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 0;
msg1.buf[6] = 1;
msg1.buf[7] = 6;
msg1.ext = 0;
msg1.id = 0x16;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 1;
msg1.buf[6] = 1;
msg1.buf[7] = 3;
msg1.ext = 0;
msg1.id = 0x113;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 1;
msg1.buf[6] = 1;
msg1.buf[7] = 4;
msg1.ext = 0;
msg1.id = 0x114;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 1;
msg1.buf[6] = 1;
msg1.buf[7] = 5;
msg1.ext = 0;
msg1.id = 0x115;
msg1.len = 8;
Can1.write(msg1);
delay(2);
msg1.buf[0] = 0;
msg1.buf[1] = 0;
msg1.buf[2] = 0;
msg1.buf[3] = 0;
msg1.buf[4] = 0;
msg1.buf[5] = 1;
msg1.buf[6] = 1;
msg1.buf[7] = 6;
msg1.ext = 0;
msg1.id = 0x116;
msg1.len = 8;
Can1.write(msg1);
delay(2);
}