![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
Sample code for Arduino CAN
Dependencies: mbed
Revision 0:6ed8574c6258, committed 2016-02-29
- Comitter:
- jedh
- Date:
- Mon Feb 29 19:33:12 2016 +0000
- Commit message:
- Arduino CAN
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arduinoCAN.cpp Mon Feb 29 19:33:12 2016 +0000 @@ -0,0 +1,897 @@ +/* + * Copyright (C) 2009 Libelium Comunicaciones Distribuidas S.L. + * http://www.libelium.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Version: 0.3 + * Design: David Gascon + * Implementation: Luis Antonio Martin & Ahmad Saad + */ + +#include "Arduino.h" +#include "arduinoCAN.h" +#include "../SPI/SPI.h" +#include "../arduino-api/arduinoMultiprotocol.h" +#include "../arduino-api/arduinoUtils.h" + + + +#define DEBUGMODE 0 +/*********************************************************************** + * Constructors + ***********************************************************************/ + +CAN::CAN(void){} + + +/*********************************************************************** + * PUBLIC METHODS + ***********************************************************************/ + +//!************************************************************* +//! Name: ON() +//! Description: Initialization MCP2515 +//! Param : void +//! Returns: "1" if no error, "0" if error +//!************************************************************* +bool CAN::begin(uint16_t speed) +{ + + #if (DEBUGMODE ==1 ) + Serial.println("-- Constructor Can(uint16_t speed) --"); + #endif + + // Initialize in Socket1 + Utils.setONSocket0(); + Utils.setMUXSocket0(); + Utils.unsetCSSocket0(); + + //Initialization SPI + SPI.begin(); + SPI.detachInterrupt(); + SPI.setBitOrder(MSBFIRST); + // both mode 0 & 3 should work + SPI.setDataMode(SPI_MODE0); + + //Set the SPI frequency + SPI.setClockDivider(SPI_CLOCK_DIV128); + + #if (DEBUGMODE==1) + Serial.println("SPI configured"); + #endif + + + //Software resets MCP2515 + reset(); + delay(10); + + //After the reset enters configuration mode + + //Choose the rate of CAN-bus + switch(speed){ + + case 1000: + #if (DEBUGMODE==1) + Serial.println("Speed=1Mbps"); + #endif + Utils.setCSSocket0(); + SPI.transfer(SPI_WRITE); + SPI.transfer(CNF3); + SPI.transfer((1<<PHSEG21)); + SPI.transfer((1<<BTLMODE)|(1<<PHSEG11)); + Utils.unsetCSSocket0(); + break; + + case 500: + #if (DEBUGMODE==1) + Serial.println("Speed=500kps"); + #endif + Utils.setCSSocket0(); + SPI.transfer(SPI_WRITE); + SPI.transfer(CNF3); + SPI.transfer((1<<PHSEG21)); + SPI.transfer((1<<BTLMODE)|(1<<PHSEG11)); + SPI.transfer((1<<BRP0)); + Utils.unsetCSSocket0(); + break; + + case 250: + #if (DEBUGMODE==1) + Serial.println("Speed=250kps"); + #endif + Utils.setCSSocket0(); + SPI.transfer(SPI_WRITE); + SPI.transfer(CNF3); + SPI.transfer((1<<PHSEG20)|(1<<PHSEG22)); + SPI.transfer((1<<BTLMODE)|(1<<PHSEG12)|(1<<PHSEG11)|(1<<PHSEG10)); + SPI.transfer((1<<BRP0)); + Utils.unsetCSSocket0(); + break; + + default: + #if (DEBUGMODE==1) + Serial.println("The rate requested is unavailable, is set to 125 Kbit/s by default"); + #endif + Utils.setCSSocket0(); + SPI.transfer(SPI_WRITE); + SPI.transfer(CNF3); + SPI.transfer((1<<PHSEG21)); + SPI.transfer((1<<BTLMODE)|(1<<PHSEG11)); + SPI.transfer((1<<BRP2)|(1<<BRP1)|(1<<BRP0)); + Utils.unsetCSSocket0(); + break; + + } + + //Enable interrupts the Rx Buffer + writeRegister(CANINTE,(1<<RX1IE)|(1<<RX0IE)); + + //Filters and masks + //Bufer 0: All the messages and Rollover + writeRegister(RXB0CTRL,(1<<RXM1)|(1<<RXM0)|(1<<BUKT)); + + //Bufer 1: All the messages + writeRegister(RXB1CTRL,(1<<RXM1)|(1<<RXM0)); + + //All bits of the mask reception delete + writeRegister( RXM0SIDH, 0 ); + writeRegister( RXM0SIDL, 0 ); + writeRegister( RXM0EID8, 0 ); + writeRegister( RXM0EID0, 0 ); + writeRegister( RXM1SIDH, 0 ); + writeRegister( RXM1SIDL, 0 ); + writeRegister( RXM1EID8, 0 ); + writeRegister( RXM1EID0, 0 ); + + //Disable pins RXnBF pins (high impedance state) + writeRegister( BFPCTRL, 0 ); + + //Set normal mode + setMode(NORMAL_MODE); + + //Test its correct mode + /* + if (read_register(CANSTAT) != 0) { + Serial.println("Failed to initialize the MCP2515, normal mode not activated"); + return false; + }*/ + + #if (DEBUGMODE==1) + Serial.println("-- End Constructor Can(uint16_t speed) --"); + Serial.println(""); + #endif + + return 1; +} + +//!************************************************************* +//! Name: getMessage() +//! Description: Take the CAN message +//! Param : messageCAN *rec_msje: pointer to reception buffer +//! Returns: "1" if no error, "0" if error +//!************************************************************* +char CAN::getMessage(messageCAN *rec_msje) +{ + //Bought that buffer is the message + char status = readStatus(SPI_RX_STATUS); + char addr; + static uint8_t previoSerialuffer; + + /* + if (bit_is_set(status,6)) { + //If the message is in the Buffer 1 + addr = SPI_READ_RX; + } + else if (bit_is_set(status,7)) + { + //If the message is in the Buffer 2 + addr = SPI_READ_RX | 0x04; + } + else { + // Error, the message is not available + return 0; + }*/ + + if ( (((status & 0b11000000)>>6)&0b00000011) >2 ) + { + addr=SPI_READ_RX | (previoSerialuffer++ & 0x01)<<2; + #if (DEBUGMODE==1) + Serial.println("Data in buffer available"); + #endif + } + else if (bit_is_set(status,6)) + { + addr = SPI_READ_RX; + #if (DEBUGMODE==1) + Serial.println("Data in buffer 0"); + #endif + } + else if (bit_is_set(status,7)) + { + addr = SPI_READ_RX | 0x04; + #if (DEBUGMODE==1) + Serial.println("Data in buffer 1"); + #endif + } + else { + // Error: no message available + #if (DEBUGMODE==1) + Serial.println("No messages"); + #endif + + return 0; + } + + Utils.setCSSocket0(); + SPI.transfer(addr); + + //Read id + rec_msje->id = (unsigned int) SPI.transfer(0xff) << 3; //Read the top + rec_msje->id |= SPI.transfer(0xff) >> 5; //Read the lower + + //Return the Extended ID + SPI.transfer(0xff); + SPI.transfer(0xff); + + //Read DLC + char length = SPI.transfer(0xff) & 0x0f; + + rec_msje->header.length = length; + rec_msje->header.rtr = (bit_is_set(status, 3)) ? 1 : 0; + + //Read data + for (char i=0;i<length;i++) { + rec_msje->data[i] = SPI.transfer(0xFF); + } + + Utils.unsetCSSocket0(); + + //Delete the interruptions flags + if (bit_is_set(status, 6)) { + bitModify(CANINTF, (1<<RX0IF), 0); + } + else { + bitModify(CANINTF, (1<<RX1IF), 0); + } + + return status; +} + + + +//!************************************************************* +//! Name: sendMessage() +//! Description: Send the CAN message +//! Param: messageCAN *send_msje: pointer to transmission buffer +//! Returns: "1" if no error, "0" if error +//!************************************************************* +char CAN::sendMessage(messageCAN *send_msje) +{ + char status = readStatus(SPI_READ_STATUS); + + /* Status char: + * + * Bit Funcion + * 2 TXB0CNTRL.TXREQ + * 4 TXB1CNTRL.TXREQ + * 6 TXB2CNTRL.TXREQ + */ + + char address; + + if (bit_is_clear(status, 2)) { + address = 0x00; + } else if (bit_is_clear(status, 4)) { + address = 0x02; + } else if (bit_is_clear(status, 6)) { + address = 0x04; + } else { + //All buffers are used can not send messages (returns 0) + return 0; + } + + Utils.setCSSocket0(); + SPI.transfer(SPI_WRITE_TX | address); + //First, send the top ID10....ID3 + SPI.transfer(send_msje->id >> 3); + //After sending the lower ID2....ID0 + SPI.transfer(send_msje->id << 5); + + //As we will not use the Extended ID you set it to 0 + SPI.transfer(0); + SPI.transfer(0); + + char length = send_msje->header.length & 0x0F; + + if (send_msje->header.rtr) { + SPI.transfer((1<<RTR) | length); + } else { + //Send the message length + SPI.transfer(length); + //Send data + for (char i=0;i<length;i++) { + SPI.transfer(send_msje->data[i]); + } + } + + Utils.unsetCSSocket0(); + + //Send message + Utils.setCSSocket0(); + address = (address == 0) ? 1 : address; + SPI.transfer(SPI_RTS | address); + Utils.unsetCSSocket0(); + + return address; +} + + +//!************************************************************* +//! Name: printMessage() +//! Description: CAN message print out the serial port +//! Param : messageCAN *msje: pointer to the message +//! Returns: "1" if no error, "0" if error +//!************************************************************* +void CAN::printMessage(messageCAN *msje) +{ + Serial.print(" id: "); + Serial.print(messageRx.id,HEX); + Serial.print(" rtr: "); + Serial.print(messageRx.header.rtr,HEX); + Serial.print(" => "); + + if (!msje->header.rtr) { + //Data + Serial.print(" data: "); + Serial.print(messageRx.data[0],HEX); Serial.print(","); + Serial.print(messageRx.data[1],HEX); Serial.print(","); + Serial.print(messageRx.data[2],HEX); Serial.print(","); + Serial.print(messageRx.data[3],HEX); Serial.print(","); + Serial.print(messageRx.data[4],HEX); Serial.print(","); + Serial.print(messageRx.data[5],HEX); Serial.print(","); + Serial.print(messageRx.data[6],HEX); Serial.print(","); + Serial.println(messageRx.data[7],HEX); + } +} + + +//!************************************************************* +//! Name: setMode() +//! Description: Configure the MCP2515 +//! Param : uint8_t mode: The work mode +//! Returns: void +//!************************************************************* +void CAN::setMode(uint8_t mode) +{ + uint8_t mode_register = 0; + + if (mode == LISTEN_ONLY_MODE) { + mode_register = (0<<REQOP2)|(1<<REQOP1)|(1<<REQOP0); + } + else if (mode == LOOPBACK_MODE) { + mode_register = (0<<REQOP2)|(1<<REQOP1)|(0<<REQOP0); + } + else if (mode == SLEEP_MODE) { + mode_register = (0<<REQOP2)|(0<<REQOP1)|(1<<REQOP0); + } + else if (mode == NORMAL_MODE) { + mode_register = (0<<REQOP2)|(0<<REQOP1)|(0<<REQOP0); + } + + //Set the new mode + bitModify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), mode_register); + + //Wait until the mode has been changed + while ((readRegister(CANSTAT) & 0xe0) != mode_register) { } +} + + +//!************************************************************* +//! Name: messageAvailable() +//! Description: Check if there is any message +//! Param : void +//! Returns: 1 if available, 0 if not. +//!************************************************************* +uint8_t CAN::messageAvailable(void) +{ + char status = readStatus(SPI_RX_STATUS); + + if ( (((status & 0b11000000)>>6)&0b00000011) >2 ) + { + return 1; + } else if (bit_is_set(status,6)) { + return 1; + } else if (bit_is_set(status,7)) { + return 1; + } else { + return 0; + + #if (DEBUGMODE==1) + Serial.println("No data available"); + #endif + } +} + +//********************************************************************** +// Standars PIDs +//********************************************************************** + + +//!************************************************************* +//! Name: getEngineLoad() +//! Description: Calculated engine load value +//! Param : void +//! Returns: unsigned int: engine load value (0-100) +//!************************************************************* +unsigned int CAN::getEngineLoad() +{ + unsigned int data; + + CiARequest(CALC_ENGINE_LOAD); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3] * 100) / 255; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; +} + + +//!************************************************************* +//! Name: getEngineCoolantTemp() +//! Description: Engine coolant temperature +//! Param : void +//! Returns: Engine coolant temperature(-40 - 215) +//!************************************************************* +unsigned int CAN::getEngineCoolantTemp() +{ + unsigned int data; + + CiARequest(ENGINE_COOLANT_TEMP); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3] - 40); + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; +} + + +//!************************************************************* +//! Name: getFuelPressure() +//! Description: Fuel pressure +//! Param : void +//! Returns: unsigned int: Fuel pressure (0 - 765 Kpa) +//!************************************************************* +unsigned int CAN::getFuelPressure() +{ + unsigned int data; + + CiARequest(FUEL_PRESSURE); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3] * 3) ; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; +} + + +//!************************************************************* +//! Name: getIntakeMAPressure() +//! Description: Intake manifold absolute pressure +//! Param : void +//! Returns: unsigned int: absolute pressure (0 - 255 Kpa) +//!************************************************************* +unsigned int CAN::getIntakeMAPressure() +{ + unsigned int data; + + CiARequest(INTAKE_M_A_PRESSURE); + + if (messageRx.id==ID_RESPONSE) { + data = messageRx.data[3]; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; + + +} + + +//!************************************************************* +//! Name: getEngineRPM() +//! Description: Engine RPM +//! Param : void +//! Returns: unsigned int: Engine RPM (0 - 16,383 RPM) +//!************************************************************* +unsigned int CAN::getEngineRPM() +{ + + unsigned int data; + + CiARequest(ENGINE_RPM); + + if (messageRx.id==ID_RESPONSE) { + data = (uint16_t(messageRx.data[3]*256) + messageRx.data[4])/4; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; +} + + +//!************************************************************* +//! Name: getVehicleSpeed() +//! Description: Vehicle speed +//! Param : void +//! Returns: unsigned int: Vehicle speed (0 - 255) +//!************************************************************* +unsigned int CAN::getVehicleSpeed() +{ + unsigned int data; + + CiARequest(VEHICLE_SPEED); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3]); + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; + +} + + +//!************************************************************* +//! Name: getTimingAdvance() +//! Description: Timing advance +//! Param : void +//! Returns: unsigned int: Time (-64 - 63.5) +//!************************************************************* +unsigned int CAN::getTimingAdvance() +{ + unsigned int data; + + CiARequest(TIMING_ADVANCE); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3] / 2- 64); + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; +} + +//!************************************************************* +//! Name: getIntankeAirTemp() +//! Description: Intake air temperature +//! Param : void +//! Returns: unsigned int: Intake air temperature(-40 - 215) +//!************************************************************* +unsigned int CAN::getIntankeAirTemp() +{ + unsigned int data; + + CiARequest(INTAKE_AIR_TEMP); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3] - 40); + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; +} + + +//!************************************************************* +//! Name: getMAFairFlowRate() +//! Description: MAF air flow rate +//! Param : void +//! Returns: unsigned int: air flow rate (0 - 655.35 g/s) +//!************************************************************* +unsigned int CAN::getMAFairFlowRate() +{ + unsigned int data; + + CiARequest(MAF_AIR_FLOW_RATE); + + if (messageRx.id==ID_RESPONSE) { + data = ( uint16_t(messageRx.data[3] * 256) + messageRx.data[4]) / 100; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; + +} + + +//!************************************************************* +//! Name: getThrottlePosition() +//! Description: Throttle position +//! Param : void +//! Returns: unsigned int: Throttle position (0 - 100%) +//!************************************************************* +unsigned int CAN::getThrottlePosition() +{ + unsigned int data; + + CiARequest(THROTTLE_POSITION); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3] * 100) / 255; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; + + +} + + +//!************************************************************* +//! Name: getFuelLevel() +//! Description: Fuel Level Input +//! Param : void +//! Returns: unsigned int: Fuel Level Input (0 - 100%) +//!************************************************************* +unsigned int CAN::getFuelLevel() +{ + unsigned int data; + + CiARequest(FUEL_LEVEL); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3] * 100) / 255; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; + +} + + +//!************************************************************* +//! Name: getBarometricPressure() +//! Description: Barometric pressure +//! Param : void +//! Returns: unsigned int: Barometric pressure (0 - 255 Kpa) +//!************************************************************* +unsigned int CAN::getBarometricPressure() +{ + unsigned int data; + + CiARequest(BAROMETRIC_PRESSURE); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t(messageRx.data[3]); + + #if (DEBUGMODE == 1) + printMessage(&messageRx); + #endif + } + + return data; +} + + +//!************************************************************* +//! Name: getEngineFuelRate() +//! Description: Engine fuel rate +//! Param : void +//! Returns: unsigned int: Engine fuel rate (0 - 3212 L/h) +//!************************************************************* +unsigned int CAN::getEngineFuelRate() +{ + unsigned int data; + + CiARequest(ENGINE_FUEL_RATE); + + if (messageRx.id==ID_RESPONSE) { + data = uint16_t((messageRx.data[3] * 256) + messageRx.data[4]) * 0.05; + + #if (DEBUGMODE==1) + printMessage(&messageRx); + #endif + } + + return data; + +} + + +/*********************************************************************** + CAN in Automation (CiA) + ***********************************************************************/ + +//Request information through OBD +void CAN::CiARequest(uint8_t PID) +{ + messageTx.id = ID_QUERY; + messageTx.header.rtr = 0; + messageTx.header.length = 8; + messageTx.data[0]= 0x02; + messageTx.data[1]= 0x01; + messageTx.data[2]= PID; + + + sendMessage(&messageTx); + delay(5); + + if (messageAvailable()) { + //Read the message buffers + getMessage(&messageRx); + } + +} + + +/*********************************************************************** + * PRIVATE METHODS + ***********************************************************************/ + +//Write a MCP2515 register +void CAN::writeRegister( char direction, char data ) +{ + //CS low to select the MCP2515 + Utils.setCSSocket0(); + + SPI.transfer(SPI_WRITE); + SPI.transfer(direction); + SPI.transfer(data); + + //CS line again to release + Utils.unsetCSSocket0(); +} + + +//********************************************************************** + +//Read a MCP2515 register +char CAN::readRegister(char direction) +{ + char data; + + //CS low to select the MCP2515 + Utils.setCSSocket0(); + + SPI.transfer(SPI_READ); + SPI.transfer(direction); + //Read data SPI + data = SPI.transfer(0xff); + + //CS line again to release + Utils.unsetCSSocket0(); + + return data; +} + + +//*********************************************************************** + +//Modify a bit of the MCP2515 registers +void CAN::bitModify(char direction, char mask, char data) +{ + //CS low to select the MCP2515 + Utils.setCSSocket0(); + + SPI.transfer(SPI_BIT_MODIFY); + SPI.transfer(direction); + SPI.transfer(mask); + SPI.transfer(data); + + //CS line again to release + Utils.unsetCSSocket0(); +} + + +//*********************************************************************** + +//Check the status of the MCP2515 registers (SPI_RX_STATUS / SPI_READ_STATUS) +char CAN::readStatus(char type) +{ + char data; + + //CS low to select the MCP2515 + Utils.setCSSocket0(); + + SPI.transfer(type); + //Read data SPI + data = SPI.transfer(0xFF); + + //CS line again to release + Utils.unsetCSSocket0(); + + return data; +} + + +//*********************************************************************** + +//Check if the buffers are empty +bool CAN::checkFreeBuffer(void) +{ + char status = readStatus(SPI_READ_STATUS); + + + if ((status & 0x54) == 0x54) + { + //All buffers used + return false; + } + + return true; +} + + +//*********************************************************************** + +//Reset MCP2515 +void CAN::reset(void) +{ + //CS low to select the MCP2515 + Utils.setCSSocket0(); + + SPI.transfer(SPI_RESET); + //CS line again to release + Utils.unsetCSSocket0(); + + + //Wait a bit to be stabilized after the reset MCP2515 + delay(10); + + #if (DEBUGMODE==1) + Serial.println("The MCP2515 has been successfully reset, configuration mode activated"); + #endif +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arduinoCAN.h Mon Feb 29 19:33:12 2016 +0000 @@ -0,0 +1,501 @@ +/*! \file CAN.h + \brief Library for managing CAN-bus modules + + Copyright (C) 2011 Libelium Comunicaciones Distribuidas S.L. + http://www.libelium.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + Version: 0.3 + Design: David Gascón + Implementation: Luis Antonio Martín Nuez + + */ + +/*! \def WaspCAN_h + \brief The library flag + */ + +#ifndef ARDUINOCAN_h +#define ARDUINOCAN_h + + +/****************************************************************************** + * Includes + ******************************************************************************/ + + + +/****************************************************************************** + * Definitions & Declarations + ******************************************************************************/ + +//CAN-bus connection pins + +#define CAN_CS 6 +#define CAN_INT 4 + +//MCP2515 Opcodes + +#define SPI_RESET 0xC0 +#define SPI_READ 0x03 +#define SPI_READ_RX 0x90 +#define SPI_WRITE 0x02 +#define SPI_WRITE_TX 0x40 +#define SPI_RTS 0x80 +#define SPI_READ_STATUS 0xA0 +#define SPI_RX_STATUS 0xB0 +#define SPI_BIT_MODIFY 0x05 + +#define LISTEN_ONLY_MODE 0x01 +#define LOOPBACK_MODE 0x02 +#define SLEEP_MODE 0x03 +#define NORMAL_MODE 0x04 + +/**************************************************************************** + MCP2515 REGISTERS + ****************************************************************************/ + +//Message acceptance filters registers - Buffer 0 + +#define RXF0SIDH 0x00 +#define RXF0SIDL 0x01 +#define RXF0EID8 0x02 +#define RXF0EID0 0x03 +#define RXF1SIDH 0x04 +#define RXF1SIDL 0x05 +#define RXF1EID8 0x06 +#define RXF1EID0 0x07 +#define RXF2SIDH 0x08 +#define RXF2SIDL 0x09 +#define RXF2EID8 0x0A +#define RXF2EID0 0x0B + +//Digital outputs/inputs registers + +#define BFPCTRL 0x0C +#define TXRTSCTRL 0x0D + +//CAN-bus control and status registers + +#define CANSTAT 0x0E +#define CANCTRL 0x0F + +//Message acceptance filters registerts - Buffer 1 + +#define RXF3SIDH 0x10 +#define RXF3SIDL 0x11 +#define RXF3EID8 0x12 +#define RXF3EID0 0x13 +#define RXF4SIDH 0x14 +#define RXF4SIDL 0x15 +#define RXF4EID8 0x16 +#define RXF4EID0 0x17 +#define RXF5SIDH 0x18 +#define RXF5SIDL 0x19 +#define RXF5EID8 0x1A +#define RXF5EID0 0x1B + +//Error counters registers + +#define TEC 0x1C +#define REC 0x1D + +//Message acceptance masks registers + +#define RXM0SIDH 0x20 +#define RXM0SIDL 0x21 +#define RXM0EID8 0x22 +#define RXM0EID0 0x23 +#define RXM1SIDH 0x24 +#define RXM1SIDL 0x25 +#define RXM1EID8 0x26 +#define RXM1EID0 0x27 + +//Bit timing registers + +#define CNF3 0x28 +#define CNF2 0x29 +#define CNF1 0x2A + +//Interrups registers + +#define CANINTE 0x2B +#define CANINTF 0x2C + +//Error flags registers + +#define EFLG 0x2D + +//Message transmission registers - buffer --> 0 + +#define TXB0CTRL 0x30 +#define TXB0SIDH 0x31 +#define TXB0SIDL 0x32 +#define TXB0EID8 0x33 +#define TXB0EID0 0x34 +#define TXB0DLC 0x35 +#define TXB0D0 0x36 +#define TXB0D1 0x37 +#define TXB0D2 0x38 +#define TXB0D3 0x39 +#define TXB0D4 0x3A +#define TXB0D5 0x3B +#define TXB0D6 0x3C +#define TXB0D7 0x3D + +//Message transmission registers - buffer --> 1 + +#define TXB1CTRL 0x40 +#define TXB1SIDH 0x41 +#define TXB1SIDL 0x42 +#define TXB1EID8 0x43 +#define TXB1EID0 0x44 +#define TXB1DLC 0x45 +#define TXB1D0 0x46 +#define TXB1D1 0x47 +#define TXB1D2 0x48 +#define TXB1D3 0x49 +#define TXB1D4 0x4A +#define TXB1D5 0x4B +#define TXB1D6 0x4C +#define TXB1D7 0x4D + +//Message transmission registers - buffer --> 2 + +#define TXB2CTRL 0x50 +#define TXB2SIDH 0x51 +#define TXB2SIDL 0x52 +#define TXB2EID8 0x53 +#define TXB2EID0 0x54 +#define TXB2DLC 0x55 +#define TXB2D0 0x56 +#define TXB2D1 0x57 +#define TXB2D2 0x58 +#define TXB2D3 0x59 +#define TXB2D4 0x5A +#define TXB2D5 0x5B +#define TXB2D6 0x5C +#define TXB2D7 0x5D + +//Message reception registers - buffer --> 0 + +#define RXB0CTRL 0x60 +#define RXB0SIDH 0x61 +#define RXB0SIDL 0x62 +#define RXB0EID8 0x63 +#define RXB0EID0 0x64 +#define RXB0DLC 0x65 +#define RXB0D0 0x66 +#define RXB0D1 0x67 +#define RXB0D2 0x68 +#define RXB0D3 0x69 +#define RXB0D4 0x6A +#define RXB0D5 0x6B +#define RXB0D6 0x6C +#define RXB0D7 0x6D + +//Message reception registers - buffer --> 1 + +#define RXB1CTRL 0x70 +#define RXB1SIDH 0x71 +#define RXB1SIDL 0x72 +#define RXB1EID8 0x73 +#define RXB1EID0 0x74 +#define RXB1DLC 0x75 +#define RXB1D0 0x76 +#define RXB1D1 0x77 +#define RXB1D2 0x78 +#define RXB1D3 0x79 +#define RXB1D4 0x7A +#define RXB1D5 0x7B +#define RXB1D6 0x7C +#define RXB1D7 0x7D + +//Control registers + +/** BFPCTRL **/ +#define B1BFS 5 +#define B0BFS 4 +#define B1BFE 3 +#define B0BFE 2 +#define B1BFM 1 +#define B0BFM 0 + +/** TXRTSCTRL **/ +#define B2RTS 5 +#define B1RTS 4 +#define B0RTS 3 +#define B2RTSM 2 +#define B1RTSM 1 +#define B0RTSM 0 + +/** CANSTAT **/ +#define OPMOD2 7 +#define OPMOD1 6 +#define OPMOD0 5 +#define ICOD2 3 +#define ICOD1 2 +#define ICOD0 1 + +/** CANCTRL **/ +#define REQOP2 7 +#define REQOP1 6 +#define REQOP0 5 +#define ABAT 4 +#define CLKEN 2 +#define CLKPRE1 1 +#define CLKPRE0 0 + +/** CNF3 **/ +#define SOF 7 +#define WAKFIL 6 +#define PHSEG22 2 +#define PHSEG21 1 +#define PHSEG20 0 + +/** CNF2 **/ +#define BTLMODE 7 +#define SAM 6 +#define PHSEG12 5 +#define PHSEG11 4 +#define PHSEG10 3 +#define PHSEG2 2 +#define PHSEG1 1 +#define PHSEG0 0 + +/** CNF1 **/ +#define SJW1 7 +#define SJW0 6 +#define BRP5 5 +#define BRP4 4 +#define BRP3 3 +#define BRP2 2 +#define BRP1 1 +#define BRP0 0 + +/** CANINTE **/ +#define MERRE 7 +#define WAKIE 6 +#define ERRIE 5 +#define TX2IE 4 +#define TX1IE 3 +#define TX0IE 2 +#define RX1IE 1 +#define RX0IE 0 + +/** CANINTF */ +#define MERRF 7 +#define WAKIF 6 +#define ERRIF 5 +#define TX2IF 4 +#define TX1IF 3 +#define TX0IF 2 +#define RX1IF 1 +#define RX0IF 0 + +/** EFLG **/ +#define RX1OVR 7 +#define RX0OVR 6 +#define TXB0 5 +#define TXEP 4 +#define RXEP 3 +#define TXWAR 2 +#define RXWAR 1 +#define EWARN 0 + +/** TXBnCTRL (n = 0, 1, 2) **/ +#define ABTF 6 +#define MLOA 5 +#define TXERR 4 +#define TXREQ 3 +#define TXP1 1 +#define TXP0 0 + +/** RXB0CTRL **/ +#define RXM1 6 +#define RXM0 5 +#define RXRTR 3 +#define BUKT 2 +#define BUKT1 1 +#define FILHIT0 0 + +/** RXB1CTRL **/ +#define RSM1 6 +#define FILHIT2 2 +#define FILHIT1 1 + +/** TXBnSIDL (n = 0, 1) **/ +#define EXIDE 3 + +/** RXBnSIDL (n = 0, 1) **/ +#define SRR 4 +#define IDE 3 + +/** RXBnDLC (n = 0, 1) / TXBnDLC **/ +#define RTR 6 +#define DLC3 3 +#define DLC2 2 +#define DLC1 1 +#define DLC0 0 + + +/****************************************************************************** + CAN in Automation (CiA) + ******************************************************************************/ + +//Standard OBD requests and responses + +#define ID_QUERY 0x7DF +#define ID_RESPONSE 0x7E8 + + +//Standars PIDs + + //Mode PID Data ret......Description...............min_val...max_val..units...formula + +#define CALC_ENGINE_LOAD 0X04 //01 04 1 Calculated engine load value 0 100 % A*100/255 +#define ENGINE_COOLANT_TEMP 0x05 //01 05 1 Engine coolant temperature -40 215 °C A-40 +#define SHORT_TERM_FUEL_1 0x06 //01 06 1 Short term fuel % trim—Bank 1 -100 (Rich) 99.22 (Lean) % (A-128) * 100/128 +#define LONG_TERM_FUEL_1 0x07 //01 07 1 Long term fuel % trim—Bank 1 -100 (Rich) 99.22 (Lean) % (A-128) * 100/128 +#define SHORT_TERM_FUEL_2 0x08 //01 08 1 Short term fuel % trim—Bank 2 -100 (Rich) 99.22 (Lean) % (A-128) * 100/128 +#define LONG_TERM_FUEL_2 0x09 //01 09 1 Long term fuel % trim—Bank 2 -100 (Rich) 99.22 (Lean) % (A-128) * 100/128 +#define O2_B1_S1_VOLTAGE 0x14 //01 14 2 Bank 1, Sensor 1:Oxygen sensor voltage,Short term fuel trim 0-100(lean) 1.275 99.2(rich) Volts % A/200(B-128) * 100/128 (if B==0xFF, sensor is not used in trim calc) +#define FUEL_PRESSURE 0x0A //01 0A 1 Fuel pressure 0 765 kPa (gauge) A*3 +#define INTAKE_M_A_PRESSURE 0x0B //01 0B 1 Intake manifold absolute pressure 0 255 kPa (absolute) A +#define ENGINE_RPM 0x0C //01 0C 2 Engine RPM 0 16,383.75 rpm ((A*256)+B)/4 +#define VEHICLE_SPEED 0x0D //01 0D 1 Vehicle speed 0 255 km/h A +#define TIMING_ADVANCE 0x0E //01 0E 1 Timing advance -64 63.5 ° relative to #1 cylinder A/2 - 64 +#define INTAKE_AIR_TEMP 0x0F //01 0F 1 Intake air temperature -40 215 °C A-40 +#define MAF_AIR_FLOW_RATE 0x10 //01 10 2 MAF air flow rate 0 655.35 g/s ((A*256)+B) / 100 +#define THROTTLE_POSITION 0x11 //01 11 1 Throttle position 0 100 % A*100/255 +#define RUNTIME_SINCE_START 0x1F //01 1F 2 Run time since engine start 0 65,535 seconds (A*256)+B +#define DISTANCE_WITH_MALF 0x21 //01 21 2 Distance traveled with malfunction indicator lamp (MIL) on 0 65,535 km (A*256)+B +#define FUEL_RAIL_PRESSURE_RELATIVE 0x22 //01 22 2 Fuel Rail Pressure (relative to manifold vacuum) 0 5177.265 kPa (((A*256)+B) * 10) / 128 +#define FUEL_RAIL_PRESSURE_DIESEL 0x23 //01 23 2 Fuel Rail Pressure (diesel) 0 655350 kPa (gauge) ((A*256)+B) * 10 +#define FUEL_LEVEL 0x2F //01 2F 1 Fuel Level Input 0 100 % 100*A/255 +#define NUM_WARMUPS_SINCE_CODES 0x30 //01 30 1 # of warm-ups since codes cleared 0 255 N/A A +#define DISTANCE_SINCE_CODES 0x31 //01 31 2 Distance traveled since codes cleared 0 65,535 km (A*256)+B +#define EVAP_SYSTEM_VAPOR_PRESSURE 0x32 //01 32 2 Evap. System Vapor Pressure -8,192 8,192 Pa ((A*256)+B)/4 (A is signed) +#define BAROMETRIC_PRESSURE 0x33 //01 33 1 Barometric pressure 0 255 kPa (Absolute) A +#define CONTROL_MODULE_VOLTAGE 0x42 //01 42 2 Control module voltage 0 65.535 V ((A*256)+B)/1000 +#define ABSOLUTE_LOAD_VALUE 0x43 //01 43 2 Absolute load value 0 25,700 % ((A*256)+B)*100/255 +#define COMMAND_EQUIV_RATIO 0x44 //01 44 2 Command equivalence ratio 0 2 N/A ((A*256)+B)/32768 +#define REL_THROTTLE_POSITION 0x45 //01 45 1 Relative throttle position 0 100 % A*100/255 +#define AMBIENT_AIR_TEMPERATURE 0x46 //01 46 1 Ambient air temperature -40 215 °C A-40 +#define ABS_THROTTLE_POSITION_B 0x47 //01 47 1 Absolute throttle position B 0 100 % A*100/255 +#define ABS_THROTTLE_POSITION_C 0x48 //01 48 1 Absolute throttle position C 0 100 % A*100/255 +#define ABS_THROTTLE_POSITION_D 0x49 //01 49 1 Accelerator pedal position D 0 100 % A*100/255 +#define ABS_THROTTLE_POSITION_E 0x4A //01 4A 1 Accelerator pedal position E 0 100 % A*100/255 +#define ABS_THROTTLE_POSITION_F 0x4B //01 4B 1 Accelerator pedal position F 0 100 % A*100/255 +#define COMMANDED_THROTTLE_ACTUATOR 0x4C //01 4C 1 Commanded throttle actuator 0 100 % A*100/255 +#define TIME_RUN_WITH_MIL_ON 0x4D //01 4D 2 Time run with MIL on 0 65,535 minutes (A*256)+B +#define TIME_SINCE_T_CODES_CLEAR 0x4E //01 4E 2 Time since trouble codes cleared 0 65,535 minutes (A*256)+B +#define FUEL_TYPE 0x51 //01 51 1 Fuel Type From fuel type table see below +#define ETHANOL_FUEL 0x52 //01 52 1 Ethanol fuel % 0 100 % A*100/255 +#define ABS_EVAP_SYST_VAPOUR_PRESS 0x53 //01 53 2 Absoulute Evap system Vapour Pressure 0 327675 kpa 1/200 per bit +#define ENGINE_FUEL_RATE 0x5E //01 5E 2 Engine fuel rate 0 - 3212.75 L/h ((A*256)+B)*0.05 + + +#include <inttypes.h> + + +/****************************************************************************** + * Class + ******************************************************************************/ + + //! CAN Class +/*! + CAN Class defines all the variables and functions used to manage CAN-bus modules + */ + +class CAN +{ + + private: + // Write a register of the MCP2515 using SPI + void writeRegister( char direction, char data ); + // Read a register of the MCP2515 using SPI + char readRegister(char direction); + // Modify a bit of the MCP2515 using SPI + void bitModify(char direction, char mask, char data); + // Check the status of the MCP2515 registers + char readStatus(char type); + // Check if the buffers are empty + bool checkFreeBuffer(void); + // Reset MCP2515 + void reset(void); + + + public: + + // Data structure + typedef struct{ + unsigned int id; + struct + { + char rtr : 1; + char length : 4; + }header; + + uint8_t data[8]; + }messageCAN; + + // Receive buffer + messageCAN messageRx; + // Trasmit buffer + messageCAN messageTx; + // Empty constructor + CAN(void); + // Powers the CANBus module and opens the SPI + bool begin(uint16_t speed); + // Check if there is any message + uint8_t messageAvailable(void); + // Take the CAN message + char getMessage(messageCAN *msje); + // Send the CAN message + char sendMessage(messageCAN *msje); + // CAN message print out the serial port + void printMessage(messageCAN *msje); + // Configure the MCP2515 + void setMode(uint8_t mode); + +/*********************************************************************** + CAN in Automation (CiA) +***********************************************************************/ + + unsigned int getEngineLoad(); + unsigned int getEngineCoolantTemp(); + unsigned int getFuelPressure(); + unsigned int getIntakeMAPressure(); + unsigned int getEngineRPM(); + unsigned int getVehicleSpeed(); + unsigned int getTimingAdvance(); + unsigned int getIntankeAirTemp(); + unsigned int getMAFairFlowRate(); + unsigned int getThrottlePosition(); + unsigned int getFuelLevel(); + unsigned int getBarometricPressure(); + unsigned int getEngineFuelRate(); + + // General Function + void CiARequest(uint8_t PID); + + +}; + + +#endif + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Feb 29 19:33:12 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/252557024ec3 \ No newline at end of file