CAN nucleo examplecode website

Dependencies:   CANnucleo

main.cpp

Committer:
adv_lut
Date:
2019-09-13
Revision:
31:0b5c9a37a5a6
Parent:
29:9ae558ec888c

File content as of revision 31:0b5c9a37a5a6:

/*
 * An example showing how to use the CANnucleo library:
 *
 * Two affordable (less than $3 on ebay) STM32F103C8T6 boards (20kB SRAM, 64kB Flash), 
 * (see [https://developer.mbed.org/users/hudakz/code/STM32F103C8T6_Hello/] for more details) 
 * 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.
 *
 * For more details see the wiki page <https://developer.mbed.org/users/hudakz/code/CANnucleo_Hello/>
 *
 * NOTE: If you'd like to use an STM32F103C8T6 board uncomment line 23
 *
 * 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 23 before compiling 
 *
 * 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 "CANnucleo.h"
#include "mbed.h"

Serial          pc(PA_2, PA_3);
CAN*            can;
CANMessage      rxMsg;
CANMessage      txMsg;
DigitalOut      led(LED_PIN);
Timer           timer;
uint8_t         counter = 0;    // one byte
AnalogIn        analogIn(A0);
float           voltage;        // four bytes
volatile bool   msgAvailable = false;

/**
 * @brief   'CAN receive-complete' interrup service routine.
 * @note    Called on arrival of new CAN message.
 *          Keep it as short as possible.
 * @param   
 * @retval  
 */
void onMsgReceived() {
    msgAvailable = true;
}

/**
 * @brief   Prints CAN msg to PC's serial terminal.
 * @note}
 * @param   CANMessage to print
 * @retval  none
 */
void printMsg(CANMessage& 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() {
#if defined(TARGET_STM32F103C8T6)
    confSysClock();     //Configure the system clock (72MHz HSE clock, 48MHz USB clock)
#endif
    pc.baud(9600);                      // set the Serial speed

    can = new CAN(PA_11, PA_12);        // CAN Rx pin name, CAN Tx pin name
    can->frequency(1000000);            // set the bit rate to 1Mbps
    can->attach(&onMsgReceived);        // attach the 'CAN receive-complete' interrupt service routine (ISR)
    
#if defined(BOARD1)
    led = ON;       // turn the LED on
    timer.start();  // start the 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 the timer
            timer.reset();                      // reset the timer
            counter++;                          // increment the counter
            voltage = (analogIn * 3.3f)/4096.0f;// read the small drifting voltage from analog input
            txMsg.clear();                      // clear the Tx message storage
            txMsg.id = TX_ID;                   // set the message ID
            // We are about to transmit two data items to the CAN bus.
            //     counter: uint_8 (unsigned eight bits int) value (one byte).
            //     voltage: floating point value (four bytes).
            // So the total length of payload data is five bytes.
            // We'll use the "<<" (append) operator to add data to the CAN message.
            // The usage is same as of the similar C++ io-stream operators.
            // NOTE: The data length of CAN message is automatically updated when using "<<" operators.  
            txMsg << counter << voltage;        // append data (total data length must be <= 8 bytes!)
            if(can->write(txMsg)) {             // transmit the CAN message
                led = OFF;                      // turn the 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(msgAvailable) {
            msgAvailable = false;               // reset the flag for next use in the interrupt service routine
            can->read(rxMsg);                   // read the message into the Rx message storage
            led = ON;                           // turn the LED on
            pc.printf("-------------------------------------\r\n");
            pc.printf("CAN message received\r\n");
            printMsg(rxMsg);
            // Filtering performed by software:           
            if(rxMsg.id == RX_ID) {             // about filtering performed by hardware see the comments in CANnucleo.cpp 
                rxMsg >> counter >> voltage;    // extract data from the received CAN message (in same sequence as they were added)
                pc.printf("  counter = %d\r\n", counter);
                pc.printf("  voltage = %e V\r\n", voltage);
                timer.start();                  // insert transmission lag
            }
        }
    }
}