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

main.cpp

Committer:
michaesc
Date:
2017-07-24
Revision:
0:fd2dbe74d7f6

File content as of revision 0:fd2dbe74d7f6:

/*
* 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);
            }
        }
    }
}