MCP2515 CAN library

Fork of mcp2515 by Jason Engelman

Committer:
driscoll85
Date:
Mon Jun 05 01:03:51 2017 +0000
Revision:
11:b364adad6f08
Parent:
10:6d6fd99da044
Child:
13:ff12c7f532f9
Updated frequency to 20MHz

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tecnosys 0:d8f50b1e384f 1 /******************************************************************************
tecnosys 1:dbc44582f2f8 2 *
tecnosys 0:d8f50b1e384f 3 * Controller Area Network (CAN) Demo-Application
tecnosys 1:dbc44582f2f8 4 * Atmel AVR with Microchip MCP2515
tecnosys 1:dbc44582f2f8 5 *
tecnosys 0:d8f50b1e384f 6 * Copyright (C) 2005 Martin THOMAS, Kaiserslautern, Germany
tecnosys 0:d8f50b1e384f 7 * <eversmith@heizung-thomas.de>
tecnosys 0:d8f50b1e384f 8 * http://www.siwawi.arubi.uni-kl.de/avr_projects
tecnosys 0:d8f50b1e384f 9 *
tecnosys 0:d8f50b1e384f 10 *****************************************************************************
tecnosys 0:d8f50b1e384f 11 *
tecnosys 0:d8f50b1e384f 12 * File : mcp2515.c
tecnosys 0:d8f50b1e384f 13 * Version : 0.9
tecnosys 1:dbc44582f2f8 14 *
tecnosys 0:d8f50b1e384f 15 * Summary : MCP2515 "low-level" driver
tecnosys 0:d8f50b1e384f 16 *
tecnosys 1:dbc44582f2f8 17 * Parts of this code are adapted from a MCP2510 sample-application
tecnosys 0:d8f50b1e384f 18 * by KVASER AB, http://www.kvaser.com (KVASER-code is marked as free)
tecnosys 0:d8f50b1e384f 19 *
tecnosys 0:d8f50b1e384f 20 * This code-module is free to use but you have to keep the copyright
tecnosys 0:d8f50b1e384f 21 * notice.
tecnosys 0:d8f50b1e384f 22 *
tecnosys 0:d8f50b1e384f 23 *
tecnosys 0:d8f50b1e384f 24 *****************************************************************************
tecnosys 0:d8f50b1e384f 25 *
tecnosys 0:d8f50b1e384f 26 * File : mcp2515.cpp (mbed LPC1768 version)
tecnosys 0:d8f50b1e384f 27 * Version : 0.1
tecnosys 0:d8f50b1e384f 28 *
tecnosys 1:dbc44582f2f8 29 * All credits to the nerds above, this source has been adapted for the
driscoll85 9:d50f103848e0 30 * LPC1768 platform by J.Engelman. And doesn't require and of the copyrighted
tecnosys 0:d8f50b1e384f 31 * SPI or AVR controller code that Martin or co have excluded copyright.
tecnosys 0:d8f50b1e384f 32 * This module remains free.
tecnosys 0:d8f50b1e384f 33 *
tecnosys 0:d8f50b1e384f 34 *
tecnosys 0:d8f50b1e384f 35 *****************************************************************************/
tecnosys 0:d8f50b1e384f 36
tecnosys 0:d8f50b1e384f 37 #include "mcp2515.h"
tecnosys 0:d8f50b1e384f 38
tecnosys 1:dbc44582f2f8 39 #include "mbed.h"
tecnosys 0:d8f50b1e384f 40 #include "mcp2515_can.h"
tecnosys 0:d8f50b1e384f 41 #include "mcp2515_defs.h"
tecnosys 0:d8f50b1e384f 42 #include "mcp2515_bittime.h"
tecnosys 0:d8f50b1e384f 43
tecnosys 0:d8f50b1e384f 44 #define SPI_NULL (0x00)
tecnosys 0:d8f50b1e384f 45
tecnosys 1:dbc44582f2f8 46 #define PHSEG11 4
tecnosys 1:dbc44582f2f8 47 #define PHSEG21 1
tecnosys 1:dbc44582f2f8 48 #define BTLMODE2 7
tecnosys 1:dbc44582f2f8 49 //BTLMODE 0x80 (128)
tecnosys 1:dbc44582f2f8 50 #define BRP2 2
tecnosys 1:dbc44582f2f8 51 #define BRP1 1
tecnosys 1:dbc44582f2f8 52 #define BRP0 0
tecnosys 0:d8f50b1e384f 53
tecnosys 1:dbc44582f2f8 54 #define CNF2_BTLMODE 0x80
tecnosys 1:dbc44582f2f8 55 #define CNF3 0x28
tecnosys 1:dbc44582f2f8 56 #define CNF3_SOF 0x08
tecnosys 1:dbc44582f2f8 57 #define CNF3_WAKFIL 0x04
tecnosys 1:dbc44582f2f8 58 #define CNF3_PHSEG2_MASK 0x07
tecnosys 0:d8f50b1e384f 59
tecnosys 1:dbc44582f2f8 60 mcp2515::mcp2515(SPI& _spi, PinName ncs)
tecnosys 1:dbc44582f2f8 61 : spi(_spi), _ncs(ncs) {
tecnosys 1:dbc44582f2f8 62 printf("\n\rmcp2515 = %d",this);
tecnosys 1:dbc44582f2f8 63 printf("\n\rpin = %d",ncs);
tecnosys 0:d8f50b1e384f 64
tecnosys 0:d8f50b1e384f 65 }
tecnosys 0:d8f50b1e384f 66
tecnosys 0:d8f50b1e384f 67
tecnosys 1:dbc44582f2f8 68
tecnosys 0:d8f50b1e384f 69 void mcp2515::_reset() {
tecnosys 0:d8f50b1e384f 70
tecnosys 0:d8f50b1e384f 71 _select();
tecnosys 0:d8f50b1e384f 72 _spi_readwrite(MCP_RESET);
tecnosys 0:d8f50b1e384f 73 _deselect();
tecnosys 0:d8f50b1e384f 74 wait(0.001);
tecnosys 0:d8f50b1e384f 75 }
tecnosys 0:d8f50b1e384f 76
tecnosys 1:dbc44582f2f8 77 void mcp2515::setRegister( uint8_t address, uint8_t value) {
tecnosys 0:d8f50b1e384f 78 _select();
tecnosys 0:d8f50b1e384f 79 _spi_readwrite(MCP_WRITE);
tecnosys 0:d8f50b1e384f 80 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 81 _spi_readwrite(value);
tecnosys 0:d8f50b1e384f 82 _deselect();
tecnosys 0:d8f50b1e384f 83 }
tecnosys 0:d8f50b1e384f 84
tecnosys 1:dbc44582f2f8 85 uint8_t mcp2515::configRate( uint8_t canSpeed) {
tecnosys 0:d8f50b1e384f 86 uint8_t set, cfg1, cfg2, cfg3;
tecnosys 1:dbc44582f2f8 87
tecnosys 0:d8f50b1e384f 88 set = 0;
tecnosys 1:dbc44582f2f8 89
tecnosys 0:d8f50b1e384f 90 switch (canSpeed) {
tecnosys 1:dbc44582f2f8 91 case (CAN_500KBPS_8MHZ) :
driscoll85 10:6d6fd99da044 92 cfg1 = 0x04;
tecnosys 1:dbc44582f2f8 93 cfg2 = 0xA0;
tecnosys 1:dbc44582f2f8 94 cfg3 = 0x02;
tecnosys 1:dbc44582f2f8 95 case (CAN_50KBPS_8MHZ) :
driscoll85 10:6d6fd99da044 96 cfg1 = 0x04; //0x09;
tecnosys 1:dbc44582f2f8 97 cfg2 = 0xB8; //0x90;
tecnosys 1:dbc44582f2f8 98 cfg3 = 0x05; //0x02;
tecnosys 0:d8f50b1e384f 99 case (CAN_125KBPS) :
driscoll85 10:6d6fd99da044 100 cfg1 = MCP_4MHz_125kBPS_CFG1 ;
tecnosys 0:d8f50b1e384f 101 cfg2 = MCP_4MHz_125kBPS_CFG2 ;
tecnosys 0:d8f50b1e384f 102 cfg3 = MCP_4MHz_125kBPS_CFG3 ;
tecnosys 0:d8f50b1e384f 103 set = 1;
tecnosys 0:d8f50b1e384f 104 break;
tecnosys 0:d8f50b1e384f 105 case (CAN_20KBPS) :
driscoll85 10:6d6fd99da044 106 cfg1 = MCP_4MHz_20kBPS_CFG1 ;
tecnosys 0:d8f50b1e384f 107 cfg2 = MCP_4MHz_20kBPS_CFG2 ;
tecnosys 0:d8f50b1e384f 108 cfg3 = MCP_4MHz_20kBPS_CFG3 ;
tecnosys 0:d8f50b1e384f 109 set = 1;
tecnosys 0:d8f50b1e384f 110 break;
driscoll85 10:6d6fd99da044 111 case (CAN_500KBPS_10MHz) :
driscoll85 10:6d6fd99da044 112 cfg1 = 0x00;
driscoll85 10:6d6fd99da044 113 cfg2 = 0x92;
driscoll85 10:6d6fd99da044 114 cfg3 = 0x02;
driscoll85 10:6d6fd99da044 115 set = 1;
driscoll85 10:6d6fd99da044 116 break;
tecnosys 0:d8f50b1e384f 117 default:
tecnosys 0:d8f50b1e384f 118 set = 0;
tecnosys 0:d8f50b1e384f 119 break;
tecnosys 0:d8f50b1e384f 120 }
tecnosys 1:dbc44582f2f8 121
tecnosys 0:d8f50b1e384f 122 if (set) {
tecnosys 0:d8f50b1e384f 123 setRegister(MCP_CNF1, cfg1);
tecnosys 0:d8f50b1e384f 124 setRegister(MCP_CNF2, cfg2);
tecnosys 0:d8f50b1e384f 125 setRegister(MCP_CNF3, cfg3);
tecnosys 0:d8f50b1e384f 126 return MCP2515_OK;
tecnosys 1:dbc44582f2f8 127 } else {
tecnosys 0:d8f50b1e384f 128 return MCP2515_FAIL;
tecnosys 0:d8f50b1e384f 129 }
tecnosys 1:dbc44582f2f8 130 }
tecnosys 1:dbc44582f2f8 131
tecnosys 1:dbc44582f2f8 132 int mcp2515::configRate2(int bit_rate)
tecnosys 1:dbc44582f2f8 133 {
tecnosys 1:dbc44582f2f8 134 //struct spi_device *spi = to_spi_device(can->cdev.dev);
tecnosys 1:dbc44582f2f8 135 //struct mcp251x *chip = dev_get_drvdata(&spi->dev);
tecnosys 1:dbc44582f2f8 136 //struct mcp251x_platform_data *pdata = spi->dev.platform_data;
tecnosys 1:dbc44582f2f8 137
tecnosys 1:dbc44582f2f8 138 printf("\n\rcanspeed=%d",bit_rate);
driscoll85 11:b364adad6f08 139 int f_osc = 20000000; //4000000; //4Mhz
tecnosys 1:dbc44582f2f8 140 int tqs; /* tbit/TQ */
tecnosys 1:dbc44582f2f8 141 int brp;
tecnosys 1:dbc44582f2f8 142 int ps1, ps2, propseg, sjw;
tecnosys 1:dbc44582f2f8 143
tecnosys 1:dbc44582f2f8 144 /* Determine the BRP value that gives the requested bit rate. */
tecnosys 1:dbc44582f2f8 145 for(brp = 0; brp < 8; brp++) {
tecnosys 1:dbc44582f2f8 146 tqs = f_osc / (2 * (brp + 1)) / bit_rate;
tecnosys 1:dbc44582f2f8 147 if (tqs >= 5 && tqs <= 25
tecnosys 1:dbc44582f2f8 148 && (f_osc / (2 * (brp + 1)) / tqs) == bit_rate)
tecnosys 1:dbc44582f2f8 149 break;
tecnosys 1:dbc44582f2f8 150 }
tecnosys 1:dbc44582f2f8 151 if (brp >= 8) printf("Spaztic BRP");
tecnosys 1:dbc44582f2f8 152 // return -1;
tecnosys 0:d8f50b1e384f 153
tecnosys 1:dbc44582f2f8 154 /* The CAN bus bit time (tbit) is determined by:
tecnosys 1:dbc44582f2f8 155 * tbit = (SyncSeg + PropSeg + PS1 + PS2) * TQ
tecnosys 1:dbc44582f2f8 156 * with:
tecnosys 1:dbc44582f2f8 157 * SyncSeg = 1
tecnosys 1:dbc44582f2f8 158 * sample point (between PS1 and PS2) must be at 60%-70% of the bit time
tecnosys 1:dbc44582f2f8 159 * PropSeg + PS1 >= PS2
tecnosys 1:dbc44582f2f8 160 * PropSeg + PS1 >= Tdelay
tecnosys 1:dbc44582f2f8 161 * PS2 > SJW
tecnosys 1:dbc44582f2f8 162 * 1 <= PropSeg <= 8, 1 <= PS1 <=8, 2 <= PS2 <= 8
tecnosys 1:dbc44582f2f8 163 * SJW = 1 is sufficient in most cases.
tecnosys 1:dbc44582f2f8 164 * Tdelay is usually 1 or 2 TQ.
tecnosys 1:dbc44582f2f8 165 */
tecnosys 1:dbc44582f2f8 166
tecnosys 1:dbc44582f2f8 167 propseg = ps1 = ps2 = (tqs - 1) / 3;
tecnosys 1:dbc44582f2f8 168 if (tqs - (1 + propseg + ps1 + ps2) == 2)
tecnosys 1:dbc44582f2f8 169 ps1++;
tecnosys 1:dbc44582f2f8 170 if (tqs - (1 + propseg + ps1 + ps2) == 1)
tecnosys 1:dbc44582f2f8 171 ps2++;
tecnosys 1:dbc44582f2f8 172 sjw = 1;
tecnosys 1:dbc44582f2f8 173
tecnosys 1:dbc44582f2f8 174 printf("\n\rbit rate: BRP = %d, Tbit = %d TQ, PropSeg = %d, PS1 = %d, PS2 = %d, SJW = %d\n",
tecnosys 1:dbc44582f2f8 175 brp, tqs, propseg, ps1, ps2, sjw);
tecnosys 1:dbc44582f2f8 176
tecnosys 1:dbc44582f2f8 177 /* Since we can only change the bit rate when the network device is
tecnosys 1:dbc44582f2f8 178 * down the chip must be in sleep mode. Wake it up and put it into
tecnosys 1:dbc44582f2f8 179 * config mode. */
tecnosys 1:dbc44582f2f8 180 //mcp251x_hw_wakeup(spi);
tecnosys 1:dbc44582f2f8 181 //mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_CONF);
tecnosys 1:dbc44582f2f8 182
tecnosys 1:dbc44582f2f8 183 //mcp251x_write_reg(spi, CNF1, ((sjw-1) << 6) | brp);
tecnosys 1:dbc44582f2f8 184 //mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1));
tecnosys 1:dbc44582f2f8 185 //mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, (ps2-1));
tecnosys 1:dbc44582f2f8 186 setRegister(MCP_CNF1, ((sjw-1) << 6) | brp );
tecnosys 1:dbc44582f2f8 187 setRegister(MCP_CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1) );
tecnosys 1:dbc44582f2f8 188 modifyRegister(MCP_CNF3, CNF3_PHSEG2_MASK, (ps2-1) );
tecnosys 1:dbc44582f2f8 189 //mcp251x_hw_sleep(spi);
tecnosys 1:dbc44582f2f8 190
tecnosys 1:dbc44582f2f8 191 /* Calculate actual bit rate. */
tecnosys 1:dbc44582f2f8 192 //chip->bit_rate = pdata->f_osc / (2 * (brp + 1)) / tqs;
tecnosys 1:dbc44582f2f8 193
tecnosys 1:dbc44582f2f8 194 return 0;
tecnosys 1:dbc44582f2f8 195 }
tecnosys 1:dbc44582f2f8 196
tecnosys 1:dbc44582f2f8 197 uint8_t mcp2515::readRegister( uint8_t address) {
tecnosys 0:d8f50b1e384f 198 uint8_t ret;
tecnosys 1:dbc44582f2f8 199
tecnosys 0:d8f50b1e384f 200 _select();
tecnosys 0:d8f50b1e384f 201 _spi_readwrite(MCP_READ);
tecnosys 0:d8f50b1e384f 202 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 203 ret = _spi_read();
tecnosys 0:d8f50b1e384f 204 _deselect();
tecnosys 1:dbc44582f2f8 205
tecnosys 0:d8f50b1e384f 206 return ret;
tecnosys 0:d8f50b1e384f 207 }
tecnosys 0:d8f50b1e384f 208
tecnosys 1:dbc44582f2f8 209 void mcp2515::readRegisterS( uint8_t address,
tecnosys 1:dbc44582f2f8 210 uint8_t values[], uint8_t n) {
tecnosys 0:d8f50b1e384f 211 uint8_t i;
tecnosys 1:dbc44582f2f8 212
tecnosys 0:d8f50b1e384f 213 _select();
tecnosys 0:d8f50b1e384f 214 _spi_readwrite(MCP_READ);
tecnosys 0:d8f50b1e384f 215 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 216 // mcp2515 has auto-increment of address-pointer
tecnosys 0:d8f50b1e384f 217 for (i=0; i<n; i++) {
tecnosys 0:d8f50b1e384f 218 values[i] = _spi_read();
tecnosys 0:d8f50b1e384f 219 }
tecnosys 0:d8f50b1e384f 220 _deselect();
tecnosys 0:d8f50b1e384f 221 }
tecnosys 0:d8f50b1e384f 222
tecnosys 1:dbc44582f2f8 223 void mcp2515::modifyRegister( uint8_t address,
tecnosys 1:dbc44582f2f8 224 uint8_t mask, uint8_t data) {
tecnosys 0:d8f50b1e384f 225 _select();
tecnosys 0:d8f50b1e384f 226 _spi_readwrite(MCP_BITMOD);
tecnosys 0:d8f50b1e384f 227 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 228 _spi_readwrite(mask);
tecnosys 0:d8f50b1e384f 229 _spi_readwrite(data);
tecnosys 0:d8f50b1e384f 230 _deselect();
tecnosys 0:d8f50b1e384f 231 }
tecnosys 0:d8f50b1e384f 232
tecnosys 0:d8f50b1e384f 233
tecnosys 1:dbc44582f2f8 234 uint8_t mcp2515::readXXStatus_helper( uint8_t cmd) {
tecnosys 0:d8f50b1e384f 235 uint8_t i;
tecnosys 1:dbc44582f2f8 236
tecnosys 0:d8f50b1e384f 237 _select();
tecnosys 0:d8f50b1e384f 238 _spi_readwrite(cmd);
tecnosys 0:d8f50b1e384f 239 i = _spi_read();
tecnosys 0:d8f50b1e384f 240 _deselect();
tecnosys 1:dbc44582f2f8 241
tecnosys 0:d8f50b1e384f 242 return i;
tecnosys 0:d8f50b1e384f 243 }
tecnosys 1:dbc44582f2f8 244
tecnosys 1:dbc44582f2f8 245 uint8_t mcp2515::readStatus(void) {
tecnosys 0:d8f50b1e384f 246 return readXXStatus_helper(MCP_READ_STATUS);
tecnosys 0:d8f50b1e384f 247 }
tecnosys 0:d8f50b1e384f 248
tecnosys 1:dbc44582f2f8 249 uint8_t mcp2515::RXStatus(void) {
tecnosys 0:d8f50b1e384f 250 return readXXStatus_helper(MCP_RX_STATUS);
tecnosys 0:d8f50b1e384f 251 }
tecnosys 0:d8f50b1e384f 252
tecnosys 0:d8f50b1e384f 253 // read-modify-write - better: Bit Modify Instruction
tecnosys 1:dbc44582f2f8 254 uint8_t mcp2515::setCANCTRL_Mode(uint8_t newmode) {
tecnosys 1:dbc44582f2f8 255
tecnosys 0:d8f50b1e384f 256 uint8_t i;
tecnosys 1:dbc44582f2f8 257
tecnosys 0:d8f50b1e384f 258 i = readRegister(MCP_CANCTRL);
tecnosys 0:d8f50b1e384f 259 i &= ~(MODE_MASK);
tecnosys 0:d8f50b1e384f 260 i |= newmode;
tecnosys 0:d8f50b1e384f 261 setRegister(MCP_CANCTRL, i);
tecnosys 1:dbc44582f2f8 262
tecnosys 0:d8f50b1e384f 263 // verify as advised in datasheet
tecnosys 0:d8f50b1e384f 264 i = readRegister(MCP_CANCTRL);
tecnosys 0:d8f50b1e384f 265 i &= MODE_MASK;
tecnosys 0:d8f50b1e384f 266 if ( i == newmode ) {
tecnosys 1:dbc44582f2f8 267 return MCP2515_OK;
tecnosys 1:dbc44582f2f8 268 } else {
tecnosys 0:d8f50b1e384f 269 return MCP2515_FAIL;
tecnosys 0:d8f50b1e384f 270 }
tecnosys 1:dbc44582f2f8 271
tecnosys 0:d8f50b1e384f 272 }
tecnosys 0:d8f50b1e384f 273
tecnosys 0:d8f50b1e384f 274
tecnosys 1:dbc44582f2f8 275 void mcp2515::setRegisterS( uint8_t address,
tecnosys 1:dbc44582f2f8 276 uint8_t values[], uint8_t n) {
tecnosys 0:d8f50b1e384f 277 uint8_t i;
tecnosys 1:dbc44582f2f8 278
tecnosys 0:d8f50b1e384f 279 _select();
tecnosys 0:d8f50b1e384f 280 _spi_readwrite(MCP_WRITE);
tecnosys 0:d8f50b1e384f 281 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 282 // mcp2515 has auto-increment of address-pointer
tecnosys 0:d8f50b1e384f 283 for (i=0; i<n; i++) {
tecnosys 0:d8f50b1e384f 284 _spi_readwrite(values[i]);
tecnosys 0:d8f50b1e384f 285 }
tecnosys 0:d8f50b1e384f 286 _deselect();
tecnosys 0:d8f50b1e384f 287 }
tecnosys 0:d8f50b1e384f 288
tecnosys 1:dbc44582f2f8 289 void mcp2515::read_can_id( uint8_t mcp_addr,
tecnosys 1:dbc44582f2f8 290 uint8_t* ext, uint32_t* can_id ) {
tecnosys 0:d8f50b1e384f 291 uint8_t tbufdata[4];
tecnosys 1:dbc44582f2f8 292
tecnosys 0:d8f50b1e384f 293 *ext = 0;
tecnosys 0:d8f50b1e384f 294 *can_id = 0;
tecnosys 1:dbc44582f2f8 295
tecnosys 0:d8f50b1e384f 296 readRegisterS( mcp_addr, tbufdata, 4 );
tecnosys 1:dbc44582f2f8 297
tecnosys 0:d8f50b1e384f 298 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5);
tecnosys 1:dbc44582f2f8 299
tecnosys 0:d8f50b1e384f 300 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) {
tecnosys 0:d8f50b1e384f 301 // extended id
tecnosys 0:d8f50b1e384f 302 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03);
tecnosys 0:d8f50b1e384f 303 *can_id <<= 16;
tecnosys 0:d8f50b1e384f 304 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0];
tecnosys 0:d8f50b1e384f 305 *ext = 1;
tecnosys 0:d8f50b1e384f 306 }
tecnosys 0:d8f50b1e384f 307 }
tecnosys 0:d8f50b1e384f 308
tecnosys 0:d8f50b1e384f 309
tecnosys 1:dbc44582f2f8 310 void mcp2515::read_can_idN( uint8_t mcp_addr,
tecnosys 1:dbc44582f2f8 311 CANFormat* ext, unsigned int* can_id ) {
tecnosys 1:dbc44582f2f8 312 uint8_t tbufdata[4];
tecnosys 1:dbc44582f2f8 313
tecnosys 1:dbc44582f2f8 314 *ext = CANStandard;
tecnosys 1:dbc44582f2f8 315 *can_id = 0;
tecnosys 1:dbc44582f2f8 316
tecnosys 1:dbc44582f2f8 317 readRegisterS( mcp_addr, tbufdata, 4 );
tecnosys 1:dbc44582f2f8 318
tecnosys 1:dbc44582f2f8 319 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5);
tecnosys 1:dbc44582f2f8 320
tecnosys 1:dbc44582f2f8 321 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) {
tecnosys 1:dbc44582f2f8 322 // extended id
tecnosys 1:dbc44582f2f8 323 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03);
tecnosys 1:dbc44582f2f8 324 *can_id <<= 16;
tecnosys 1:dbc44582f2f8 325 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0];
tecnosys 1:dbc44582f2f8 326 *ext = CANExtended;//1;
tecnosys 1:dbc44582f2f8 327 }
tecnosys 1:dbc44582f2f8 328 }
tecnosys 1:dbc44582f2f8 329
tecnosys 0:d8f50b1e384f 330 // Buffer can be MCP_RXBUF_0 or MCP_RXBUF_1
tecnosys 1:dbc44582f2f8 331 void mcp2515::read_canMsg( uint8_t buffer_sidh_addr, CANMessage* msg)
tecnosys 1:dbc44582f2f8 332 //CANMessage mcp2515::read_canMsg( uint8_t buffer_sidh_addr)
tecnosys 0:d8f50b1e384f 333 {
tecnosys 1:dbc44582f2f8 334 uint8_t mcp_addr, ctrl,dlc;
tecnosys 1:dbc44582f2f8 335
tecnosys 1:dbc44582f2f8 336
tecnosys 0:d8f50b1e384f 337
tecnosys 0:d8f50b1e384f 338 mcp_addr = buffer_sidh_addr;
tecnosys 1:dbc44582f2f8 339
tecnosys 1:dbc44582f2f8 340 read_can_idN( mcp_addr, &msg->format, &msg->id );
tecnosys 1:dbc44582f2f8 341
tecnosys 0:d8f50b1e384f 342 ctrl = readRegister( mcp_addr-1 );
tecnosys 1:dbc44582f2f8 343 dlc = readRegister( mcp_addr+4 );
tecnosys 1:dbc44582f2f8 344
tecnosys 0:d8f50b1e384f 345 //if ((*dlc & RTR_MASK) || (ctrl & 0x08)) {
tecnosys 0:d8f50b1e384f 346 if ((ctrl & 0x08)) {
tecnosys 1:dbc44582f2f8 347 msg->type = CANRemote; //1 CANRemote
tecnosys 0:d8f50b1e384f 348 } else {
tecnosys 1:dbc44582f2f8 349 msg->type = CANData; //0 CANData
tecnosys 0:d8f50b1e384f 350 }
tecnosys 1:dbc44582f2f8 351
tecnosys 1:dbc44582f2f8 352 dlc &= MCP_DLC_MASK;
tecnosys 1:dbc44582f2f8 353 readRegisterS( mcp_addr+5, &(msg->data[0]), dlc );
tecnosys 1:dbc44582f2f8 354 msg->len =dlc;
tecnosys 1:dbc44582f2f8 355
tecnosys 0:d8f50b1e384f 356 }
tecnosys 0:d8f50b1e384f 357
tecnosys 1:dbc44582f2f8 358 void mcp2515::setDebugConsole(Serial c){
tecnosys 1:dbc44582f2f8 359 //console=c;
tecnosys 1:dbc44582f2f8 360 debug=true;
tecnosys 1:dbc44582f2f8 361 }
tecnosys 0:d8f50b1e384f 362
tecnosys 1:dbc44582f2f8 363 void mcp2515::write_can_id( uint8_t mcp_addr,
tecnosys 1:dbc44582f2f8 364 uint8_t ext, uint32_t can_id ) {
tecnosys 0:d8f50b1e384f 365 uint16_t canid;
tecnosys 0:d8f50b1e384f 366 uint8_t tbufdata[4];
tecnosys 1:dbc44582f2f8 367
tecnosys 0:d8f50b1e384f 368 canid = (uint16_t)(can_id & 0x0FFFF);
tecnosys 1:dbc44582f2f8 369
tecnosys 0:d8f50b1e384f 370 if ( ext == 1) {
tecnosys 0:d8f50b1e384f 371 tbufdata[MCP_EID0] = (uint8_t) (canid & 0xFF);
tecnosys 0:d8f50b1e384f 372 tbufdata[MCP_EID8] = (uint8_t) (canid / 256);
tecnosys 0:d8f50b1e384f 373 canid = (uint16_t)( can_id / 0x10000L );
tecnosys 0:d8f50b1e384f 374 tbufdata[MCP_SIDL] = (uint8_t) (canid & 0x03);
tecnosys 0:d8f50b1e384f 375 tbufdata[MCP_SIDL] += (uint8_t) ((canid & 0x1C )*8);
tecnosys 0:d8f50b1e384f 376 tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M;
tecnosys 0:d8f50b1e384f 377 tbufdata[MCP_SIDH] = (uint8_t) (canid / 32 );
tecnosys 1:dbc44582f2f8 378 } else {
tecnosys 0:d8f50b1e384f 379 tbufdata[MCP_SIDH] = (uint8_t) (canid / 8 );
tecnosys 0:d8f50b1e384f 380 tbufdata[MCP_SIDL] = (uint8_t) ((canid & 0x07 )*32);
tecnosys 0:d8f50b1e384f 381 tbufdata[MCP_EID0] = 0;
tecnosys 0:d8f50b1e384f 382 tbufdata[MCP_EID8] = 0;
tecnosys 0:d8f50b1e384f 383 }
tecnosys 0:d8f50b1e384f 384 setRegisterS( mcp_addr, tbufdata, 4 );
tecnosys 0:d8f50b1e384f 385 }
tecnosys 0:d8f50b1e384f 386
tecnosys 0:d8f50b1e384f 387 // Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2
tecnosys 1:dbc44582f2f8 388 void mcp2515::write_canMsg( uint8_t buffer_sidh_addr,
tecnosys 1:dbc44582f2f8 389 CANMessage* msg) {
tecnosys 0:d8f50b1e384f 390 uint8_t mcp_addr, dlc;
tecnosys 0:d8f50b1e384f 391
tecnosys 0:d8f50b1e384f 392 mcp_addr = buffer_sidh_addr;
tecnosys 0:d8f50b1e384f 393 dlc = msg->len;
tecnosys 1:dbc44582f2f8 394
tecnosys 0:d8f50b1e384f 395 setRegisterS(mcp_addr+5, &(msg->data[0]), dlc ); // write data bytes
tecnosys 0:d8f50b1e384f 396 write_can_id( mcp_addr, msg->format,
tecnosys 1:dbc44582f2f8 397 msg->id ); // write CAN id
tecnosys 0:d8f50b1e384f 398 if ( msg->type == 1) dlc |= MCP_RTR_MASK; // if RTR set bit in byte
tecnosys 0:d8f50b1e384f 399 setRegister( (mcp_addr+4), dlc ); // write the RTR and DLC
tecnosys 0:d8f50b1e384f 400 }
tecnosys 0:d8f50b1e384f 401
tecnosys 1:dbc44582f2f8 402 void mcp2515::start_transmit( uint8_t buffer_sidh_addr) {
tecnosys 1:dbc44582f2f8 403 // TXBnCTRL_addr = TXBnSIDH_addr - 1
tecnosys 1:dbc44582f2f8 404 modifyRegister( buffer_sidh_addr-1 , MCP_TXB_TXREQ_M,
tecnosys 1:dbc44582f2f8 405 MCP_TXB_TXREQ_M );
tecnosys 0:d8f50b1e384f 406 }
tecnosys 0:d8f50b1e384f 407
tecnosys 1:dbc44582f2f8 408 uint8_t mcp2515::getNextFreeTXBuf(uint8_t *txbuf_n) {
tecnosys 1:dbc44582f2f8 409 uint8_t res, i, ctrlval;
tecnosys 1:dbc44582f2f8 410 uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL };
tecnosys 1:dbc44582f2f8 411
tecnosys 1:dbc44582f2f8 412 res = MCP_ALLTXBUSY;
tecnosys 1:dbc44582f2f8 413 *txbuf_n = 0x00;
tecnosys 0:d8f50b1e384f 414
tecnosys 1:dbc44582f2f8 415 // check all 3 TX-Buffers
tecnosys 1:dbc44582f2f8 416 for (i=0; i<MCP_N_TXBUFFERS; i++) {
tecnosys 1:dbc44582f2f8 417 ctrlval = readRegister( ctrlregs[i] );
tecnosys 1:dbc44582f2f8 418 if ( (ctrlval & MCP_TXB_TXREQ_M) == 0 ) {
tecnosys 1:dbc44582f2f8 419
tecnosys 1:dbc44582f2f8 420 *txbuf_n = ctrlregs[i]+1; // return SIDH-address of Buffer
tecnosys 1:dbc44582f2f8 421 res = MCP2515_OK;
tecnosys 1:dbc44582f2f8 422 return res; /* ! function exit */
tecnosys 1:dbc44582f2f8 423 }
tecnosys 1:dbc44582f2f8 424 }
tecnosys 1:dbc44582f2f8 425
tecnosys 1:dbc44582f2f8 426 return res;
tecnosys 0:d8f50b1e384f 427 }
tecnosys 0:d8f50b1e384f 428
tecnosys 1:dbc44582f2f8 429 void mcp2515::initCANBuffers(void) {
tecnosys 1:dbc44582f2f8 430 // uint8_t i, a1, a2, a3;
tecnosys 1:dbc44582f2f8 431
tecnosys 1:dbc44582f2f8 432 // TODO: check why this is needed to receive extended
tecnosys 0:d8f50b1e384f 433 // and standard frames
tecnosys 0:d8f50b1e384f 434 // Mark all filter bits as don't care:
tecnosys 0:d8f50b1e384f 435 write_can_id(MCP_RXM0SIDH, 0, 0);
tecnosys 0:d8f50b1e384f 436 write_can_id(MCP_RXM1SIDH, 0, 0);
tecnosys 0:d8f50b1e384f 437 // Anyway, set all filters to 0:
tecnosys 1:dbc44582f2f8 438 write_can_id(MCP_RXF0SIDH, 1, 0); // RXB0: extended
tecnosys 0:d8f50b1e384f 439 write_can_id(MCP_RXF1SIDH, 0, 0); // AND standard
tecnosys 1:dbc44582f2f8 440 write_can_id(MCP_RXF2SIDH, 1, 0); // RXB1: extended
tecnosys 0:d8f50b1e384f 441 write_can_id(MCP_RXF3SIDH, 0, 0); // AND standard
tecnosys 0:d8f50b1e384f 442 write_can_id(MCP_RXF4SIDH, 0, 0);
tecnosys 0:d8f50b1e384f 443 write_can_id(MCP_RXF5SIDH, 0, 0);
tecnosys 1:dbc44582f2f8 444 /*
tecnosys 0:d8f50b1e384f 445 // Clear, deactivate the three transmit buffers
tecnosys 0:d8f50b1e384f 446 // TXBnCTRL -> TXBnD7
tecnosys 0:d8f50b1e384f 447 a1 = MCP_TXB0CTRL;
tecnosys 0:d8f50b1e384f 448 a2 = MCP_TXB1CTRL;
tecnosys 0:d8f50b1e384f 449 a3 = MCP_TXB2CTRL;
tecnosys 0:d8f50b1e384f 450 for (i = 0; i < 14; i++) { // in-buffer loop
tecnosys 0:d8f50b1e384f 451 setRegister(a1, 0);
tecnosys 0:d8f50b1e384f 452 setRegister(a2, 0);
tecnosys 0:d8f50b1e384f 453 setRegister(a3, 0);
tecnosys 0:d8f50b1e384f 454 a1++;
tecnosys 0:d8f50b1e384f 455 a2++;
tecnosys 0:d8f50b1e384f 456 a3++;
tecnosys 0:d8f50b1e384f 457 }
tecnosys 1:dbc44582f2f8 458 */
tecnosys 0:d8f50b1e384f 459 // and clear, deactivate the two receive buffers.
tecnosys 1:dbc44582f2f8 460 // setRegister(MCP_RXB0CTRL, 0);
tecnosys 1:dbc44582f2f8 461 //setRegister(MCP_RXB1CTRL, 0);
tecnosys 0:d8f50b1e384f 462 }
tecnosys 0:d8f50b1e384f 463
tecnosys 1:dbc44582f2f8 464 uint8_t mcp2515::init( int canSpeed) {
tecnosys 0:d8f50b1e384f 465 uint8_t res;
tecnosys 1:dbc44582f2f8 466
tecnosys 0:d8f50b1e384f 467 _deselect();
tecnosys 0:d8f50b1e384f 468 //MCP_CS_DDR |= ( 1 << MCP_CS_BIT );
tecnosys 1:dbc44582f2f8 469
tecnosys 0:d8f50b1e384f 470 _reset();
tecnosys 1:dbc44582f2f8 471
tecnosys 0:d8f50b1e384f 472
tecnosys 0:d8f50b1e384f 473 res = setCANCTRL_Mode(MODE_CONFIG);
tecnosys 1:dbc44582f2f8 474
tecnosys 1:dbc44582f2f8 475 if ( res == MCP2515_FAIL ) {
tecnosys 1:dbc44582f2f8 476 printf("\r\nCAN init failed %d\n\r",&_ncs);
tecnosys 1:dbc44582f2f8 477 return res; /* function exit on error */
tecnosys 0:d8f50b1e384f 478 }
tecnosys 1:dbc44582f2f8 479 res = configRate2(canSpeed);
driscoll85 10:6d6fd99da044 480 //res = configRate(CAN_500KBPS_10MHz);
tecnosys 1:dbc44582f2f8 481
tecnosys 0:d8f50b1e384f 482 if ( res == MCP2515_OK ) {
tecnosys 0:d8f50b1e384f 483 initCANBuffers();
tecnosys 1:dbc44582f2f8 484
tecnosys 0:d8f50b1e384f 485 // enable both receive-buffers to receive messages
tecnosys 0:d8f50b1e384f 486 // with std. and ext. identifiers
tecnosys 0:d8f50b1e384f 487 // and enable rollover
tecnosys 1:dbc44582f2f8 488 modifyRegister(MCP_RXB0CTRL,
tecnosys 1:dbc44582f2f8 489 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
tecnosys 1:dbc44582f2f8 490 MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
tecnosys 1:dbc44582f2f8 491 modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK,
tecnosys 1:dbc44582f2f8 492 MCP_RXB_RX_STDEXT);
tecnosys 0:d8f50b1e384f 493
tecnosys 1:dbc44582f2f8 494 // Prescaler setting of the CLKOUT pin to zero
tecnosys 1:dbc44582f2f8 495 // => Spending clock frequency of the CLKOUT pin MCP2515
tecnosys 1:dbc44582f2f8 496 modifyRegister (MCP_CANCTRL, 0x07, CLKOUT_ENABLE);
tecnosys 0:d8f50b1e384f 497 }
tecnosys 1:dbc44582f2f8 498
tecnosys 0:d8f50b1e384f 499 return res;
tecnosys 0:d8f50b1e384f 500 }
tecnosys 0:d8f50b1e384f 501
tecnosys 0:d8f50b1e384f 502 /*
tecnosys 0:d8f50b1e384f 503 * Select function
tecnosys 0:d8f50b1e384f 504 */
tecnosys 1:dbc44582f2f8 505
tecnosys 0:d8f50b1e384f 506 void mcp2515::_select() {
tecnosys 0:d8f50b1e384f 507 //printf("{");
tecnosys 0:d8f50b1e384f 508 _ncs = 0;
tecnosys 0:d8f50b1e384f 509 }
tecnosys 0:d8f50b1e384f 510
tecnosys 0:d8f50b1e384f 511
tecnosys 0:d8f50b1e384f 512 /*
tecnosys 0:d8f50b1e384f 513 * Deselect function
tecnosys 0:d8f50b1e384f 514 */
tecnosys 0:d8f50b1e384f 515
tecnosys 0:d8f50b1e384f 516 void mcp2515::_deselect() {
tecnosys 0:d8f50b1e384f 517 _ncs = 1;
tecnosys 0:d8f50b1e384f 518 //printf("}");
tecnosys 0:d8f50b1e384f 519 }
tecnosys 0:d8f50b1e384f 520
tecnosys 0:d8f50b1e384f 521 int mcp2515::status() {
tecnosys 0:d8f50b1e384f 522 int status = 0;
tecnosys 0:d8f50b1e384f 523 _select();
tecnosys 1:dbc44582f2f8 524 spi.write(0xd7);
tecnosys 1:dbc44582f2f8 525 status = (spi.write(0x00) << 8 );
tecnosys 1:dbc44582f2f8 526 status |= spi.write(0x00);
tecnosys 0:d8f50b1e384f 527 _deselect();
tecnosys 0:d8f50b1e384f 528 return status;
tecnosys 0:d8f50b1e384f 529 }
tecnosys 0:d8f50b1e384f 530
tecnosys 0:d8f50b1e384f 531 void mcp2515::_pollbusy() {
tecnosys 0:d8f50b1e384f 532 volatile int busy = 1;
tecnosys 0:d8f50b1e384f 533 while (busy) {
tecnosys 0:d8f50b1e384f 534 // if bit 7 is set, we can proceed
tecnosys 0:d8f50b1e384f 535 if ( status() & 0x80 ) {
tecnosys 0:d8f50b1e384f 536 busy = 0;
tecnosys 0:d8f50b1e384f 537 }
tecnosys 0:d8f50b1e384f 538 }
tecnosys 0:d8f50b1e384f 539 }
tecnosys 0:d8f50b1e384f 540
tecnosys 0:d8f50b1e384f 541
tecnosys 1:dbc44582f2f8 542 uint8_t mcp2515::_spi_readwrite(uint8_t data) {
tecnosys 1:dbc44582f2f8 543 //printf("W0x%x ", data);
tecnosys 1:dbc44582f2f8 544 uint8_t ret = spi.write(data);
tecnosys 1:dbc44582f2f8 545 // printf("R0x%x,", ret);
tecnosys 0:d8f50b1e384f 546 return ret;
tecnosys 0:d8f50b1e384f 547 }
tecnosys 0:d8f50b1e384f 548
tecnosys 1:dbc44582f2f8 549 uint8_t mcp2515::_spi_read(void) {
tecnosys 0:d8f50b1e384f 550 return _spi_readwrite(SPI_NULL);
tecnosys 0:d8f50b1e384f 551 }
tecnosys 1:dbc44582f2f8 552
tecnosys 1:dbc44582f2f8 553 void mcp2515::dumpExtendedStatus(void) {
tecnosys 1:dbc44582f2f8 554 uint8_t tec, rec, eflg;
tecnosys 1:dbc44582f2f8 555
tecnosys 1:dbc44582f2f8 556 tec = readRegister(MCP_TEC);
tecnosys 1:dbc44582f2f8 557 rec = readRegister(MCP_REC);
tecnosys 1:dbc44582f2f8 558 eflg = readRegister(MCP_EFLG);
tecnosys 1:dbc44582f2f8 559
tecnosys 1:dbc44582f2f8 560 printf("MCP2515 Extended Status:\n\r");
tecnosys 1:dbc44582f2f8 561 printf("MCP Transmit Error Count %d \r\n", tec);
tecnosys 1:dbc44582f2f8 562 printf("MCP Receiver Error Count %d \n\r", rec);
tecnosys 1:dbc44582f2f8 563 printf("MCP Error Flag %d\n\r", eflg);
tecnosys 1:dbc44582f2f8 564
tecnosys 1:dbc44582f2f8 565 if ( (rec>127) || (tec>127) ) {
tecnosys 1:dbc44582f2f8 566 printf("Error-Passive or Bus-Off\n\r");
tecnosys 1:dbc44582f2f8 567 }
tecnosys 1:dbc44582f2f8 568
tecnosys 1:dbc44582f2f8 569 if (eflg & MCP_EFLG_RX1OVR)
tecnosys 1:dbc44582f2f8 570 printf("Receive Buffer 1 Overflow\r\n");
tecnosys 1:dbc44582f2f8 571 if (eflg & MCP_EFLG_RX0OVR)
tecnosys 1:dbc44582f2f8 572 printf("Receive Buffer 0 Overflow\n\r");
tecnosys 1:dbc44582f2f8 573 if (eflg & MCP_EFLG_TXBO)
tecnosys 1:dbc44582f2f8 574 printf("Bus-Off\n\r");
tecnosys 1:dbc44582f2f8 575 if (eflg & MCP_EFLG_TXEP)
tecnosys 1:dbc44582f2f8 576 printf("Receive Error Passive\n\r");
tecnosys 1:dbc44582f2f8 577 if (eflg & MCP_EFLG_TXWAR)
tecnosys 1:dbc44582f2f8 578 printf("Transmit Error Warning\n\r");
tecnosys 1:dbc44582f2f8 579 if (eflg & MCP_EFLG_RXWAR)
tecnosys 1:dbc44582f2f8 580 printf("Receive Error Warning\r\n");
tecnosys 1:dbc44582f2f8 581 if (eflg & MCP_EFLG_EWARN )
tecnosys 1:dbc44582f2f8 582 printf("Receive Error Warning\n\r");
tecnosys 1:dbc44582f2f8 583 }