Introductory CAN bus messaging application using a microcontroller built in UART connection and requiring a second CAN bus peer (to transmit or receive.)

Dependencies:   SEEED_CAN mbed

Committer:
michaesc
Date:
Mon Jul 24 10:21:43 2017 +0000
Revision:
0:fd2dbe74d7f6
Initialized introductory CAN bus receiver application pending import.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
michaesc 0:fd2dbe74d7f6 1 /*
michaesc 0:fd2dbe74d7f6 2 * WARNING! With some CAN shields (those breaking SPI out exclusively to ICSP)
michaesc 0:fd2dbe74d7f6 3 * there must be rewiring done. This is simple and involves connecting
michaesc 0:fd2dbe74d7f6 4 * ICSP contacts for MOSI, MISO, and SCLK to D11, D12, and D13 on FRDM.
michaesc 0:fd2dbe74d7f6 5 *
michaesc 0:fd2dbe74d7f6 6 * SPI clock rate is 1MHz by default, set a Bus Pirate to this speed.
michaesc 0:fd2dbe74d7f6 7 */
michaesc 0:fd2dbe74d7f6 8
michaesc 0:fd2dbe74d7f6 9 #include "mbed.h"
michaesc 0:fd2dbe74d7f6 10 #include "seeed_can.h"
michaesc 0:fd2dbe74d7f6 11
michaesc 0:fd2dbe74d7f6 12 //SEEED_CAN can(SEEED_CAN_CS, SEEED_CAN_IRQ, SEEED_CAN_MOSI, SEEED_CAN_MISO, SEEED_CAN_CLK, 30000);
michaesc 0:fd2dbe74d7f6 13 SEEED_CAN can; // No parameters needed when Seeed Studios' CAN-BUS Shield is plugged into a FRDM-KL25Z mbed
michaesc 0:fd2dbe74d7f6 14 // or an LPC1768b and using pins p9, p10, p11, p12 and p13.
michaesc 0:fd2dbe74d7f6 15 Serial pc(USBTX, USBRX); // USB serial port TTYACM0 (or COMn in a Windows environment - use device manager to find 'n')
michaesc 0:fd2dbe74d7f6 16
michaesc 0:fd2dbe74d7f6 17 Ticker minute;
michaesc 0:fd2dbe74d7f6 18 Timer timestamp;
michaesc 0:fd2dbe74d7f6 19
michaesc 0:fd2dbe74d7f6 20 bool msgRxFlag = 0;
michaesc 0:fd2dbe74d7f6 21
michaesc 0:fd2dbe74d7f6 22 void canInterrupt()
michaesc 0:fd2dbe74d7f6 23 {
michaesc 0:fd2dbe74d7f6 24 can.attach(NULL); // Disable the interrupt - the application must re-anable the interrupt after it has acted upon it
michaesc 0:fd2dbe74d7f6 25 msgRxFlag = 1; // Set a 'Flag' to say that there is an interrupt that needs to be processed
michaesc 0:fd2dbe74d7f6 26 }
michaesc 0:fd2dbe74d7f6 27
michaesc 0:fd2dbe74d7f6 28 void resetTimestamp() // Resets the 'timestamp' Timer (attached to the 'minute' Ticker)
michaesc 0:fd2dbe74d7f6 29 {
michaesc 0:fd2dbe74d7f6 30 timestamp.reset();
michaesc 0:fd2dbe74d7f6 31 }
michaesc 0:fd2dbe74d7f6 32
michaesc 0:fd2dbe74d7f6 33 void displayMessage() // Display a CAN message if there is one in a receive buffer
michaesc 0:fd2dbe74d7f6 34 {
michaesc 0:fd2dbe74d7f6 35 SEEED_CANMessage canMsg;
michaesc 0:fd2dbe74d7f6 36
michaesc 0:fd2dbe74d7f6 37 /* Note: If incoming message bytes are higher than '30'
michaesc 0:fd2dbe74d7f6 38 it could mean that they are encoded, ANSI, ASCII
michaesc 0:fd2dbe74d7f6 39 or similar, for example D:3031323334353637 == 01234567 */
michaesc 0:fd2dbe74d7f6 40 if (can.read(canMsg)) { // Timestamp in ms, message Id and message Length
michaesc 0:fd2dbe74d7f6 41 printf("**** T:%05d I:%03x L:%d D:", timestamp.read_ms(), canMsg.id, canMsg.len);
michaesc 0:fd2dbe74d7f6 42 for (uint32_t i = 0; i < canMsg.len; i++) {
michaesc 0:fd2dbe74d7f6 43 printf("%02x", canMsg.data[i]); // Show the message's data bytes in Hex representation
michaesc 0:fd2dbe74d7f6 44 }
michaesc 0:fd2dbe74d7f6 45 printf(" ****\r\n");
michaesc 0:fd2dbe74d7f6 46 }
michaesc 0:fd2dbe74d7f6 47 }
michaesc 0:fd2dbe74d7f6 48
michaesc 0:fd2dbe74d7f6 49 int main()
michaesc 0:fd2dbe74d7f6 50 {
michaesc 0:fd2dbe74d7f6 51 SEEED_CANMessage canMsg;
michaesc 0:fd2dbe74d7f6 52 char VIN[18] = {NULL}; // VIN code is 17 characters long + 1 for string terminator character (NULL or \0)
michaesc 0:fd2dbe74d7f6 53 char reqvin[] = {0x02,0x1A,0x90,0x00,0x00,0x00,0x00,0x00}; // CAN message to request VIN code
michaesc 0:fd2dbe74d7f6 54 char floctl[] = {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // CAN message to request all remaining frames in a multi-frame message
michaesc 0:fd2dbe74d7f6 55
michaesc 0:fd2dbe74d7f6 56 pc.baud(115200); // Increase bitrate appropriately for receiving and printing CAN messages
michaesc 0:fd2dbe74d7f6 57
michaesc 0:fd2dbe74d7f6 58 printf("Analyzing an IoT Empire CAN Bus Test\r\n");
michaesc 0:fd2dbe74d7f6 59 timestamp.start();
michaesc 0:fd2dbe74d7f6 60 minute.attach(&resetTimestamp, 60.0); // Reset the 'Timestamp' timer every minute
michaesc 0:fd2dbe74d7f6 61 can.open(500000, SEEED_CAN::Config); // Initialise CAN Bus hardware with a baudrate of 500 kbps (P-bus)
michaesc 0:fd2dbe74d7f6 62 can.mask(0, 0x7FF); // Configure Mask 0 to check all bits of a Standard CAN message Id
michaesc 0:fd2dbe74d7f6 63 can.mask(1, 0x7FF, CANStandard); // Configure Mask 1 to check all bits of a Standard CAN message Id
michaesc 0:fd2dbe74d7f6 64 can.filter(0, 0x222); // Configure Filter 0 - 0x7E8 is the id used by ECUs on GMLAN
michaesc 0:fd2dbe74d7f6 65
michaesc 0:fd2dbe74d7f6 66 // Read and Display the VIN code stored in a ECU
michaesc 0:fd2dbe74d7f6 67 can.write(SEEED_CANMessage(0x7E0, reqvin)); // Request VIN using ReadDataByIdentifier method (GMLAN_DID)
michaesc 0:fd2dbe74d7f6 68 while (!(can.read(canMsg) && (canMsg.id == 0x222))); // Wait for the response
michaesc 0:fd2dbe74d7f6 69 memcpy(VIN+0, canMsg.data+4, 4); // 1st 4 Bytes are part of message protocol, last 4 bytes are 1st 4 characters of VIN
michaesc 0:fd2dbe74d7f6 70 can.write(SEEED_CANMessage(0x7E0, floctl)); // Send Trionic8 a "Flow Control Message to get the rest of the VIN
michaesc 0:fd2dbe74d7f6 71 while (!(can.read(canMsg) && (canMsg.id == 0x222))); // Wait for the 1st continuation message
michaesc 0:fd2dbe74d7f6 72 memcpy(VIN+4, canMsg.data+1, 7); // 1st Byte is message continuation sequence number, last 7 bytes are next 7 characters of VIN
michaesc 0:fd2dbe74d7f6 73 while (!(can.read(canMsg) && (canMsg.id == 0x222))); // Wait for the last message
michaesc 0:fd2dbe74d7f6 74 memcpy(VIN+11, canMsg.data+1, 6); // 1st Byte is message continuation sequence number, last 6 bytes are remaining characters of VIN
michaesc 0:fd2dbe74d7f6 75 printf("VIN code: %s\r\n", VIN);
michaesc 0:fd2dbe74d7f6 76
michaesc 0:fd2dbe74d7f6 77 // Analysis loop, display all messages on the CAN bus regardless of addressing
michaesc 0:fd2dbe74d7f6 78 can.monitor(1); // Select moniter mode to listen only (no ACKs to CAN)
michaesc 0:fd2dbe74d7f6 79 can.mask(0, NULL); // Clear acceptance mask 0 (i.e. accept all meassages)
michaesc 0:fd2dbe74d7f6 80 can.attach(&canInterrupt, SEEED_CAN::RxAny);
michaesc 0:fd2dbe74d7f6 81 while (1) {
michaesc 0:fd2dbe74d7f6 82 if (msgRxFlag) {
michaesc 0:fd2dbe74d7f6 83 displayMessage();
michaesc 0:fd2dbe74d7f6 84 if (can.interrupts(SEEED_CAN::RxAny)) {
michaesc 0:fd2dbe74d7f6 85 msgRxFlag = 0;
michaesc 0:fd2dbe74d7f6 86 can.attach(&canInterrupt, SEEED_CAN::RxAny);
michaesc 0:fd2dbe74d7f6 87 }
michaesc 0:fd2dbe74d7f6 88 }
michaesc 0:fd2dbe74d7f6 89 }
michaesc 0:fd2dbe74d7f6 90 }