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

Revision:
0:fd2dbe74d7f6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jul 24 10:21:43 2017 +0000
@@ -0,0 +1,90 @@
+/*
+* WARNING! With some CAN shields (those breaking SPI out exclusively to ICSP)
+*          there must be rewiring done. This is simple and involves connecting
+*          ICSP contacts for MOSI, MISO, and SCLK to D11, D12, and D13 on FRDM.
+*
+*          SPI clock rate is 1MHz by default, set a Bus Pirate to this speed.
+*/
+
+#include "mbed.h"
+#include "seeed_can.h"
+
+//SEEED_CAN can(SEEED_CAN_CS, SEEED_CAN_IRQ, SEEED_CAN_MOSI, SEEED_CAN_MISO, SEEED_CAN_CLK, 30000);
+SEEED_CAN can;            // No parameters needed when Seeed Studios' CAN-BUS Shield is plugged into a FRDM-KL25Z mbed
+                          // or an LPC1768b and using pins p9, p10, p11, p12 and p13.
+Serial pc(USBTX, USBRX);  // USB serial port TTYACM0 (or COMn in a Windows environment - use device manager to find 'n')
+
+Ticker minute;
+Timer timestamp;
+
+bool msgRxFlag = 0;
+
+void canInterrupt()
+{
+    can.attach(NULL);     // Disable the interrupt - the application must re-anable the interrupt after it has acted upon it
+    msgRxFlag = 1;        // Set a 'Flag' to say that there is an interrupt that needs to be processed
+}
+
+void resetTimestamp()     // Resets the 'timestamp' Timer (attached to the 'minute' Ticker)
+{
+    timestamp.reset();
+}
+
+void displayMessage()     // Display a CAN message if there is one in a receive buffer
+{
+    SEEED_CANMessage canMsg;
+
+    /* Note: If incoming message bytes are higher than '30'
+             it could mean that they are encoded, ANSI, ASCII
+             or similar, for example D:3031323334353637 == 01234567 */
+    if (can.read(canMsg)) {  // Timestamp in ms, message Id and message Length
+        printf("**** T:%05d I:%03x L:%d D:", timestamp.read_ms(), canMsg.id, canMsg.len);
+        for (uint32_t i = 0; i < canMsg.len; i++) {
+            printf("%02x", canMsg.data[i]);  // Show the message's data bytes in Hex representation
+        }
+        printf(" ****\r\n");
+    }
+}
+
+int main()
+{
+    SEEED_CANMessage canMsg;
+    char VIN[18] = {NULL};                                      // VIN code is 17 characters long + 1 for string terminator character (NULL or \0)
+    char reqvin[] = {0x02,0x1A,0x90,0x00,0x00,0x00,0x00,0x00};  // CAN message to request VIN code
+    char floctl[] = {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00};  // CAN message to request all remaining frames in a multi-frame message
+
+    pc.baud(115200);  // Increase bitrate appropriately for receiving and printing CAN messages
+
+    printf("Analyzing an IoT Empire CAN Bus Test\r\n");
+    timestamp.start();
+    minute.attach(&resetTimestamp, 60.0);  // Reset the 'Timestamp' timer every minute
+    can.open(500000, SEEED_CAN::Config);   // Initialise CAN Bus hardware with a baudrate of 500 kbps (P-bus)
+    can.mask(0, 0x7FF);                    // Configure Mask 0 to check all bits of a Standard CAN message Id
+    can.mask(1, 0x7FF, CANStandard);       // Configure Mask 1 to check all bits of a Standard CAN message Id
+    can.filter(0, 0x222);                  // Configure Filter 0 - 0x7E8 is the id used by ECUs on GMLAN
+
+    // Read and Display the VIN code stored in a ECU
+    can.write(SEEED_CANMessage(0x7E0, reqvin));           // Request VIN using ReadDataByIdentifier method (GMLAN_DID)
+    while (!(can.read(canMsg) && (canMsg.id == 0x222)));  // Wait for the response
+    memcpy(VIN+0, canMsg.data+4, 4);                      // 1st 4 Bytes are part of message protocol, last 4 bytes are 1st 4 characters of VIN
+    can.write(SEEED_CANMessage(0x7E0, floctl));           // Send Trionic8 a "Flow Control Message to get the rest of the VIN
+    while (!(can.read(canMsg) && (canMsg.id == 0x222)));  // Wait for the 1st continuation message
+    memcpy(VIN+4, canMsg.data+1, 7);                      // 1st Byte is message continuation sequence number, last 7 bytes are next 7 characters of VIN
+    while (!(can.read(canMsg) && (canMsg.id == 0x222)));  // Wait for the last message
+    memcpy(VIN+11, canMsg.data+1, 6);                     // 1st Byte is message continuation sequence number, last 6 bytes are remaining characters of VIN
+    printf("VIN code: %s\r\n", VIN);
+
+    // Analysis loop, display all messages on the CAN bus regardless of addressing
+    can.monitor(1);                               // Select moniter mode to listen only (no ACKs to CAN)
+    can.mask(0, NULL);                            // Clear acceptance mask 0 (i.e. accept all meassages)
+    can.attach(&canInterrupt, SEEED_CAN::RxAny);
+    while (1) {
+        if (msgRxFlag) {
+            displayMessage();
+            if (can.interrupts(SEEED_CAN::RxAny)) {
+                msgRxFlag = 0;
+                can.attach(&canInterrupt, SEEED_CAN::RxAny);
+            }
+        }
+    }
+}