├── .travis.yml ├── CANHackerV2.00.01.exe ├── CAN_BUS_Shield License.txt ├── LICENSE ├── README.md ├── arduino-canbus-monitor ├── arduino-canbus-monitor.ino ├── can-232.cpp ├── can-232.h ├── mcp_can.cpp ├── mcp_can.h └── mcp_can_dfs.h ├── docs ├── README.md ├── _config.yml └── overview.md └── sonar-project.properties /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | before_install: 3 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" 4 | - sleep 3 5 | - export DISPLAY=:1.0 6 | - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz 7 | - tar xf arduino-1.6.5-linux64.tar.xz 8 | - sudo mv arduino-1.6.5 /usr/local/share/arduino 9 | - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino 10 | script: 11 | - arduino --verify --board arduino:avr:uno "${TRAVIS_BUILD_DIR}/arduino-canbus-monitor/arduino-canbus-monitor.ino" 12 | # - sonar-scanner 13 | notifications: 14 | email: false 15 | -------------------------------------------------------------------------------- /CANHackerV2.00.01.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latonita/arduino-canbus-monitor/43de5bef55a37f0de6d7817247741222dae6ce6d/CANHackerV2.00.01.exe -------------------------------------------------------------------------------- /CAN_BUS_Shield License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Seeed Technology Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Anton Viktorov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # arduino-canbus-monitor [![Build Status](https://api.travis-ci.org/latonita/arduino-canbus-monitor.svg?branch=master)](https://travis-ci.org/latonita/arduino-canbus-monitor) [![Coverity Scan](https://scan.coverity.com/projects/11684/badge.svg)](https://scan.coverity.com/projects/latonita-arduino-canbus-monitor) [![Analytics](https://ga-beacon.appspot.com/UA-99380399-1/welcome-page)](https://github.com/igrigorik/ga-beacon) 2 | 3 | CAN BUS monitoring software based on Arduino with Seeduino/ElecFreaks CAN BUS shield based on MCP2515 (Numerous other MCP2515 based CAN BUS modules from ebay and aliexpress work well to). 4 | 5 | This software implements CAN ASCII / Serial CAN / SLCAN protocol compatible with Lawicel CAN232/CANUSB. 6 | 7 | As for PC counterpart software I personally used and can recommend two tools: 8 | 9 | 1) [Windows] CANHacker tool v.2.00.01 (by fuchs) to sniff and visualize data on the bus. You can download CANHacker tool from this forum page: http://www.canhack.net/viewforum.php?f=25&sid=ac01d465f19e088cb160cab630561607 (P.S. Looks like canhack.net no longer operating, here is a copy of installation file: [CANHackerV2.00.01.exe](https://github.com/latonita/arduino-canbus-monitor/raw/master/CANHackerV2.00.01.exe)) 10 | 11 | 2) [Windows] CAN-COOL (by MHS Elektronik), open source, but unfortunaly available only in German. Download link: http://www.mhs-elektronik.de/index.php?module=content&action=show&page=can_cool (Make sure you select RS232 and SL-CAN protocol and then click hardware bus reset icon on a toolbar) 12 | 13 | 3) [Linux] SLCAN/SocketCAN can be used https://github.com/linux-can/can-utils. See details in the end of this README file 14 | 15 | This monitor uses CAN BUS library forked from https://github.com/Seeed-Studio/CAN_BUS_Shield. 16 | 17 | Copyright (C) 2015,2016 Anton Viktorov 18 | 19 | You can buy me a beer if you like the tool :o) [![Donate](https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JPDVHYWUY3LW) 20 | 21 | 22 | See protocol definition here http://www.can232.com/docs/can232_v3.pdf and here http://www.can232.com/docs/canusb_manual.pdf 23 | 24 | Commands not supported/not implemented: 25 | - s, W, M, m, U. 26 | 27 | Commands modified: 28 | - S - supports not declared 83.3 rate 29 | - F - returns MCP2515 error flags 30 | - Z - extra Z2 option enables 4 byte timestamp vs standard 2 byte (60000ms max) 31 | 32 | ``` 33 | CMD | IMPLEMENTED | SYNTAX | DESCRIPTION 34 | ------------------------------------------------------------------------------------------------------------ 35 | 'S' | YES+ | Sn[CR] Setup with standard CAN bit-rates where n is 0-8. 36 | | | S0 10Kbit S4 125Kbit S8 1Mbit 37 | | | S1 20Kbit S5 250Kbit S9 83.3Kbit 38 | | | S2 50Kbit S6 500Kbit 39 | | | S3 100Kbit S7 800Kbit 40 | 's' | - | sxxyy[CR] Setup with BTR0/BTR1 CAN bit-rates where xx and yy is a hex value. 41 | 'O' | YES | O[CR] Open the CAN channel in normal mode (sending & receiving). 42 | 'L' | YES | L[CR] Open the CAN channel in listen only mode (receiving). 43 | 'C' | YES | C[CR] Close the CAN channel. 44 | 't' | YES | tiiildd...[CR] Transmit a standard (11bit) CAN frame. 45 | 'T' | YES | Tiiiiiiiildd...[CR] Transmit an extended (29bit) CAN frame 46 | 'r' | YES | riiil[CR] Transmit an standard RTR (11bit) CAN frame. 47 | 'R' | YES | Riiiiiiiil[CR] Transmit an extended RTR (29bit) CAN frame. 48 | 'P' | YES | P[CR] Poll incomming FIFO for CAN frames (single poll) 49 | 'A' | YES | A[CR] Polls incomming FIFO for CAN frames (all pending frames) 50 | 'F' | YES+ | F[CR] Read Status Flags. 51 | 'X' | YES | Xn[CR] Sets Auto Poll/Send ON/OFF for received frames. 52 | 'W' | - | Wn[CR] Filter mode setting. By default CAN232 works in dual filter mode (0) and is backwards compatible with previous CAN232 versions. 53 | 'M' | - | Mxxxxxxxx[CR] Sets Acceptance Code Register (ACn Register of SJA1000). // we use MCP2515, not supported 54 | 'm' | - | mxxxxxxxx[CR] Sets Acceptance Mask Register (AMn Register of SJA1000). // we use MCP2515, not supported 55 | 'U' | YES | Un[CR] Setup UART with a new baud rate where n is 0-6. 56 | 'V' | YES | v[CR] Get Version number of both CAN232 hardware and software 57 | 'v' | YES | V[CR] Get Version number of both CAN232 hardware and software 58 | 'N' | YES | N[CR] Get Serial number of the CAN232. 59 | 'Z' | YES+ | Zn[CR] Sets Time Stamp ON/OFF for received frames only. EXTENSION to LAWICEL: Z2 - millis() timestamp w/o standard 60000ms cycle 60 | 'Q' | YES todo | Qn[CR] Auto Startup feature (from power on). 61 | 62 | ``` 63 | 64 | ## Linux SLCAN instructions 65 | ### Prerequisites 66 | Install `can-utils` first. 67 | On Ubuntu and other Debian-based distros `can-utils` package is included into standard repositories: 68 | ``` 69 | sudo apt install can-utils 70 | ``` 71 | For other distros please follow respective instructions, start from here https://github.com/linux-can/can-utils 72 | 73 | ### Create CAN device 74 | ``` 75 | sudo slcan_attach -f -s4 -o /dev/ttyUSB0 76 | sudo slcand -S 115200 /dev/ttyUSB0 can0 77 | sudo ifconfig can0 up 78 | ``` 79 | where 115200 is port speed, `/dev/ttyUSB0` - name of your arduino device. can be different 80 | 81 | ### To dump running traffic 82 | ``` 83 | candump can0 84 | ``` 85 | 86 | ### To delete CAN device 87 | ``` 88 | sudo ifconfig can0 down 89 | sudo killall slcand 90 | ``` 91 | 92 | 93 | -------------------------------------------------------------------------------- /arduino-canbus-monitor/arduino-canbus-monitor.ino: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | * This is implementation of CAN BUS ASCII protocol based on LAWICEL v1.3 serial protocol 3 | * of CAN232/CANUSB device (http://www.can232.com/docs/can232_v3.pdf) 4 | * 5 | * Made for Arduino with Seeduino/ElecFreaks CAN BUS Shield based on MCP2515 6 | * 7 | * Copyright (C) 2015 Anton Viktorov 8 | * https://github.com/latonita/arduino-canbus-monitor 9 | * 10 | * This library is free software. You may use/redistribute it under The MIT License terms. 11 | * 12 | *****************************************************************************************/ 13 | 14 | #include 15 | #include "mcp_can.h" 16 | #include "can-232.h" 17 | #include "SoftwareSerial.h" 18 | 19 | #define DEBUG_MODE 20 | 21 | void setup() { 22 | Serial.begin(LW232_DEFAULT_BAUD_RATE); // default COM baud rate is 115200. 23 | 24 | // Can232::init (RATE, CLOCK) 25 | // Rates: CAN_10KBPS, CAN_20KBPS, CAN_50KBPS, CAN_100KBPS, CAN_125KBPS, CAN_250KBPS, CAN_500KBPS, CAN_500KBPS, CAN_1000KBPS, CAN_83K3BPS 26 | // Default is CAN_83K3BPS ;))))))))) 27 | // Clock: MCP_16MHz or MCP_8MHz. 28 | // Default is MCP_16MHz. Please note, not all CAN speeds supported. check big switch in mcp_can.cpp 29 | // defaults can be changed in mcp_can.h 30 | 31 | // Can232::init(); // rate and clock = LW232_DEFAULT_CAN_RATE and LW232_DEFAULT_CLOCK_FREQ 32 | // Can232::init(CAN_125KBPS); // rate = 125, clock = LW232_DEFAULT_CLOCK_FREQ 33 | Can232::init(CAN_125KBPS, MCP_16MHz); // set default rate you need here and clock frequency of CAN shield. Typically it is 16MHz, but on some MCP2515 + TJA1050 it is 8Mhz 34 | 35 | 36 | // optional custom packet filter to reduce number of messages comingh through to canhacker 37 | // Can232::setFilter(myCustomAddressFilter); 38 | } 39 | 40 | INT8U myCustomAddressFilter(INT32U addr) { 41 | INT8U ret = LW232_FILTER_SKIP; //LW232_FILTER_PROCESS or LW232_FILTER_SKIP 42 | switch(addr) { 43 | // case 0x01b: //VIN 44 | // case 0x1C8: //lights 45 | // case 0x2C0: // pedals 46 | case 0x3d0: // sound vol, treb.. 47 | ret = LW232_FILTER_PROCESS; 48 | // case 0x000: // ? 49 | // case 0x003: //shifter 50 | // case 0x015: // dor open close affects this as well 51 | // case 0x02c: // ??? 52 | // ret = 0; 53 | // break; 54 | // case 0x002: 55 | // case 0x1a7: //fuel cons or some other 56 | // ret = 1; 57 | // break; 58 | // default: 59 | // ret = 0; 60 | } 61 | 62 | return ret; 63 | } 64 | 65 | void loop() { 66 | Can232::loop(); 67 | } 68 | 69 | void serialEvent() { 70 | Can232::serialEvent(); 71 | } 72 | 73 | -------------------------------------------------------------------------------- /arduino-canbus-monitor/can-232.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | * This is implementation of CAN BUS ASCII protocol based on LAWICEL v1.3 serial protocol 3 | * of CAN232/CANUSB device (http://www.can232.com/docs/can232_v3.pdf) 4 | * 5 | * Made for Arduino with Seeduino/ElecFreaks CAN BUS Shield based on MCP2515 6 | * 7 | * Copyright (C) 2015 Anton Viktorov 8 | * https://github.com/latonita/can-ascii 9 | * 10 | * This library is free software. You may use/redistribute it under The MIT License terms. 11 | * 12 | *****************************************************************************************/ 13 | 14 | #include 15 | #include "mcp_can.h" 16 | #include "can-232.h" 17 | 18 | #define LOGGING_ENABLED 19 | 20 | #ifdef LOGGING_ENABLED 21 | #define dbg_begin(x) debug.begin(x) 22 | #define dbg0(x) debug.print(x) 23 | #define dbg1(x) debug.println(x) 24 | #define dbg2(x,y) debug.print(x); debug.println(y) 25 | #define dbgH(x) debug.print(x,HEX) 26 | #define DEBUG_RX_PIN 8 27 | #define DEBUG_TX_PIN 9 28 | #else 29 | #define dbg_begin(x) 30 | #define dbg0(x) 31 | #define dbg1(x) 32 | #define dbg2(x,y) 33 | #define dbgH(x) 34 | #endif 35 | 36 | #ifdef LOGGING_ENABLED 37 | // software serial #2: TX = digital pin 8, RX = digital pin 9 38 | // on the Mega, use other pins instead, since 8 and 9 don't work on the Mega 39 | 40 | SoftwareSerial debug(DEBUG_RX_PIN, DEBUG_TX_PIN); 41 | //#define debug Serial 42 | #endif 43 | 44 | Can232* Can232::_instance = 0; 45 | 46 | Can232* Can232::instance() { 47 | if (_instance == 0) 48 | _instance = new Can232(); 49 | return _instance; 50 | } 51 | 52 | void Can232::init(INT8U defaultCanSpeed, const INT8U clock) { 53 | dbg_begin(LW232_DEFAULT_BAUD_RATE); // logging through software serial 54 | dbg1("CAN ASCII. Welcome to debug"); 55 | 56 | instance()->lw232CanSpeedSelection = defaultCanSpeed; 57 | instance()->lw232McpModuleClock = clock; 58 | instance()->initFunc(); 59 | } 60 | 61 | void Can232::setFilter(INT8U (*userFunc)(INT32U)) { 62 | instance()->setFilterFunc(userFunc); 63 | } 64 | 65 | void Can232::loop() { 66 | instance()->loopFunc(); 67 | } 68 | 69 | void Can232::serialEvent() { 70 | instance()->serialEventFunc(); 71 | } 72 | 73 | void Can232::initFunc() { 74 | if (!inputString.reserve(LW232_INPUT_STRING_BUFFER_SIZE)) { 75 | dbg0("inputString.reserve failed in initFunc. less optimal String work is expected"); 76 | } 77 | // lw232AutoStart = true; //todo: read from eeprom 78 | // lw232AutoPoll = false; //todo: read from eeprom 79 | // lw232TimeStamp = //read from eeprom 80 | // lw232Message[0] = 'Z'; lw232Message[1] = '1'; exec(); 81 | //if (lw232AutoStart) { 82 | inputString = "O\0x0D"; 83 | stringComplete = true; 84 | loopFunc(); 85 | //} 86 | } 87 | 88 | void Can232::setFilterFunc(INT8U (*userFunc)(INT32U)) { 89 | instance()->userAddressFilterFunc = userFunc; 90 | } 91 | 92 | void Can232::loopFunc() { 93 | if (stringComplete) { 94 | int len = inputString.length(); 95 | if (len > 0 && len < LW232_FRAME_MAX_SIZE) { 96 | strcpy((char*)lw232Message, inputString.c_str()); 97 | exec(); 98 | } 99 | // clear the string: 100 | inputString = ""; 101 | stringComplete = false; 102 | } 103 | if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED) { 104 | int recv = 0; 105 | while (CAN_MSGAVAIL == checkReceive() && recv++<5) { 106 | dbg0('+'); 107 | if (CAN_OK == receiveSingleFrame()) { 108 | Serial.write(LW232_CR); 109 | } 110 | } 111 | Serial.flush(); 112 | } 113 | } 114 | void Can232::serialEventFunc() { 115 | while (Serial.available()) { 116 | char inChar = (char)Serial.read(); 117 | inputString += inChar; 118 | if (inChar == LW232_CR) { 119 | stringComplete = true; 120 | } 121 | } 122 | } 123 | 124 | INT8U Can232::exec() { 125 | dbg2("Command received:", inputString); 126 | lw232LastErr = parseAndRunCommand(); 127 | switch (lw232LastErr) { 128 | case LW232_OK: 129 | Serial.write(LW232_RET_ASCII_OK); 130 | break; 131 | case LW232_OK_SMALL: 132 | Serial.write(LW232_RET_ASCII_OK_SMALL); 133 | Serial.write(LW232_RET_ASCII_OK); 134 | break; 135 | case LW232_OK_BIG: 136 | Serial.write(LW232_RET_ASCII_OK_BIG); 137 | Serial.write(LW232_RET_ASCII_OK); 138 | break; 139 | case LW232_ERR_NOT_IMPLEMENTED: 140 | // Choose behavior: will it fail or not when not implemented command comes in. Some can monitors might be affected by this selection. 141 | Serial.write(LW232_RET_ASCII_ERROR); 142 | //Serial.write(LW232_RET_ASCII_OK); 143 | break; 144 | default: 145 | Serial.write(LW232_RET_ASCII_ERROR); 146 | } 147 | return 0; 148 | } 149 | 150 | INT8U Can232::parseAndRunCommand() { 151 | INT8U ret = LW232_OK; 152 | INT8U idx = 0; 153 | INT8U err = 0; 154 | 155 | lw232LastErr = LW232_OK; 156 | 157 | switch (lw232Message[0]) { 158 | case LW232_CMD_SETUP: 159 | // Sn[CR] Setup with standard CAN bit-rates where n is 0-9. 160 | if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) { 161 | idx = HexHelper::parseNibbleWithLimit(lw232Message[1], LW232_CAN_BAUD_NUM); 162 | lw232CanSpeedSelection = lw232CanBaudRates[idx]; 163 | } 164 | else { 165 | ret = LW232_ERR; 166 | } 167 | break; 168 | case LW232_CMD_SETUP_BTR: 169 | // sxxyy[CR] Setup with BTR0/BTR1 CAN bit-rates where xx and yy is a hex value. 170 | ret = LW232_ERR; break; 171 | case LW232_CMD_OPEN: 172 | // O[CR] Open the CAN channel in normal mode (sending & receiving). 173 | if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) { 174 | ret = openCanBus(); 175 | if (ret == LW232_OK) { 176 | lw232CanChannelMode = LW232_STATUS_CAN_OPEN_NORMAL; 177 | } 178 | } 179 | else { 180 | ret = LW232_ERR; 181 | } 182 | break; 183 | case LW232_CMD_LISTEN: 184 | // L[CR] Open the CAN channel in listen only mode (receiving). 185 | if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) { 186 | ret = openCanBus(); 187 | if (ret == LW232_OK) { 188 | lw232CanChannelMode = LW232_STATUS_CAN_OPEN_LISTEN; 189 | } 190 | } 191 | else { 192 | ret = LW232_ERR; 193 | } 194 | break; 195 | case LW232_CMD_CLOSE: 196 | // C[CR] Close the CAN channel. 197 | if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED) { 198 | lw232CanChannelMode = LW232_STATUS_CAN_CLOSED; 199 | } 200 | else { 201 | ret = LW232_ERR; 202 | } 203 | break; 204 | case LW232_CMD_TX11: 205 | // tiiildd...[CR] Transmit a standard (11bit) CAN frame. 206 | if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) { 207 | parseCanStdId(); 208 | lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_STD_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1); 209 | for (; idx < lw232PacketLen; idx++) { 210 | lw232Buffer[idx] = HexHelper::parseFullByte(lw232Message[LW232_OFFSET_STD_PKT_DATA + idx * 2], lw232Message[LW232_OFFSET_STD_PKT_DATA + idx * 2 + 1]); 211 | } 212 | INT8U mcpErr = sendMsgBuf(lw232CanId, 0, 0, lw232PacketLen, lw232Buffer); 213 | if (mcpErr != CAN_OK) { 214 | ret = LW232_ERR; 215 | } else if (lw232AutoPoll) { 216 | ret = LW232_OK_SMALL; 217 | } 218 | } 219 | else { 220 | ret = LW232_ERR; 221 | } 222 | break; 223 | case LW232_CMD_TX29: 224 | // Tiiiiiiiildd...[CR] Transmit an extended (29bit) CAN frame 225 | if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) { 226 | parseCanExtId(); 227 | lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_EXT_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1); 228 | for (; idx < lw232PacketLen; idx++) { 229 | lw232Buffer[idx] = HexHelper::parseFullByte(lw232Message[LW232_OFFSET_EXT_PKT_DATA + idx * 2], lw232Message[LW232_OFFSET_EXT_PKT_DATA + idx * 2 + 1]); 230 | } 231 | if (CAN_OK != sendMsgBuf(lw232CanId, 1, 0, lw232PacketLen, lw232Buffer)) { 232 | ret = LW232_ERR; 233 | } else if (lw232AutoPoll) { 234 | ret = LW232_OK_BIG; 235 | } else { 236 | ret = LW232_OK; 237 | } 238 | } 239 | break; 240 | case LW232_CMD_RTR11: 241 | // riiil[CR] Transmit an standard RTR (11bit) CAN frame. 242 | if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) { 243 | parseCanStdId(); 244 | lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_STD_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1); 245 | if (CAN_OK != sendMsgBuf(lw232CanId, 0, 1, lw232PacketLen, lw232Buffer)) { 246 | ret = LW232_ERR; 247 | } 248 | else if (lw232AutoPoll) { 249 | ret = LW232_OK_SMALL; 250 | } 251 | } 252 | else { 253 | ret = LW232_ERR; 254 | } 255 | break; 256 | case LW232_CMD_RTR29: 257 | // Riiiiiiiil[CR] Transmit an extended RTR (29bit) CAN frame. 258 | if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) { 259 | parseCanExtId(); 260 | lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_EXT_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1); 261 | if (CAN_OK != sendMsgBuf(lw232CanId, 1, 1, lw232PacketLen, lw232Buffer)) { 262 | ret = LW232_ERR; 263 | } 264 | else if (lw232AutoPoll) { 265 | ret = LW232_OK_SMALL; // not a typo. strangely can232_v3.pdf tells to return "z[CR]", not "Z[CR]" as in 29bit. todo: check if it is error in pdf??? 266 | } 267 | } else { 268 | ret = LW232_ERR; 269 | } 270 | break; 271 | case LW232_CMD_POLL_ONE: 272 | // P[CR] Poll incomming FIFO for CAN frames (single poll) 273 | if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED && lw232AutoPoll == LW232_AUTOPOLL_OFF) { 274 | if (CAN_MSGAVAIL == checkReceive()) { 275 | ret = receiveSingleFrame(); 276 | } 277 | } else { 278 | ret = LW232_ERR; 279 | } 280 | break; 281 | case LW232_CMD_POLL_MANY: 282 | // A[CR] Polls incomming FIFO for CAN frames (all pending frames) 283 | if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED && lw232AutoPoll == LW232_AUTOPOLL_OFF) { 284 | while (CAN_MSGAVAIL == checkReceive()) { 285 | ret = ret ^ receiveSingleFrame(); 286 | if (ret != CAN_OK) 287 | break; 288 | Serial.write(LW232_CR); 289 | } 290 | if (ret == CAN_OK) 291 | Serial.print(LW232_ALL); 292 | } else { 293 | ret = LW232_ERR; 294 | } 295 | break; 296 | case LW232_CMD_FLAGS: 297 | // F[CR] Read Status Flags. 298 | // LAWICEL CAN232 and CANUSB have some specific errors which differ from MCP2515/MCP2551 errors. We just return MCP2515 error. 299 | Serial.print(LW232_FLAG); 300 | if (lw232CAN.checkError(&err) == CAN_OK) 301 | err = 0; 302 | HexHelper::printFullByte(err & MCP_EFLG_ERRORMASK); 303 | break; 304 | case LW232_CMD_AUTOPOLL: 305 | // Xn[CR] Sets Auto Poll/Send ON/OFF for received frames. 306 | if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) { 307 | lw232AutoPoll = (lw232Message[1] == LW232_ON_ONE) ? LW232_AUTOPOLL_ON : LW232_AUTOPOLL_OFF; 308 | //todo: save to eeprom 309 | } else { 310 | ret = LW232_ERR; 311 | } 312 | break; 313 | case LW232_CMD_FILTER: 314 | // Wn[CR] Filter mode setting. By default CAN232 works in dual filter mode (0) and is backwards compatible with previous CAN232 versions. 315 | ret = LW232_ERR_NOT_IMPLEMENTED; break; 316 | case LW232_CMD_ACC_CODE: 317 | // Mxxxxxxxx[CR] Sets Acceptance Code Register (ACn Register of SJA1000). // we use MCP2515, 318 | ret = LW232_ERR_NOT_IMPLEMENTED; break; 319 | case LW232_CMD_ACC_MASK: 320 | // mxxxxxxxx[CR] Sets Acceptance Mask Register (AMn Register of SJA1000). 321 | ret = LW232_ERR_NOT_IMPLEMENTED; break; 322 | case LW232_CMD_UART: 323 | // Un[CR] Setup UART with a new baud rate where n is 0-6. 324 | idx = HexHelper::parseNibbleWithLimit(lw232Message[1], LW232_UART_BAUD_NUM); 325 | Serial.begin(lw232SerialBaudRates[idx]); 326 | break; 327 | case LW232_CMD_VERSION1: 328 | case LW232_CMD_VERSION2: 329 | // V[CR] Get Version number of both CAN232 hardware and software 330 | Serial.print(LW232_LAWICEL_VERSION_STR); 331 | break; 332 | case LW232_CMD_SERIAL: 333 | // N[CR] Get Serial number of the CAN232. 334 | Serial.print(LW232_LAWICEL_SERIAL_NUM); 335 | break; 336 | case LW232_CMD_TIMESTAMP: 337 | // Zn[CR] Sets Time Stamp ON/OFF for received frames only. Z0 - OFF, Z1 - Lawicel's timestamp 2 bytes, Z2 - arduino timestamp 4 bytes. 338 | if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) { 339 | // lw232TimeStamp = (lw232Message[1] == LW232_ON_ONE); 340 | if (lw232Message[1] == LW232_ON_ONE) { 341 | lw232TimeStamp = LW232_TIMESTAMP_ON_NORMAL; 342 | } 343 | else if (lw232Message[1] == LW232_ON_TWO) { 344 | lw232TimeStamp = LW232_TIMESTAMP_ON_EXTENDED; 345 | } 346 | else { 347 | lw232TimeStamp = LW232_TIMESTAMP_OFF; 348 | } 349 | } 350 | else { 351 | ret = LW232_ERR; 352 | } 353 | break; 354 | case LW232_CMD_AUTOSTART: 355 | // Qn[CR] Auto Startup feature (from power on). 356 | if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED) { 357 | if (lw232Message[1] == LW232_ON_ONE) { 358 | lw232AutoStart = LW232_AUTOSTART_ON_NORMAL; 359 | } 360 | else if (lw232Message[1] == LW232_ON_TWO) { 361 | lw232AutoStart = LW232_AUTOSTART_ON_LISTEN; 362 | } 363 | else { 364 | lw232AutoStart = LW232_AUTOSTART_OFF; 365 | } 366 | //todo: save to eeprom 367 | } 368 | else { 369 | ret = LW232_ERR; 370 | } 371 | break; 372 | default: 373 | ret = LW232_ERR_UNKNOWN_CMD; 374 | } 375 | 376 | return ret; 377 | } 378 | 379 | INT8U Can232::checkReceive() { 380 | #ifndef _MCP_FAKE_MODE_ 381 | return lw232CAN.checkReceive(); 382 | #else 383 | return CAN_MSGAVAIL; 384 | #endif 385 | } 386 | 387 | INT8U Can232::readMsgBufID(INT32U *ID, INT8U *len, INT8U buf[]) { 388 | #ifndef _MCP_FAKE_MODE_ 389 | return lw232CAN.readMsgBufID(ID, len, buf); 390 | #else 391 | *ID = random(0x100, 0x110); 392 | *len = 4; 393 | buf[0] = random(0x01, 0x10); 394 | buf[1] = random(0xa1, 0xf0); 395 | buf[2] = 0x00; 396 | buf[3] = 0x00; 397 | return CAN_OK; 398 | #endif 399 | } 400 | 401 | 402 | 403 | INT8U Can232::receiveSingleFrame() { 404 | INT8U ret = LW232_OK; 405 | INT8U idx = 0; 406 | if (CAN_OK == readMsgBufID(&lw232CanId, &lw232PacketLen, lw232Buffer)) { 407 | if (lw232CanId > 0x1FFFFFFF) { 408 | ret = LW232_ERR; // address if totally wrong 409 | } 410 | else if (checkPassFilter(lw232CanId)) {// do we want to skip some addresses? 411 | if (isExtendedFrame()) { 412 | Serial.print(LW232_TR29); 413 | HexHelper::printFullByte(HIGH_BYTE(HIGH_WORD(lw232CanId))); 414 | HexHelper::printFullByte(LOW_BYTE(HIGH_WORD(lw232CanId))); 415 | HexHelper::printFullByte(HIGH_BYTE(LOW_WORD(lw232CanId))); 416 | HexHelper::printFullByte(LOW_BYTE(LOW_WORD(lw232CanId))); 417 | } 418 | else { 419 | Serial.print(LW232_TR11); 420 | HexHelper::printNibble(HIGH_BYTE(LOW_WORD(lw232CanId))); 421 | HexHelper::printFullByte(LOW_BYTE(LOW_WORD(lw232CanId))); 422 | } 423 | //write data len 424 | HexHelper::printNibble(lw232PacketLen); 425 | //write data 426 | for (idx = 0; idx < lw232PacketLen; idx++) { 427 | HexHelper::printFullByte(lw232Buffer[idx]); 428 | } 429 | //write timestamp if needed 430 | if (lw232TimeStamp != LW232_TIMESTAMP_OFF) { 431 | INT32U time = millis(); 432 | if (lw232TimeStamp == LW232_TIMESTAMP_ON_NORMAL) { 433 | // standard LAWICEL protocol. two bytes. 434 | time %= 60000; 435 | } else { 436 | // non standard protocol - 4 bytes timestamp 437 | HexHelper::printFullByte(HIGH_BYTE(HIGH_WORD(time))); 438 | HexHelper::printFullByte(LOW_BYTE(HIGH_WORD(time))); 439 | } 440 | HexHelper::printFullByte(HIGH_BYTE(LOW_WORD(time))); 441 | HexHelper::printFullByte(LOW_BYTE(LOW_WORD(time))); 442 | } 443 | } 444 | } 445 | else { 446 | ret = LW232_ERR; 447 | } 448 | return ret; 449 | } 450 | 451 | 452 | INT8U Can232::isExtendedFrame() { 453 | #ifndef _MCP_FAKE_MODE_ 454 | return lw232CAN.isExtendedFrame(); 455 | #else 456 | return lw232CanId > 0x7FF ? 1 : 0; //simple hack for fake mode 457 | #endif 458 | } 459 | 460 | 461 | INT8U Can232::checkPassFilter(INT32U addr) { 462 | if (userAddressFilterFunc == 0) 463 | return LW232_FILTER_PROCESS; 464 | 465 | return (*userAddressFilterFunc)(addr); 466 | } 467 | 468 | INT8U Can232::openCanBus() { 469 | INT8U ret = LW232_OK; 470 | #ifndef _MCP_FAKE_MODE_ 471 | if (CAN_OK != lw232CAN.begin(lw232CanSpeedSelection, lw232McpModuleClock)) 472 | ret = LW232_ERR; 473 | #endif 474 | return ret; 475 | } 476 | 477 | 478 | INT8U Can232::sendMsgBuf(INT32U id, INT8U ext, INT8U rtr, INT8U len, INT8U *buf) { 479 | #ifndef _MCP_FAKE_MODE_ 480 | return lw232CAN.sendMsgBuf(id, ext, rtr, len, buf); 481 | #else 482 | Serial.print("= '0' && hex <= '9') { 537 | ret = hex - '0'; 538 | } else if (hex >= 'a' && hex <= 'f') { 539 | ret = hex - 'a' + 10; 540 | } else if (hex >= 'A' && hex <= 'F') { 541 | ret = hex - 'A' + 10; 542 | } // else error, return 0 543 | return ret; 544 | } 545 | 546 | INT8U HexHelper::parseFullByte(INT8U H, INT8U L) { 547 | return (parseNibble(H) << 4) + parseNibble(L); 548 | } 549 | 550 | INT8U HexHelper::parseNibbleWithLimit(INT8U hex, INT8U limit) { 551 | INT8U ret = parseNibble(hex); 552 | if (ret < limit) 553 | return ret; 554 | else 555 | return 0; 556 | } 557 | -------------------------------------------------------------------------------- /arduino-canbus-monitor/can-232.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | * This is implementation of CAN BUS ASCII protocol based on LAWICEL v1.3 serial protocol 3 | * of CAN232/CANUSB device (http://www.can232.com/docs/can232_v3.pdf) 4 | * 5 | * Made for Arduino with Seeduino/ElecFreaks CAN BUS Shield based on MCP2515 6 | * 7 | * Copyright (C) 2015 Anton Viktorov 8 | * https://github.com/latonita/can-ascii 9 | * 10 | * This library is free software. You may use/redistribute it under The MIT License terms. 11 | * 12 | *****************************************************************************************/ 13 | 14 | 15 | #ifndef _CAN_232_H_ 16 | #define _CAN_232_H_ 17 | 18 | //#if defined(ARDUINO) && ARDUINO >= 100 19 | // #include "arduino.h" 20 | //#else 21 | // #include "WProgram.h" 22 | //#endif 23 | 24 | #include "mcp_can.h" 25 | #include "SoftwareSerial.h" 26 | 27 | #define LW232_LAWICEL_VERSION_STR "V1013" 28 | #define LW232_LAWICEL_SERIAL_NUM "NA123" 29 | #define LW232_CAN_BUS_SHIELD_CS_PIN 10 30 | 31 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | // 33 | // Commands not supported/not implemented: 34 | // s, W, M, m, U 35 | // 36 | // Commands modified: 37 | // S - supports not declared 83.3 rate straight away (S9) 38 | // refer to https://github.com/latonita/CAN_BUS_Shield fork with 83.3 support, easy to add. 39 | // F - returns MCP2515 error flags 40 | // Z - extra Z2 option enables 4 byte timestamp vs standard 2 byte (60000ms max) 41 | // 42 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | // 44 | // CODE SUPPORTED SYNTAX DESCRIPTION 45 | // 46 | #define LW232_CMD_SETUP 'S' // YES+ Sn[CR] Setup with standard CAN bit-rates where n is 0-8. 47 | // S0 10Kbit S4 125Kbit S8 1Mbit 48 | // S1 20Kbit S5 250Kbit S9 83.3Kbit 49 | // S2 50Kbit S6 500Kbit 50 | // S3 100Kbit S7 800Kbit 51 | #define LW232_CMD_SETUP_BTR 's' // - sxxyy[CR] Setup with BTR0/BTR1 CAN bit-rates where xx and yy is a hex value. 52 | #define LW232_CMD_OPEN 'O' // YES O[CR] Open the CAN channel in normal mode (sending & receiving). 53 | #define LW232_CMD_LISTEN 'L' // YES L[CR] Open the CAN channel in listen only mode (receiving). 54 | #define LW232_CMD_CLOSE 'C' // YES C[CR] Close the CAN channel. 55 | #define LW232_CMD_TX11 't' // YES tiiildd...[CR] Transmit a standard (11bit) CAN frame. 56 | #define LW232_CMD_TX29 'T' // YES Tiiiiiiiildd...[CR] Transmit an extended (29bit) CAN frame 57 | #define LW232_CMD_RTR11 'r' // YES riiil[CR] Transmit an standard RTR (11bit) CAN frame. 58 | #define LW232_CMD_RTR29 'R' // YES Riiiiiiiil[CR] Transmit an extended RTR (29bit) CAN frame. 59 | #define LW232_CMD_POLL_ONE 'P' // YES P[CR] Poll incomming FIFO for CAN frames (single poll) 60 | #define LW232_CMD_POLL_MANY 'A' // YES A[CR] Polls incomming FIFO for CAN frames (all pending frames) 61 | #define LW232_CMD_FLAGS 'F' // YES+ F[CR] Read Status Flags. 62 | #define LW232_CMD_AUTOPOLL 'X' // YES Xn[CR] Sets Auto Poll/Send ON/OFF for received frames. 63 | #define LW232_CMD_FILTER 'W' // - Wn[CR] Filter mode setting. By default CAN232 works in dual filter mode (0) and is backwards compatible with previous CAN232 versions. 64 | #define LW232_CMD_ACC_CODE 'M' // - Mxxxxxxxx[CR] Sets Acceptance Code Register (ACn Register of SJA1000). // we use MCP2515, not supported 65 | #define LW232_CMD_ACC_MASK 'm' // - mxxxxxxxx[CR] Sets Acceptance Mask Register (AMn Register of SJA1000). // we use MCP2515, not supported 66 | #define LW232_CMD_UART 'U' // YES Un[CR] Setup UART with a new baud rate where n is 0-6. 67 | #define LW232_CMD_VERSION1 'V' // YES v[CR] Get Version number of both CAN232 hardware and software 68 | #define LW232_CMD_VERSION2 'v' // YES V[CR] Get Version number of both CAN232 hardware and software 69 | #define LW232_CMD_SERIAL 'N' // YES N[CR] Get Serial number of the CAN232. 70 | #define LW232_CMD_TIMESTAMP 'Z' // YES+ Zn[CR] Sets Time Stamp ON/OFF for received frames only. EXTENSION to LAWICEL: Z2 - millis() timestamp w/o standard 60000ms cycle 71 | #define LW232_CMD_AUTOSTART 'Q' // YES todo Qn[CR] Auto Startup feature (from power on). 72 | 73 | #define LOW_BYTE(x) ((unsigned char)((x)&0xFF)) 74 | #define HIGH_BYTE(x) ((unsigned char)(((x)>>8)&0xFF)) 75 | #define LOW_WORD(x) ((unsigned short)((x)&0xFFFF)) 76 | #define HIGH_WORD(x) ((unsigned short)(((x)>>16)&0xFFFF)) 77 | 78 | #ifndef INT32U 79 | #define INT32U unsigned long 80 | #endif 81 | 82 | #ifndef INT16U 83 | #define INT16U word 84 | #endif 85 | 86 | #ifndef INT8U 87 | #define INT8U byte 88 | #endif 89 | 90 | #define LW232_OK 0x00 91 | #define LW232_OK_SMALL 0x01 92 | #define LW232_OK_BIG 0x02 93 | #define LW232_ERR 0x03 94 | #define LW232_ERR_NOT_IMPLEMENTED 0x04 95 | #define LW232_ERR_UNKNOWN_CMD 0x05 96 | 97 | #define LW232_FILTER_SKIP 0x00 98 | #define LW232_FILTER_PROCESS 0x01 99 | 100 | //#define LW232_IS_OK(x) ((x)==LW232_OK ||(x)==LW232_OK_NEW ? TRUE : FALSE) 101 | 102 | #define LW232_CR '\r' 103 | #define LW232_ALL 'A' 104 | #define LW232_FLAG 'F' 105 | #define LW232_TR11 't' 106 | #define LW232_TR29 'T' 107 | 108 | #define LW232_RET_ASCII_OK 0x0D 109 | #define LW232_RET_ASCII_ERROR 0x07 110 | #define LW232_RET_ASCII_OK_SMALL 'z' 111 | #define LW232_RET_ASCII_OK_BIG 'Z' 112 | 113 | #define LW232_STATUS_CAN_CLOSED 0x00 114 | #define LW232_STATUS_CAN_OPEN_NORMAL 0x01 115 | #define LW232_STATUS_CAN_OPEN_LISTEN 0x01 116 | 117 | #define LW232_FRAME_MAX_LENGTH 0x08 118 | #define LW232_FRAME_MAX_SIZE (sizeof("Tiiiiiiiildddddddddddddddd\r")+1) 119 | 120 | #define LW232_INPUT_STRING_BUFFER_SIZE 200 121 | 122 | #define LW232_OFF '0' 123 | #define LW232_ON_ONE '1' 124 | #define LW232_ON_TWO '2' 125 | 126 | #define LW232_AUTOPOLL_OFF 0x00 127 | #define LW232_AUTOPOLL_ON 0x01 128 | 129 | #define LW232_AUTOSTART_OFF 0x00 130 | #define LW232_AUTOSTART_ON_NORMAL 0x01 131 | #define LW232_AUTOSTART_ON_LISTEN 0x02 132 | 133 | #define LW232_TIMESTAMP_OFF 0x00 134 | #define LW232_TIMESTAMP_ON_NORMAL 0x01 135 | #define LW232_TIMESTAMP_ON_EXTENDED 0x02 136 | 137 | #define LW232_OFFSET_STD_PKT_LEN 0x04 138 | #define LW232_OFFSET_STD_PKT_DATA 0x05 139 | #define LW232_OFFSET_EXT_PKT_LEN 0x09 140 | #define LW232_OFFSET_EXT_PKT_DATA 0x0A 141 | 142 | 143 | #define LW232_DEFAULT_BAUD_RATE 115200 144 | #define LW232_DEFAULT_CAN_RATE CAN_500KBPS 145 | #define LW232_DEFAULT_CLOCK_FREQ MCP_16MHz 146 | 147 | #define LW232_CAN_BAUD_NUM 0x0a 148 | #define LW232_UART_BAUD_NUM 0x07 149 | 150 | 151 | const INT32U lw232SerialBaudRates[] //PROGMEM 152 | = { 230400, 115200, 57600, 38400, 19200, 9600, 2400 }; 153 | 154 | const INT8U lw232CanBaudRates[] //PROGMEM 155 | = { CAN_10KBPS, CAN_20KBPS, CAN_50KBPS, CAN_100KBPS, CAN_125KBPS, CAN_250KBPS, CAN_500KBPS, CAN_500KBPS /*CAN_800KBPS*/, CAN_1000KBPS, CAN_83K3BPS }; 156 | 157 | class Can232 158 | { 159 | public: 160 | static void init(INT8U defaultCanSpeed = LW232_DEFAULT_CAN_RATE, const INT8U clock = LW232_DEFAULT_CLOCK_FREQ); 161 | static void setFilter(INT8U (*userFunc)(INT32U)); 162 | static void loop(); 163 | static void serialEvent(); 164 | 165 | private: 166 | static Can232* _instance; 167 | static Can232* instance(); 168 | 169 | void initFunc(); 170 | void setFilterFunc(INT8U (*userFunc)(INT32U)); 171 | void loopFunc(); 172 | void serialEventFunc(); 173 | 174 | INT8U (*userAddressFilterFunc)(INT32U addr) = 0; 175 | 176 | MCP_CAN lw232CAN = MCP_CAN(LW232_CAN_BUS_SHIELD_CS_PIN); 177 | 178 | INT8U lw232CanSpeedSelection = CAN_83K3BPS; 179 | INT8U lw232McpModuleClock = MCP_16MHz; 180 | INT8U lw232CanChannelMode = LW232_STATUS_CAN_CLOSED; 181 | INT8U lw232LastErr = LW232_OK; 182 | 183 | INT8U lw232AutoStart = LW232_AUTOSTART_OFF; 184 | INT8U lw232AutoPoll = LW232_AUTOPOLL_OFF; 185 | INT8U lw232TimeStamp = LW232_TIMESTAMP_OFF; 186 | 187 | INT32U lw232CanId = 0; 188 | 189 | INT8U lw232Buffer[8]; 190 | INT8U lw232PacketLen = 0; 191 | 192 | INT8U lw232Message[LW232_FRAME_MAX_SIZE]; 193 | 194 | String inputString = ""; // a string to hold incoming data 195 | boolean stringComplete = false; // whether the string is complete 196 | 197 | INT8U parseAndRunCommand(); 198 | INT8U exec(); 199 | 200 | INT8U checkReceive(); 201 | INT8U readMsgBufID(INT32U *ID, INT8U *len, INT8U buf[]); 202 | INT8U receiveSingleFrame(); 203 | INT8U isExtendedFrame(); 204 | INT8U checkPassFilter(INT32U addr); 205 | INT8U openCanBus(); 206 | 207 | INT8U sendMsgBuf(INT32U id, INT8U ext, INT8U rtr, INT8U len, INT8U *buf); 208 | 209 | void parseCanStdId(); 210 | void parseCanExtId(); 211 | }; 212 | 213 | class HexHelper { 214 | public: 215 | static void printFullByte(INT8U b); 216 | static void printNibble(INT8U b); 217 | 218 | static INT8U parseNibble(INT8U hex); 219 | static INT8U parseFullByte(INT8U H, INT8U L); 220 | static INT8U parseNibbleWithLimit(INT8U hex, INT8U limit); 221 | }; 222 | 223 | class Can232Fake : Can232 { 224 | 225 | }; 226 | 227 | 228 | #endif 229 | -------------------------------------------------------------------------------- /arduino-canbus-monitor/mcp_can.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | mcp_can.cpp 3 | 2012 Copyright (c) Seeed Technology Inc. All right reserved. 4 | 5 | Author:Loovee 6 | Contributor: Cory J. Fowler 7 | 2014-1-16 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110- 21 | 1301 USA 22 | */ 23 | #include "mcp_can.h" 24 | 25 | //#define DEBUG_MODE 26 | 27 | #define spi_readwrite SPI.transfer 28 | #define spi_read() spi_readwrite(0x00) 29 | 30 | /********************************************************************************************************* 31 | ** Function name: mcp2515_reset 32 | ** Descriptions: reset the device 33 | *********************************************************************************************************/ 34 | void MCP_CAN::mcp2515_reset(void) 35 | { 36 | MCP2515_SELECT(); 37 | spi_readwrite(MCP_RESET); 38 | MCP2515_UNSELECT(); 39 | delay(10); 40 | } 41 | 42 | /********************************************************************************************************* 43 | ** Function name: mcp2515_readRegister 44 | ** Descriptions: read register 45 | *********************************************************************************************************/ 46 | INT8U MCP_CAN::mcp2515_readRegister(const INT8U address) 47 | { 48 | INT8U ret; 49 | 50 | MCP2515_SELECT(); 51 | spi_readwrite(MCP_READ); 52 | spi_readwrite(address); 53 | ret = spi_read(); 54 | MCP2515_UNSELECT(); 55 | 56 | return ret; 57 | } 58 | 59 | /********************************************************************************************************* 60 | ** Function name: mcp2515_readRegisterS 61 | ** Descriptions: read registerS 62 | *********************************************************************************************************/ 63 | void MCP_CAN::mcp2515_readRegisterS(const INT8U address, INT8U values[], const INT8U n) 64 | { 65 | INT8U i; 66 | MCP2515_SELECT(); 67 | spi_readwrite(MCP_READ); 68 | spi_readwrite(address); 69 | // mcp2515 has auto-increment of address-pointer 70 | for (i=0; i TXBnD7 */ 420 | a1 = MCP_TXB0CTRL; 421 | a2 = MCP_TXB1CTRL; 422 | a3 = MCP_TXB2CTRL; 423 | for (i = 0; i < 14; i++) { /* in-buffer loop */ 424 | mcp2515_setRegister(a1, 0); 425 | mcp2515_setRegister(a2, 0); 426 | mcp2515_setRegister(a3, 0); 427 | a1++; 428 | a2++; 429 | a3++; 430 | } 431 | mcp2515_setRegister(MCP_RXB0CTRL, 0); 432 | mcp2515_setRegister(MCP_RXB1CTRL, 0); 433 | } 434 | 435 | /********************************************************************************************************* 436 | ** Function name: mcp2515_init 437 | ** Descriptions: init the device 438 | *********************************************************************************************************/ 439 | INT8U MCP_CAN::mcp2515_init(const INT8U canSpeed, const INT8U clock) /* mcp2515init */ 440 | { 441 | 442 | INT8U res; 443 | 444 | mcp2515_reset(); 445 | 446 | res = mcp2515_setCANCTRL_Mode(MODE_CONFIG); 447 | if(res > 0) 448 | { 449 | #if DEBUG_MODE 450 | Serial.print("Enter setting mode fall\r\n"); 451 | #else 452 | delay(10); 453 | #endif 454 | return res; 455 | } 456 | #if DEBUG_MODE 457 | Serial.print("Enter setting mode success \r\n"); 458 | #else 459 | delay(10); 460 | #endif 461 | 462 | /* set boadrate */ 463 | if (mcp2515_configRate(canSpeed, clock)) 464 | { 465 | #if DEBUG_MODE 466 | Serial.print("set rate fall!!\r\n"); 467 | #else 468 | delay(10); 469 | #endif 470 | return res; 471 | } 472 | #if DEBUG_MODE 473 | Serial.print("set rate success!!\r\n"); 474 | #else 475 | delay(10); 476 | #endif 477 | 478 | if ( res == MCP2515_OK ) { 479 | 480 | /* init canbuffers */ 481 | mcp2515_initCANBuffers(); 482 | 483 | /* interrupt mode */ 484 | mcp2515_setRegister(MCP_CANINTE, MCP_RX0IF | MCP_RX1IF); 485 | 486 | #if (DEBUG_RXANY==1) 487 | /* enable both receive-buffers */ 488 | /* to receive any message */ 489 | /* and enable rollover */ 490 | mcp2515_modifyRegister(MCP_RXB0CTRL, 491 | MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, 492 | MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK); 493 | mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK, 494 | MCP_RXB_RX_ANY); 495 | #else 496 | /* enable both receive-buffers */ 497 | /* to receive messages */ 498 | /* with std. and ext. identifie */ 499 | /* rs */ 500 | /* and enable rollover */ 501 | mcp2515_modifyRegister(MCP_RXB0CTRL, 502 | MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, 503 | MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK ); 504 | mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK, 505 | MCP_RXB_RX_STDEXT); 506 | #endif 507 | /* enter normal mode */ 508 | res = mcp2515_setCANCTRL_Mode(MODE_NORMAL); 509 | if (res) 510 | { 511 | #if DEBUG_MODE 512 | Serial.print("Enter Normal Mode Fall!!\r\n"); 513 | #else 514 | delay(10); 515 | #endif 516 | return res; 517 | } 518 | 519 | 520 | #if DEBUG_MODE 521 | Serial.print("Enter Normal Mode Success!!\r\n"); 522 | #else 523 | delay(10); 524 | #endif 525 | 526 | } 527 | return res; 528 | 529 | } 530 | 531 | /********************************************************************************************************* 532 | ** Function name: mcp2515_write_id 533 | ** Descriptions: write can id 534 | *********************************************************************************************************/ 535 | void MCP_CAN::mcp2515_write_id( const INT8U mcp_addr, const INT8U ext, const INT32U id ) 536 | { 537 | uint16_t canid; 538 | INT8U tbufdata[4]; 539 | 540 | canid = (uint16_t)(id & 0x0FFFF); 541 | 542 | if ( ext == 1) 543 | { 544 | tbufdata[MCP_EID0] = (INT8U) (canid & 0xFF); 545 | tbufdata[MCP_EID8] = (INT8U) (canid >> 8); 546 | canid = (uint16_t)(id >> 16); 547 | tbufdata[MCP_SIDL] = (INT8U) (canid & 0x03); 548 | tbufdata[MCP_SIDL] += (INT8U) ((canid & 0x1C) << 3); 549 | tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M; 550 | tbufdata[MCP_SIDH] = (INT8U) (canid >> 5 ); 551 | } 552 | else 553 | { 554 | tbufdata[MCP_SIDH] = (INT8U) (canid >> 3 ); 555 | tbufdata[MCP_SIDL] = (INT8U) ((canid & 0x07 ) << 5); 556 | tbufdata[MCP_EID0] = 0; 557 | tbufdata[MCP_EID8] = 0; 558 | } 559 | mcp2515_setRegisterS( mcp_addr, tbufdata, 4 ); 560 | } 561 | 562 | /********************************************************************************************************* 563 | ** Function name: mcp2515_read_id 564 | ** Descriptions: read can id 565 | *********************************************************************************************************/ 566 | void MCP_CAN::mcp2515_read_id( const INT8U mcp_addr, INT8U* ext, INT32U* id ) 567 | { 568 | INT8U tbufdata[4]; 569 | 570 | *ext = 0; 571 | *id = 0; 572 | 573 | mcp2515_readRegisterS( mcp_addr, tbufdata, 4 ); 574 | 575 | *id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5); 576 | 577 | if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) 578 | { 579 | /* extended id */ 580 | *id = (*id<<2) + (tbufdata[MCP_SIDL] & 0x03); 581 | *id = (*id<<8) + tbufdata[MCP_EID8]; 582 | *id = (*id<<8) + tbufdata[MCP_EID0]; 583 | *ext = 1; 584 | } 585 | } 586 | 587 | /********************************************************************************************************* 588 | ** Function name: mcp2515_write_canMsg 589 | ** Descriptions: write msg 590 | *********************************************************************************************************/ 591 | void MCP_CAN::mcp2515_write_canMsg( const INT8U buffer_sidh_addr) 592 | { 593 | INT8U mcp_addr; 594 | mcp_addr = buffer_sidh_addr; 595 | mcp2515_setRegisterS(mcp_addr+5, m_nDta, m_nDlc ); /* write data bytes */ 596 | if ( m_nRtr == 1) /* if RTR set bit in byte */ 597 | { 598 | m_nDlc |= MCP_RTR_MASK; 599 | } 600 | mcp2515_setRegister((mcp_addr+4), m_nDlc ); /* write the RTR and DLC */ 601 | mcp2515_write_id(mcp_addr, m_nExtFlg, m_nID ); /* write CAN id */ 602 | 603 | } 604 | 605 | /********************************************************************************************************* 606 | ** Function name: mcp2515_read_canMsg 607 | ** Descriptions: read message 608 | *********************************************************************************************************/ 609 | void MCP_CAN::mcp2515_read_canMsg( const INT8U buffer_sidh_addr) /* read can msg */ 610 | { 611 | INT8U mcp_addr, ctrl; 612 | 613 | mcp_addr = buffer_sidh_addr; 614 | 615 | mcp2515_read_id( mcp_addr, &m_nExtFlg,&m_nID ); 616 | 617 | ctrl = mcp2515_readRegister( mcp_addr-1 ); 618 | m_nDlc = mcp2515_readRegister( mcp_addr+4 ); 619 | 620 | if ((ctrl & 0x08)) { 621 | m_nRtr = 1; 622 | } 623 | else { 624 | m_nRtr = 0; 625 | } 626 | 627 | m_nDlc &= MCP_DLC_MASK; 628 | mcp2515_readRegisterS( mcp_addr+5, &(m_nDta[0]), m_nDlc ); 629 | } 630 | 631 | /********************************************************************************************************* 632 | ** Function name: sendMsg 633 | ** Descriptions: send message 634 | *********************************************************************************************************/ 635 | void MCP_CAN::mcp2515_start_transmit(const INT8U mcp_addr) /* start transmit */ 636 | { 637 | mcp2515_modifyRegister( mcp_addr-1 , MCP_TXB_TXREQ_M, MCP_TXB_TXREQ_M ); 638 | } 639 | 640 | /********************************************************************************************************* 641 | ** Function name: sendMsg 642 | ** Descriptions: send message 643 | *********************************************************************************************************/ 644 | INT8U MCP_CAN::mcp2515_getNextFreeTXBuf(INT8U *txbuf_n) /* get Next free txbuf */ 645 | { 646 | INT8U res, i, ctrlval; 647 | INT8U ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL }; 648 | 649 | res = MCP_ALLTXBUSY; 650 | *txbuf_n = 0x00; 651 | 652 | /* check all 3 TX-Buffers */ 653 | for (i=0; i 0){ 704 | #if DEBUG_MODE 705 | Serial.print("Enter setting mode fall\r\n"); 706 | #else 707 | delay(10); 708 | #endif 709 | return res; 710 | } 711 | 712 | if (num == 0){ 713 | mcp2515_write_id(MCP_RXM0SIDH, ext, ulData); 714 | 715 | } 716 | else if(num == 1){ 717 | mcp2515_write_id(MCP_RXM1SIDH, ext, ulData); 718 | } 719 | else res = MCP2515_FAIL; 720 | 721 | res = mcp2515_setCANCTRL_Mode(MODE_NORMAL); 722 | if(res > 0){ 723 | #if DEBUG_MODE 724 | Serial.print("Enter normal mode fall\r\n"); 725 | #else 726 | delay(10); 727 | #endif 728 | return res; 729 | } 730 | #if DEBUG_MODE 731 | Serial.print("set Mask success!!\r\n"); 732 | #else 733 | delay(10); 734 | #endif 735 | return res; 736 | } 737 | 738 | /********************************************************************************************************* 739 | ** Function name: init_Filt 740 | ** Descriptions: init canid filters 741 | *********************************************************************************************************/ 742 | INT8U MCP_CAN::init_Filt(INT8U num, INT8U ext, INT32U ulData) 743 | { 744 | INT8U res = MCP2515_OK; 745 | #if DEBUG_MODE 746 | Serial.print("Begin to set Filter!!\r\n"); 747 | #else 748 | delay(10); 749 | #endif 750 | res = mcp2515_setCANCTRL_Mode(MODE_CONFIG); 751 | if(res > 0) 752 | { 753 | #if DEBUG_MODE 754 | Serial.print("Enter setting mode fall\r\n"); 755 | #else 756 | delay(10); 757 | #endif 758 | return res; 759 | } 760 | 761 | switch( num ) 762 | { 763 | case 0: 764 | mcp2515_write_id(MCP_RXF0SIDH, ext, ulData); 765 | break; 766 | 767 | case 1: 768 | mcp2515_write_id(MCP_RXF1SIDH, ext, ulData); 769 | break; 770 | 771 | case 2: 772 | mcp2515_write_id(MCP_RXF2SIDH, ext, ulData); 773 | break; 774 | 775 | case 3: 776 | mcp2515_write_id(MCP_RXF3SIDH, ext, ulData); 777 | break; 778 | 779 | case 4: 780 | mcp2515_write_id(MCP_RXF4SIDH, ext, ulData); 781 | break; 782 | 783 | case 5: 784 | mcp2515_write_id(MCP_RXF5SIDH, ext, ulData); 785 | break; 786 | 787 | default: 788 | res = MCP2515_FAIL; 789 | } 790 | 791 | res = mcp2515_setCANCTRL_Mode(MODE_NORMAL); 792 | if(res > 0) 793 | { 794 | #if DEBUG_MODE 795 | Serial.print("Enter normal mode fall\r\nSet filter fail!!\r\n"); 796 | #else 797 | delay(10); 798 | #endif 799 | return res; 800 | } 801 | #if DEBUG_MODE 802 | Serial.print("set Filter success!!\r\n"); 803 | #else 804 | delay(10); 805 | #endif 806 | 807 | return res; 808 | } 809 | 810 | /********************************************************************************************************* 811 | ** Function name: setMsg 812 | ** Descriptions: set can message, such as dlc, id, dta[] and so on 813 | *********************************************************************************************************/ 814 | INT8U MCP_CAN::setMsg(INT32U id, INT8U ext, INT8U len, INT8U rtr, INT8U *pData) 815 | { 816 | int i = 0; 817 | m_nExtFlg = ext; 818 | m_nID = id; 819 | m_nDlc = len; 820 | m_nRtr = rtr; 821 | for(i = 0; i 28 | #include 29 | #include 30 | 31 | #ifndef INT32U 32 | #define INT32U unsigned long 33 | #endif 34 | 35 | #ifndef INT8U 36 | #define INT8U byte 37 | #endif 38 | 39 | // if print debug information 40 | #define DEBUG_MODE 0 41 | 42 | /* 43 | * Begin mt 44 | */ 45 | #define TIMEOUTVALUE 50 46 | #define MCP_SIDH 0 47 | #define MCP_SIDL 1 48 | #define MCP_EID8 2 49 | #define MCP_EID0 3 50 | 51 | #define MCP_TXB_EXIDE_M 0x08 /* In TXBnSIDL */ 52 | #define MCP_DLC_MASK 0x0F /* 4 LSBits */ 53 | #define MCP_RTR_MASK 0x40 /* (1<<6) Bit 6 */ 54 | 55 | #define MCP_RXB_RX_ANY 0x60 56 | #define MCP_RXB_RX_EXT 0x40 57 | #define MCP_RXB_RX_STD 0x20 58 | #define MCP_RXB_RX_STDEXT 0x00 59 | #define MCP_RXB_RX_MASK 0x60 60 | #define MCP_RXB_BUKT_MASK (1<<2) 61 | 62 | /* 63 | ** Bits in the TXBnCTRL registers. 64 | */ 65 | #define MCP_TXB_TXBUFE_M 0x80 66 | #define MCP_TXB_ABTF_M 0x40 67 | #define MCP_TXB_MLOA_M 0x20 68 | #define MCP_TXB_TXERR_M 0x10 69 | #define MCP_TXB_TXREQ_M 0x08 70 | #define MCP_TXB_TXIE_M 0x04 71 | #define MCP_TXB_TXP10_M 0x03 72 | 73 | #define MCP_TXB_RTR_M 0x40 /* In TXBnDLC */ 74 | #define MCP_RXB_IDE_M 0x08 /* In RXBnSIDL */ 75 | #define MCP_RXB_RTR_M 0x40 /* In RXBnDLC */ 76 | 77 | #define MCP_STAT_RXIF_MASK (0x03) 78 | #define MCP_STAT_RX0IF (1<<0) 79 | #define MCP_STAT_RX1IF (1<<1) 80 | 81 | #define MCP_EFLG_RX1OVR (1<<7) 82 | #define MCP_EFLG_RX0OVR (1<<6) 83 | #define MCP_EFLG_TXBO (1<<5) 84 | #define MCP_EFLG_TXEP (1<<4) 85 | #define MCP_EFLG_RXEP (1<<3) 86 | #define MCP_EFLG_TXWAR (1<<2) 87 | #define MCP_EFLG_RXWAR (1<<1) 88 | #define MCP_EFLG_EWARN (1<<0) 89 | #define MCP_EFLG_ERRORMASK (0xF8) /* 5 MS-Bits */ 90 | 91 | 92 | /* 93 | * Define MCP2515 register addresses 94 | */ 95 | 96 | #define MCP_RXF0SIDH 0x00 97 | #define MCP_RXF0SIDL 0x01 98 | #define MCP_RXF0EID8 0x02 99 | #define MCP_RXF0EID0 0x03 100 | #define MCP_RXF1SIDH 0x04 101 | #define MCP_RXF1SIDL 0x05 102 | #define MCP_RXF1EID8 0x06 103 | #define MCP_RXF1EID0 0x07 104 | #define MCP_RXF2SIDH 0x08 105 | #define MCP_RXF2SIDL 0x09 106 | #define MCP_RXF2EID8 0x0A 107 | #define MCP_RXF2EID0 0x0B 108 | #define MCP_CANSTAT 0x0E 109 | #define MCP_CANCTRL 0x0F 110 | #define MCP_RXF3SIDH 0x10 111 | #define MCP_RXF3SIDL 0x11 112 | #define MCP_RXF3EID8 0x12 113 | #define MCP_RXF3EID0 0x13 114 | #define MCP_RXF4SIDH 0x14 115 | #define MCP_RXF4SIDL 0x15 116 | #define MCP_RXF4EID8 0x16 117 | #define MCP_RXF4EID0 0x17 118 | #define MCP_RXF5SIDH 0x18 119 | #define MCP_RXF5SIDL 0x19 120 | #define MCP_RXF5EID8 0x1A 121 | #define MCP_RXF5EID0 0x1B 122 | #define MCP_TEC 0x1C 123 | #define MCP_REC 0x1D 124 | #define MCP_RXM0SIDH 0x20 125 | #define MCP_RXM0SIDL 0x21 126 | #define MCP_RXM0EID8 0x22 127 | #define MCP_RXM0EID0 0x23 128 | #define MCP_RXM1SIDH 0x24 129 | #define MCP_RXM1SIDL 0x25 130 | #define MCP_RXM1EID8 0x26 131 | #define MCP_RXM1EID0 0x27 132 | #define MCP_CNF3 0x28 133 | #define MCP_CNF2 0x29 134 | #define MCP_CNF1 0x2A 135 | #define MCP_CANINTE 0x2B 136 | #define MCP_CANINTF 0x2C 137 | #define MCP_EFLG 0x2D 138 | #define MCP_TXB0CTRL 0x30 139 | #define MCP_TXB1CTRL 0x40 140 | #define MCP_TXB2CTRL 0x50 141 | #define MCP_RXB0CTRL 0x60 142 | #define MCP_RXB0SIDH 0x61 143 | #define MCP_RXB1CTRL 0x70 144 | #define MCP_RXB1SIDH 0x71 145 | 146 | 147 | #define MCP_TX_INT 0x1C // Enable all transmit interrup ts 148 | #define MCP_TX01_INT 0x0C // Enable TXB0 and TXB1 interru pts 149 | #define MCP_RX_INT 0x03 // Enable receive interrupts 150 | #define MCP_NO_INT 0x00 // Disable all interrupts 151 | 152 | #define MCP_TX01_MASK 0x14 153 | #define MCP_TX_MASK 0x54 154 | 155 | /* 156 | * Define SPI Instruction Set 157 | */ 158 | 159 | #define MCP_WRITE 0x02 160 | 161 | #define MCP_READ 0x03 162 | 163 | #define MCP_BITMOD 0x05 164 | 165 | #define MCP_LOAD_TX0 0x40 166 | #define MCP_LOAD_TX1 0x42 167 | #define MCP_LOAD_TX2 0x44 168 | 169 | #define MCP_RTS_TX0 0x81 170 | #define MCP_RTS_TX1 0x82 171 | #define MCP_RTS_TX2 0x84 172 | #define MCP_RTS_ALL 0x87 173 | 174 | #define MCP_READ_RX0 0x90 175 | #define MCP_READ_RX1 0x94 176 | 177 | #define MCP_READ_STATUS 0xA0 178 | 179 | #define MCP_RX_STATUS 0xB0 180 | 181 | #define MCP_RESET 0xC0 182 | 183 | 184 | /* 185 | * CANCTRL Register Values 186 | */ 187 | 188 | #define MODE_NORMAL 0x00 189 | #define MODE_SLEEP 0x20 190 | #define MODE_LOOPBACK 0x40 191 | #define MODE_LISTENONLY 0x60 192 | #define MODE_CONFIG 0x80 193 | #define MODE_POWERUP 0xE0 194 | #define MODE_MASK 0xE0 195 | #define ABORT_TX 0x10 196 | #define MODE_ONESHOT 0x08 197 | #define CLKOUT_ENABLE 0x04 198 | #define CLKOUT_DISABLE 0x00 199 | #define CLKOUT_PS1 0x00 200 | #define CLKOUT_PS2 0x01 201 | #define CLKOUT_PS4 0x02 202 | #define CLKOUT_PS8 0x03 203 | 204 | 205 | /* 206 | * CNF1 Register Values 207 | */ 208 | 209 | #define SJW1 0x00 210 | #define SJW2 0x40 211 | #define SJW3 0x80 212 | #define SJW4 0xC0 213 | 214 | 215 | /* 216 | * CNF2 Register Values 217 | */ 218 | 219 | #define BTLMODE 0x80 220 | #define SAMPLE_1X 0x00 221 | #define SAMPLE_3X 0x40 222 | 223 | 224 | /* 225 | * CNF3 Register Values 226 | */ 227 | 228 | #define SOF_ENABLE 0x80 229 | #define SOF_DISABLE 0x00 230 | #define WAKFIL_ENABLE 0x40 231 | #define WAKFIL_DISABLE 0x00 232 | 233 | 234 | /* 235 | * CANINTF Register Bits 236 | */ 237 | 238 | #define MCP_RX0IF 0x01 239 | #define MCP_RX1IF 0x02 240 | #define MCP_TX0IF 0x04 241 | #define MCP_TX1IF 0x08 242 | #define MCP_TX2IF 0x10 243 | #define MCP_ERRIF 0x20 244 | #define MCP_WAKIF 0x40 245 | #define MCP_MERRF 0x80 246 | 247 | /* 248 | * clock 249 | */ 250 | #define MCP_16MHz 1 251 | #define MCP_8MHz 2 252 | 253 | /* 254 | * speed 16M 255 | */ 256 | #define MCP_16MHz_1000kBPS_CFG1 (0x00) 257 | #define MCP_16MHz_1000kBPS_CFG2 (0xD0) 258 | #define MCP_16MHz_1000kBPS_CFG3 (0x82) 259 | 260 | #define MCP_16MHz_500kBPS_CFG1 (0x00) 261 | #define MCP_16MHz_500kBPS_CFG2 (0xF0) 262 | #define MCP_16MHz_500kBPS_CFG3 (0x86) 263 | 264 | #define MCP_16MHz_250kBPS_CFG1 (0x41) 265 | #define MCP_16MHz_250kBPS_CFG2 (0xF1) 266 | #define MCP_16MHz_250kBPS_CFG3 (0x85) 267 | 268 | #define MCP_16MHz_200kBPS_CFG1 (0x01) 269 | #define MCP_16MHz_200kBPS_CFG2 (0xFA) 270 | #define MCP_16MHz_200kBPS_CFG3 (0x87) 271 | 272 | #define MCP_16MHz_125kBPS_CFG1 (0x03) 273 | #define MCP_16MHz_125kBPS_CFG2 (0xF0) 274 | #define MCP_16MHz_125kBPS_CFG3 (0x86) 275 | 276 | #define MCP_16MHz_100kBPS_CFG1 (0x03) 277 | #define MCP_16MHz_100kBPS_CFG2 (0xFA) 278 | #define MCP_16MHz_100kBPS_CFG3 (0x87) 279 | 280 | /* 281 | #define MCP_16MHz_100kBPS_CFG1 (0x03) 282 | #define MCP_16MHz_100kBPS_CFG2 (0xBA) 283 | #define MCP_16MHz_100kBPS_CFG3 (0x07) 284 | */ 285 | 286 | #define MCP_16MHz_95kBPS_CFG1 (0x03) 287 | #define MCP_16MHz_95kBPS_CFG2 (0xAD) 288 | #define MCP_16MHz_95kBPS_CFG3 (0x07) 289 | 290 | #define MCP_16MHz_83k3BPS_CFG1 (0x03) 291 | #define MCP_16MHz_83k3BPS_CFG2 (0xBE) 292 | #define MCP_16MHz_83k3BPS_CFG3 (0x07) 293 | 294 | #define MCP_16MHz_80kBPS_CFG1 (0x03) 295 | #define MCP_16MHz_80kBPS_CFG2 (0xFF) 296 | #define MCP_16MHz_80kBPS_CFG3 (0x87) 297 | 298 | #define MCP_16MHz_50kBPS_CFG1 (0x07) 299 | #define MCP_16MHz_50kBPS_CFG2 (0xFA) 300 | #define MCP_16MHz_50kBPS_CFG3 (0x87) 301 | 302 | #define MCP_16MHz_40kBPS_CFG1 (0x07) 303 | #define MCP_16MHz_40kBPS_CFG2 (0xFF) 304 | #define MCP_16MHz_40kBPS_CFG3 (0x87) 305 | 306 | #define MCP_16MHz_33kBPS_CFG1 (0x09) 307 | #define MCP_16MHz_33kBPS_CFG2 (0xBE) 308 | #define MCP_16MHz_33kBPS_CFG3 (0x07) 309 | 310 | #define MCP_16MHz_31k25BPS_CFG1 (0x0F) 311 | #define MCP_16MHz_31k25BPS_CFG2 (0xF1) 312 | #define MCP_16MHz_31k25BPS_CFG3 (0x85) 313 | 314 | #define MCP_16MHz_20kBPS_CFG1 (0x0F) 315 | #define MCP_16MHz_20kBPS_CFG2 (0xFF) 316 | #define MCP_16MHz_20kBPS_CFG3 (0x87) 317 | 318 | #define MCP_16MHz_10kBPS_CFG1 (0x1F) 319 | #define MCP_16MHz_10kBPS_CFG2 (0xFF) 320 | #define MCP_16MHz_10kBPS_CFG3 (0x87) 321 | 322 | #define MCP_16MHz_5kBPS_CFG1 (0x3F) 323 | #define MCP_16MHz_5kBPS_CFG2 (0xFF) 324 | #define MCP_16MHz_5kBPS_CFG3 (0x87) 325 | 326 | /* 327 | * speed 8M 328 | */ 329 | #define MCP_8MHz_1000kBPS_CFG1 (0x00) 330 | #define MCP_8MHz_1000kBPS_CFG2 (0x80) 331 | #define MCP_8MHz_1000kBPS_CFG3 (0x00) 332 | 333 | #define MCP_8MHz_500kBPS_CFG1 (0x00) 334 | #define MCP_8MHz_500kBPS_CFG2 (0x90) 335 | #define MCP_8MHz_500kBPS_CFG3 (0x02) 336 | 337 | #define MCP_8MHz_250kBPS_CFG1 (0x00) 338 | #define MCP_8MHz_250kBPS_CFG2 (0xb1) 339 | #define MCP_8MHz_250kBPS_CFG3 (0x05) 340 | 341 | #define MCP_8MHz_200kBPS_CFG1 (0x00) 342 | #define MCP_8MHz_200kBPS_CFG2 (0xb4) 343 | #define MCP_8MHz_200kBPS_CFG3 (0x06) 344 | 345 | #define MCP_8MHz_125kBPS_CFG1 (0x01) 346 | #define MCP_8MHz_125kBPS_CFG2 (0xb1) 347 | #define MCP_8MHz_125kBPS_CFG3 (0x05) 348 | 349 | #define MCP_8MHz_100kBPS_CFG1 (0x01) 350 | #define MCP_8MHz_100kBPS_CFG2 (0xb4) 351 | #define MCP_8MHz_100kBPS_CFG3 (0x06) 352 | 353 | #define MCP_8MHz_95kBPS_CFG1 (0x01) 354 | #define MCP_8MHz_95kBPS_CFG2 (0xAD) 355 | #define MCP_8MHz_95kBPS_CFG3 (0x07) 356 | 357 | #define MCP_8MHz_83k3BPS_CFG1 (0x01) 358 | #define MCP_8MHz_83k3BPS_CFG2 (0xbe) 359 | #define MCP_8MHz_83k3BPS_CFG3 (0x07) 360 | 361 | #define MCP_8MHz_80kBPS_CFG1 (0x01) 362 | #define MCP_8MHz_80kBPS_CFG2 (0xbf) 363 | #define MCP_8MHz_80kBPS_CFG3 (0x07) 364 | 365 | #define MCP_8MHz_50kBPS_CFG1 (0x03) 366 | #define MCP_8MHz_50kBPS_CFG2 (0xb4) 367 | #define MCP_8MHz_50kBPS_CFG3 (0x06) 368 | 369 | #define MCP_8MHz_40kBPS_CFG1 (0x03) 370 | #define MCP_8MHz_40kBPS_CFG2 (0xbf) 371 | #define MCP_8MHz_40kBPS_CFG3 (0x07) 372 | 373 | #define MCP_8MHz_33kBPS_CFG1 (0x04) 374 | #define MCP_8MHz_33kBPS_CFG2 (0xBE) 375 | #define MCP_8MHz_33kBPS_CFG3 (0x07) 376 | 377 | #define MCP_8MHz_31k25BPS_CFG1 (0x07) 378 | #define MCP_8MHz_31k25BPS_CFG2 (0xa4) 379 | #define MCP_8MHz_31k25BPS_CFG3 (0x04) 380 | 381 | #define MCP_8MHz_20kBPS_CFG1 (0x07) 382 | #define MCP_8MHz_20kBPS_CFG2 (0xbf) 383 | #define MCP_8MHz_20kBPS_CFG3 (0x07) 384 | 385 | #define MCP_8MHz_10kBPS_CFG1 (0x0f) 386 | #define MCP_8MHz_10kBPS_CFG2 (0xbf) 387 | #define MCP_8MHz_10kBPS_CFG3 (0x07) 388 | 389 | #define MCP_8MHz_5kBPS_CFG1 (0x1f) 390 | #define MCP_8MHz_5kBPS_CFG2 (0xbf) 391 | #define MCP_8MHz_5kBPS_CFG3 (0x07) 392 | 393 | 394 | 395 | #define MCPDEBUG (0) 396 | #define MCPDEBUG_TXBUF (0) 397 | #define MCP_N_TXBUFFERS (3) 398 | 399 | #define MCP_RXBUF_0 (MCP_RXB0SIDH) 400 | #define MCP_RXBUF_1 (MCP_RXB1SIDH) 401 | 402 | //#define SPICS 10 403 | #define MCP2515_SELECT() digitalWrite(SPICS, LOW) 404 | #define MCP2515_UNSELECT() digitalWrite(SPICS, HIGH) 405 | 406 | #define MCP2515_OK (0) 407 | #define MCP2515_FAIL (1) 408 | #define MCP_ALLTXBUSY (2) 409 | 410 | #define CANDEBUG 1 411 | 412 | #define CANUSELOOP 0 413 | 414 | #define CANSENDTIMEOUT (200) /* milliseconds */ 415 | 416 | /* 417 | * initial value of gCANAutoProcess 418 | */ 419 | #define CANAUTOPROCESS (1) 420 | #define CANAUTOON (1) 421 | #define CANAUTOOFF (0) 422 | 423 | #define CAN_STDID (0) 424 | #define CAN_EXTID (1) 425 | 426 | #define CANDEFAULTIDENT (0x55CC) 427 | #define CANDEFAULTIDENTEXT (CAN_EXTID) 428 | 429 | #define CAN_5KBPS 1 430 | #define CAN_10KBPS 2 431 | #define CAN_20KBPS 3 432 | #define CAN_31K25BPS 4 433 | #define CAN_33KBPS 5 434 | #define CAN_40KBPS 6 435 | #define CAN_50KBPS 7 436 | #define CAN_80KBPS 8 437 | #define CAN_83K3BPS 9 438 | #define CAN_95KBPS 10 439 | #define CAN_100KBPS 11 440 | #define CAN_125KBPS 12 441 | #define CAN_200KBPS 13 442 | #define CAN_250KBPS 14 443 | #define CAN_500KBPS 15 444 | #define CAN_1000KBPS 16 445 | 446 | #define CAN_OK (0) 447 | #define CAN_FAILINIT (1) 448 | #define CAN_FAILTX (2) 449 | #define CAN_MSGAVAIL (3) 450 | #define CAN_NOMSG (4) 451 | #define CAN_CTRLERROR (5) 452 | #define CAN_GETTXBFTIMEOUT (6) 453 | #define CAN_SENDMSGTIMEOUT (7) 454 | #define CAN_FAIL (0xff) 455 | 456 | #define CAN_MAX_CHAR_IN_MESSAGE (8) 457 | 458 | #endif 459 | /********************************************************************************************************* 460 | END FILE 461 | *********************************************************************************************************/ -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Hello 2 | Readmenow 3 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /docs/overview.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latonita/arduino-canbus-monitor/43de5bef55a37f0de6d7817247741222dae6ce6d/docs/overview.md -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | # must be unique in a given SonarQube instance 2 | sonar.projectKey=my:arduino-canbus-monitor 3 | # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. 4 | sonar.projectName=arduino-canbus-monitor 5 | sonar.projectVersion=1.0 6 | 7 | # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. 8 | # Since SonarQube 4.2, this property is optional if sonar.modules is set. 9 | # If not set, SonarQube starts looking for source code from the directory containing 10 | # the sonar-project.properties file. 11 | sonar.sources=./arduino-canbus-monitor 12 | 13 | # Encoding of the source code. Default is default system encoding 14 | #sonar.sourceEncoding=UTF-8 --------------------------------------------------------------------------------