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
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
Generated on Tue Jul 12 2022 18:33:03 by 1.7.2