Using CAN bus with (not just NUCLEO) mbed boards

Dependencies:   mbed CANMsg

main.cpp

Committer:
hudakz
Date:
2017-03-17
Revision:
0:1b9561cd1c36
Child:
1:6f8ffb2c2dd7

File content as of revision 0:1b9561cd1c36:

/*
 * A demo showing how to use CAN bus and the CANMsg library's << (append) and the >> (extract) operators
 *
 * Two affordable (less than $3 on ebay) STM32F103C8T6 boards (20kB SRAM, 64kB Flash),
 * are connected to the same CAN bus via transceivers (MCP2551 or TJA1040, or etc.).
 * CAN transceivers are not part of NUCLEO boards, therefore must be added by you.
 * Remember also that CAN bus (even a short one) must be terminated with 120 Ohm resitors at both ends.
 * In this demo, the mbed board is transmitting two data items to the CAN bus.
 *   counter: uint_8 value (one byte).
 *   voltage: floating point value (four bytes).
 * So the total length of payload data is five bytes.
 * The "<<" (append) operator is used to add data to the CAN message.
 * If a CAN message is received its ID is checked. If there is match with the awaited ID
 * then data is extracted from the CAN message using the ">>" (extract) operator.
 *
 * The usage of "<<" and ">>" operators is similar to the C++ io-stream ones.
 * Data length of CAN message is automatically updated when using "<<" or ">>" operators.  
 *
 * For schematic see the wiki page <https://developer.mbed.org/users/hudakz/code/CAN_Hello/>
 *
 * NOTE: If you'd like to use an STM32F103C8T6 board uncomment line 28
 *
 * The same code is used for both NUCLEO boards, but:
 *      For board #1 compile the example without any change.
 *      For board #2 comment out line 27 before compilation
 *
 * Once the binaries have been downloaded to the boards reset board #1.
 *
 */
#define BOARD1                  1   // comment out this line when compiling for board #2
//#define TARGET_STM32F103C8T6    1   // uncomment this line when using STM32F103C8T6 boards!

#if defined(TARGET_STM32F103C8T6)
#include "stm32f103c8t6.h"
#define LED_PIN PC_13
const int           OFF = 1;
const int           ON = 0;
#else
#define LED_PIN LED1
const int           OFF = 0;
const int           ON = 1;
#endif
#if defined(BOARD1)
const unsigned int  RX_ID = 0x100;
const unsigned int  TX_ID = 0x101;
#else
const unsigned int  RX_ID = 0x101;
const unsigned int  TX_ID = 0x100;
#endif

#include "mbed.h"
#include "CANMsg.h"

Serial              pc(USBTX, USBRX);
CAN                 can(PA_11, PA_12);    // CAN Rx pin name, CAN Tx pin name
CANMsg              rxMsg;
CANMsg              txMsg;
DigitalOut          led(LED_PIN);
Timer               timer;
uint8_t             counter = 0;
AnalogIn            analogIn(A0);
float               voltage;

/**
 * @brief   Prints CAN msg to PC's serial terminal
 * @note}
 * @param   CANMess to print
 * @retval  none
 */
void printMsg(CANMsg& msg) {
    pc.printf("  ID      = 0x%.3x\r\n", msg.id);
    pc.printf("  Type    = %d\r\n", msg.type);
    pc.printf("  Format  = %d\r\n", msg.format);
    pc.printf("  Length  = %d\r\n", msg.len);
    pc.printf("  Data    =");
    for(int i = 0; i < msg.len; i++)
        pc.printf(" 0x%.2X", msg.data[i]);
    pc.printf("\r\n");
}

/**
 * @brief   Main
 * @note
 * @param
 * @retval
 */
int main(void)
{
#if defined(TARGET_STM32F103C8T6)
    confSysClock(); //Configure system clock (72MHz HSE clock, 48MHz USB clock)
#endif

    pc.baud(9600);  // set Serial speed
    can.frequency(1000000);        // set bit rate to 1Mbps
    
#if defined(BOARD1)
    led = ON;       // turn LED on
    timer.start();  // start timer
    pc.printf("CANnucleo_Hello board #1\r\n");
#else
    led = OFF;      // turn LED off
    pc.printf("CANnucleo_Hello board #2\r\n");
#endif

    while(1) {
        if(timer.read_ms() >= 1000) {

            // check for timeout
            timer.stop();   // stop timer
            timer.reset();  // reset timer
            counter++;      // increment counter
            voltage = (analogIn * 3.3f) / 4096.0f;  // read the small drifting voltage from analog input
            txMsg.clear();      // clear Tx message storage
            txMsg.id = TX_ID;   // set ID
            txMsg << counter << voltage;    // append data (total data length must be <= 8 bytes!)
            if(can.write(txMsg)) {

                // transmit message
                led = OFF;          // turn LED off
                pc.printf("-------------------------------------\r\n");
                pc.printf("CAN message sent\r\n");
                printMsg(txMsg);
                pc.printf("  counter = %d\r\n", counter);
                pc.printf("  voltage = %e V\r\n", voltage);
            }
            else
                pc.printf("Transmission error\r\n");
        }

        if(can.read(rxMsg)) {
            led = ON;   // turn LED on
            pc.printf("-------------------------------------\r\n");
            pc.printf("CAN message received\r\n");
            printMsg(rxMsg);

            // Filtering performed by software:
            if(rxMsg.id == RX_ID) {
                rxMsg >> counter >> voltage;    // extract data from the received CAN message
                pc.printf("  counter = %d\r\n", counter);
                pc.printf("  voltage = %e V\r\n", voltage);
                timer.start();  // transmission lag
            }
        }
    }
}