Using CAN bus with NUCLEO boards (Demo for the CANnucleo library).

Dependencies:   CANnucleo mbed-dev

Dependents:   BMS_2 Can_sniffer_BMS_GER Can_sniffer_bms ECU_1

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * An example showing how to use the CANnucleo library:
00003  *
00004  * Two affordable (less than $3 on ebay) STM32F103C8T6 boards (20kB SRAM, 64kB Flash), 
00005  * (see [https://developer.mbed.org/users/hudakz/code/STM32F103C8T6_Hello/] for more details) 
00006  * are connected to the same CAN bus via transceivers (MCP2551 or TJA1040, or etc.). 
00007  * CAN transceivers are not part of NUCLEO boards, therefore must be added by you. 
00008  * Remember also that CAN bus (even a short one) must be terminated with 120 Ohm resitors at both ends.
00009  *
00010  * For more details see the wiki page <https://developer.mbed.org/users/hudakz/code/CANnucleo_Hello/>
00011  *
00012  * NOTE: If you'd like to use an STM32F103C8T6 board uncomment line 23
00013  *
00014  * The same code is used for both NUCLEO boards, but:
00015  *      For board #1 compile the example without any change.
00016  *      For board #2 comment out line 23 before compiling 
00017  *
00018  * Once the binaries have been downloaded to the boards reset board #1.
00019  *
00020  */ 
00021 
00022 #define BOARD1                1     // comment out this line when compiling for board #2
00023 //#define TARGET_STM32F103C8T6  1     // uncomment this line when using STM32F103C8T6 boards!                                    
00024 
00025 #if defined(TARGET_STM32F103C8T6)
00026     #include "stm32f103c8t6.h"
00027     #define LED_PIN PC_13
00028     const int OFF = 1;
00029     const int ON  = 0;
00030 #else
00031     #define LED_PIN LED1
00032     const int OFF = 0;
00033     const int ON  = 1;
00034 #endif
00035 
00036 #if defined(BOARD1)
00037     const unsigned int RX_ID = 0x100;
00038     const unsigned int TX_ID = 0x101;
00039 #else
00040     const unsigned int RX_ID = 0x101;
00041     const unsigned int TX_ID = 0x100;
00042 #endif
00043 
00044 #include "CANnucleo.h"
00045 #include "mbed.h"
00046 
00047 Serial          pc(PA_2, PA_3);
00048 CAN*            can;
00049 CANMessage      rxMsg;
00050 CANMessage      txMsg;
00051 DigitalOut      led(LED_PIN);
00052 Timer           timer;
00053 uint8_t         counter = 0;    // one byte
00054 AnalogIn        analogIn(A0);
00055 float           voltage;        // four bytes
00056 volatile bool   msgAvailable = false;
00057 
00058 /**
00059  * @brief   'CAN receive-complete' interrup service routine.
00060  * @note    Called on arrival of new CAN message.
00061  *          Keep it as short as possible.
00062  * @param   
00063  * @retval  
00064  */
00065 void onMsgReceived() {
00066     msgAvailable = true;
00067 }
00068 
00069 /**
00070  * @brief   Prints CAN msg to PC's serial terminal.
00071  * @note}
00072  * @param   CANMessage to print
00073  * @retval  none
00074  */
00075 void printMsg(CANMessage& msg) {
00076     pc.printf("  ID      = 0x%.3x\r\n", msg.id);
00077     pc.printf("  Type    = %d\r\n", msg.type);
00078     pc.printf("  Format  = %d\r\n", msg.format);
00079     pc.printf("  Length  = %d\r\n", msg.len);
00080     pc.printf("  Data    =");            
00081     for(int i = 0; i < msg.len; i++)
00082         pc.printf(" 0x%.2X", msg.data[i]);
00083     pc.printf("\r\n");
00084  }
00085 
00086 /**
00087  * @brief   Main
00088  * @note
00089  * @param 
00090  * @retval
00091  */
00092 int main() {
00093 #if defined(TARGET_STM32F103C8T6)
00094     confSysClock();     //Configure the system clock (72MHz HSE clock, 48MHz USB clock)
00095 #endif
00096     pc.baud(9600);                      // set the Serial speed
00097 
00098     can = new CAN(PA_11, PA_12);        // CAN Rx pin name, CAN Tx pin name
00099     can->frequency(1000000);            // set the bit rate to 1Mbps
00100     can->attach(&onMsgReceived);        // attach the 'CAN receive-complete' interrupt service routine (ISR)
00101     
00102 #if defined(BOARD1)
00103     led = ON;       // turn the LED on
00104     timer.start();  // start the timer
00105     pc.printf("CANnucleo_Hello board #1\r\n");
00106 #else
00107     led = OFF;      // turn LED off
00108     pc.printf("CANnucleo_Hello board #2\r\n");
00109 #endif
00110 
00111     while(1) {
00112         if(timer.read_ms() >= 1000) {           // check for timeout
00113             timer.stop();                       // stop the timer
00114             timer.reset();                      // reset the timer
00115             counter++;                          // increment the counter
00116             voltage = (analogIn * 3.3f)/4096.0f;// read the small drifting voltage from analog input
00117             txMsg.clear();                      // clear the Tx message storage
00118             txMsg.id = TX_ID;                   // set the message ID
00119             // We are about to transmit two data items to the CAN bus.
00120             //     counter: uint_8 (unsigned eight bits int) value (one byte).
00121             //     voltage: floating point value (four bytes).
00122             // So the total length of payload data is five bytes.
00123             // We'll use the "<<" (append) operator to add data to the CAN message.
00124             // The usage is same as of the similar C++ io-stream operators.
00125             // NOTE: The data length of CAN message is automatically updated when using "<<" operators.  
00126             txMsg << counter << voltage;        // append data (total data length must be <= 8 bytes!)
00127             if(can->write(txMsg)) {             // transmit the CAN message
00128                 led = OFF;                      // turn the LED off
00129                 pc.printf("-------------------------------------\r\n");
00130                 pc.printf("CAN message sent\r\n");
00131                 printMsg(txMsg);
00132                 pc.printf("  counter = %d\r\n", counter);
00133                 pc.printf("  voltage = %e V\r\n", voltage);
00134              }
00135             else
00136                 pc.printf("Transmission error\r\n");
00137         }
00138         if(msgAvailable) {
00139             msgAvailable = false;               // reset the flag for next use in the interrupt service routine
00140             can->read(rxMsg);                   // read the message into the Rx message storage
00141             led = ON;                           // turn the LED on
00142             pc.printf("-------------------------------------\r\n");
00143             pc.printf("CAN message received\r\n");
00144             printMsg(rxMsg);
00145             // Filtering performed by software:           
00146             if(rxMsg.id == RX_ID) {             // about filtering performed by hardware see the comments in CANnucleo.cpp 
00147                 rxMsg >> counter >> voltage;    // extract data from the received CAN message (in same sequence as they were added)
00148                 pc.printf("  counter = %d\r\n", counter);
00149                 pc.printf("  voltage = %e V\r\n", voltage);
00150                 timer.start();                  // insert transmission lag
00151             }
00152         }
00153     }
00154 }
00155 
00156 
00157