Dependents:   Kamal_CAN ReadFromSerial446 USNA-UMBC-KF-02_v3-noise USNA-UMBC-KF-01

Committer:
tecnosys
Date:
Mon Oct 18 13:40:02 2010 +0000
Revision:
8:872137b3a8a8
Parent:
6:36e854e627f6
0.1

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
tecnosys 0:d8f50b1e384f 30 * LPC1768 platform by J.Engelman. And does'nt 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) :
tecnosys 1:dbc44582f2f8 92 cfg1 = 0x04;
tecnosys 1:dbc44582f2f8 93 cfg2 = 0xA0;
tecnosys 1:dbc44582f2f8 94 cfg3 = 0x02;
tecnosys 1:dbc44582f2f8 95 case (CAN_50KBPS_8MHZ) :
tecnosys 1:dbc44582f2f8 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) :
tecnosys 1:dbc44582f2f8 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) :
tecnosys 1:dbc44582f2f8 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;
tecnosys 0:d8f50b1e384f 111 default:
tecnosys 0:d8f50b1e384f 112 set = 0;
tecnosys 0:d8f50b1e384f 113 break;
tecnosys 0:d8f50b1e384f 114 }
tecnosys 1:dbc44582f2f8 115
tecnosys 0:d8f50b1e384f 116 if (set) {
tecnosys 0:d8f50b1e384f 117 setRegister(MCP_CNF1, cfg1);
tecnosys 0:d8f50b1e384f 118 setRegister(MCP_CNF2, cfg2);
tecnosys 0:d8f50b1e384f 119 setRegister(MCP_CNF3, cfg3);
tecnosys 0:d8f50b1e384f 120 return MCP2515_OK;
tecnosys 1:dbc44582f2f8 121 } else {
tecnosys 0:d8f50b1e384f 122 return MCP2515_FAIL;
tecnosys 0:d8f50b1e384f 123 }
tecnosys 1:dbc44582f2f8 124 }
tecnosys 1:dbc44582f2f8 125
tecnosys 1:dbc44582f2f8 126 int mcp2515::configRate2(int bit_rate)
tecnosys 1:dbc44582f2f8 127 {
tecnosys 1:dbc44582f2f8 128 //struct spi_device *spi = to_spi_device(can->cdev.dev);
tecnosys 1:dbc44582f2f8 129 //struct mcp251x *chip = dev_get_drvdata(&spi->dev);
tecnosys 1:dbc44582f2f8 130 //struct mcp251x_platform_data *pdata = spi->dev.platform_data;
tecnosys 1:dbc44582f2f8 131
tecnosys 1:dbc44582f2f8 132 printf("\n\rcanspeed=%d",bit_rate);
tecnosys 6:36e854e627f6 133 int f_osc = 16000000; //4000000; //4Mhz
tecnosys 1:dbc44582f2f8 134 int tqs; /* tbit/TQ */
tecnosys 1:dbc44582f2f8 135 int brp;
tecnosys 1:dbc44582f2f8 136 int ps1, ps2, propseg, sjw;
tecnosys 1:dbc44582f2f8 137
tecnosys 1:dbc44582f2f8 138 /* Determine the BRP value that gives the requested bit rate. */
tecnosys 1:dbc44582f2f8 139 for(brp = 0; brp < 8; brp++) {
tecnosys 1:dbc44582f2f8 140 tqs = f_osc / (2 * (brp + 1)) / bit_rate;
tecnosys 1:dbc44582f2f8 141 if (tqs >= 5 && tqs <= 25
tecnosys 1:dbc44582f2f8 142 && (f_osc / (2 * (brp + 1)) / tqs) == bit_rate)
tecnosys 1:dbc44582f2f8 143 break;
tecnosys 1:dbc44582f2f8 144 }
tecnosys 1:dbc44582f2f8 145 if (brp >= 8) printf("Spaztic BRP");
tecnosys 1:dbc44582f2f8 146 // return -1;
tecnosys 0:d8f50b1e384f 147
tecnosys 1:dbc44582f2f8 148 /* The CAN bus bit time (tbit) is determined by:
tecnosys 1:dbc44582f2f8 149 * tbit = (SyncSeg + PropSeg + PS1 + PS2) * TQ
tecnosys 1:dbc44582f2f8 150 * with:
tecnosys 1:dbc44582f2f8 151 * SyncSeg = 1
tecnosys 1:dbc44582f2f8 152 * sample point (between PS1 and PS2) must be at 60%-70% of the bit time
tecnosys 1:dbc44582f2f8 153 * PropSeg + PS1 >= PS2
tecnosys 1:dbc44582f2f8 154 * PropSeg + PS1 >= Tdelay
tecnosys 1:dbc44582f2f8 155 * PS2 > SJW
tecnosys 1:dbc44582f2f8 156 * 1 <= PropSeg <= 8, 1 <= PS1 <=8, 2 <= PS2 <= 8
tecnosys 1:dbc44582f2f8 157 * SJW = 1 is sufficient in most cases.
tecnosys 1:dbc44582f2f8 158 * Tdelay is usually 1 or 2 TQ.
tecnosys 1:dbc44582f2f8 159 */
tecnosys 1:dbc44582f2f8 160
tecnosys 1:dbc44582f2f8 161 propseg = ps1 = ps2 = (tqs - 1) / 3;
tecnosys 1:dbc44582f2f8 162 if (tqs - (1 + propseg + ps1 + ps2) == 2)
tecnosys 1:dbc44582f2f8 163 ps1++;
tecnosys 1:dbc44582f2f8 164 if (tqs - (1 + propseg + ps1 + ps2) == 1)
tecnosys 1:dbc44582f2f8 165 ps2++;
tecnosys 1:dbc44582f2f8 166 sjw = 1;
tecnosys 1:dbc44582f2f8 167
tecnosys 1:dbc44582f2f8 168 printf("\n\rbit rate: BRP = %d, Tbit = %d TQ, PropSeg = %d, PS1 = %d, PS2 = %d, SJW = %d\n",
tecnosys 1:dbc44582f2f8 169 brp, tqs, propseg, ps1, ps2, sjw);
tecnosys 1:dbc44582f2f8 170
tecnosys 1:dbc44582f2f8 171 /* Since we can only change the bit rate when the network device is
tecnosys 1:dbc44582f2f8 172 * down the chip must be in sleep mode. Wake it up and put it into
tecnosys 1:dbc44582f2f8 173 * config mode. */
tecnosys 1:dbc44582f2f8 174 //mcp251x_hw_wakeup(spi);
tecnosys 1:dbc44582f2f8 175 //mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_CONF);
tecnosys 1:dbc44582f2f8 176
tecnosys 1:dbc44582f2f8 177 //mcp251x_write_reg(spi, CNF1, ((sjw-1) << 6) | brp);
tecnosys 1:dbc44582f2f8 178 //mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1));
tecnosys 1:dbc44582f2f8 179 //mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, (ps2-1));
tecnosys 1:dbc44582f2f8 180 setRegister(MCP_CNF1, ((sjw-1) << 6) | brp );
tecnosys 1:dbc44582f2f8 181 setRegister(MCP_CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1) );
tecnosys 1:dbc44582f2f8 182 modifyRegister(MCP_CNF3, CNF3_PHSEG2_MASK, (ps2-1) );
tecnosys 1:dbc44582f2f8 183 //mcp251x_hw_sleep(spi);
tecnosys 1:dbc44582f2f8 184
tecnosys 1:dbc44582f2f8 185 /* Calculate actual bit rate. */
tecnosys 1:dbc44582f2f8 186 //chip->bit_rate = pdata->f_osc / (2 * (brp + 1)) / tqs;
tecnosys 1:dbc44582f2f8 187
tecnosys 1:dbc44582f2f8 188 return 0;
tecnosys 1:dbc44582f2f8 189 }
tecnosys 1:dbc44582f2f8 190
tecnosys 1:dbc44582f2f8 191 uint8_t mcp2515::readRegister( uint8_t address) {
tecnosys 0:d8f50b1e384f 192 uint8_t ret;
tecnosys 1:dbc44582f2f8 193
tecnosys 0:d8f50b1e384f 194 _select();
tecnosys 0:d8f50b1e384f 195 _spi_readwrite(MCP_READ);
tecnosys 0:d8f50b1e384f 196 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 197 ret = _spi_read();
tecnosys 0:d8f50b1e384f 198 _deselect();
tecnosys 1:dbc44582f2f8 199
tecnosys 0:d8f50b1e384f 200 return ret;
tecnosys 0:d8f50b1e384f 201 }
tecnosys 0:d8f50b1e384f 202
tecnosys 1:dbc44582f2f8 203 void mcp2515::readRegisterS( uint8_t address,
tecnosys 1:dbc44582f2f8 204 uint8_t values[], uint8_t n) {
tecnosys 0:d8f50b1e384f 205 uint8_t i;
tecnosys 1:dbc44582f2f8 206
tecnosys 0:d8f50b1e384f 207 _select();
tecnosys 0:d8f50b1e384f 208 _spi_readwrite(MCP_READ);
tecnosys 0:d8f50b1e384f 209 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 210 // mcp2515 has auto-increment of address-pointer
tecnosys 0:d8f50b1e384f 211 for (i=0; i<n; i++) {
tecnosys 0:d8f50b1e384f 212 values[i] = _spi_read();
tecnosys 0:d8f50b1e384f 213 }
tecnosys 0:d8f50b1e384f 214 _deselect();
tecnosys 0:d8f50b1e384f 215 }
tecnosys 0:d8f50b1e384f 216
tecnosys 1:dbc44582f2f8 217 void mcp2515::modifyRegister( uint8_t address,
tecnosys 1:dbc44582f2f8 218 uint8_t mask, uint8_t data) {
tecnosys 0:d8f50b1e384f 219 _select();
tecnosys 0:d8f50b1e384f 220 _spi_readwrite(MCP_BITMOD);
tecnosys 0:d8f50b1e384f 221 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 222 _spi_readwrite(mask);
tecnosys 0:d8f50b1e384f 223 _spi_readwrite(data);
tecnosys 0:d8f50b1e384f 224 _deselect();
tecnosys 0:d8f50b1e384f 225 }
tecnosys 0:d8f50b1e384f 226
tecnosys 0:d8f50b1e384f 227
tecnosys 1:dbc44582f2f8 228 uint8_t mcp2515::readXXStatus_helper( uint8_t cmd) {
tecnosys 0:d8f50b1e384f 229 uint8_t i;
tecnosys 1:dbc44582f2f8 230
tecnosys 0:d8f50b1e384f 231 _select();
tecnosys 0:d8f50b1e384f 232 _spi_readwrite(cmd);
tecnosys 0:d8f50b1e384f 233 i = _spi_read();
tecnosys 0:d8f50b1e384f 234 _deselect();
tecnosys 1:dbc44582f2f8 235
tecnosys 0:d8f50b1e384f 236 return i;
tecnosys 0:d8f50b1e384f 237 }
tecnosys 1:dbc44582f2f8 238
tecnosys 1:dbc44582f2f8 239 uint8_t mcp2515::readStatus(void) {
tecnosys 0:d8f50b1e384f 240 return readXXStatus_helper(MCP_READ_STATUS);
tecnosys 0:d8f50b1e384f 241 }
tecnosys 0:d8f50b1e384f 242
tecnosys 1:dbc44582f2f8 243 uint8_t mcp2515::RXStatus(void) {
tecnosys 0:d8f50b1e384f 244 return readXXStatus_helper(MCP_RX_STATUS);
tecnosys 0:d8f50b1e384f 245 }
tecnosys 0:d8f50b1e384f 246
tecnosys 0:d8f50b1e384f 247 // read-modify-write - better: Bit Modify Instruction
tecnosys 1:dbc44582f2f8 248 uint8_t mcp2515::setCANCTRL_Mode(uint8_t newmode) {
tecnosys 1:dbc44582f2f8 249
tecnosys 0:d8f50b1e384f 250 uint8_t i;
tecnosys 1:dbc44582f2f8 251
tecnosys 0:d8f50b1e384f 252 i = readRegister(MCP_CANCTRL);
tecnosys 0:d8f50b1e384f 253 i &= ~(MODE_MASK);
tecnosys 0:d8f50b1e384f 254 i |= newmode;
tecnosys 0:d8f50b1e384f 255 setRegister(MCP_CANCTRL, i);
tecnosys 1:dbc44582f2f8 256
tecnosys 0:d8f50b1e384f 257 // verify as advised in datasheet
tecnosys 0:d8f50b1e384f 258 i = readRegister(MCP_CANCTRL);
tecnosys 0:d8f50b1e384f 259 i &= MODE_MASK;
tecnosys 0:d8f50b1e384f 260 if ( i == newmode ) {
tecnosys 1:dbc44582f2f8 261 return MCP2515_OK;
tecnosys 1:dbc44582f2f8 262 } else {
tecnosys 0:d8f50b1e384f 263 return MCP2515_FAIL;
tecnosys 0:d8f50b1e384f 264 }
tecnosys 1:dbc44582f2f8 265
tecnosys 0:d8f50b1e384f 266 }
tecnosys 0:d8f50b1e384f 267
tecnosys 0:d8f50b1e384f 268
tecnosys 1:dbc44582f2f8 269 void mcp2515::setRegisterS( uint8_t address,
tecnosys 1:dbc44582f2f8 270 uint8_t values[], uint8_t n) {
tecnosys 0:d8f50b1e384f 271 uint8_t i;
tecnosys 1:dbc44582f2f8 272
tecnosys 0:d8f50b1e384f 273 _select();
tecnosys 0:d8f50b1e384f 274 _spi_readwrite(MCP_WRITE);
tecnosys 0:d8f50b1e384f 275 _spi_readwrite(address);
tecnosys 0:d8f50b1e384f 276 // mcp2515 has auto-increment of address-pointer
tecnosys 0:d8f50b1e384f 277 for (i=0; i<n; i++) {
tecnosys 0:d8f50b1e384f 278 _spi_readwrite(values[i]);
tecnosys 0:d8f50b1e384f 279 }
tecnosys 0:d8f50b1e384f 280 _deselect();
tecnosys 0:d8f50b1e384f 281 }
tecnosys 0:d8f50b1e384f 282
tecnosys 1:dbc44582f2f8 283 void mcp2515::read_can_id( uint8_t mcp_addr,
tecnosys 1:dbc44582f2f8 284 uint8_t* ext, uint32_t* can_id ) {
tecnosys 0:d8f50b1e384f 285 uint8_t tbufdata[4];
tecnosys 1:dbc44582f2f8 286
tecnosys 0:d8f50b1e384f 287 *ext = 0;
tecnosys 0:d8f50b1e384f 288 *can_id = 0;
tecnosys 1:dbc44582f2f8 289
tecnosys 0:d8f50b1e384f 290 readRegisterS( mcp_addr, tbufdata, 4 );
tecnosys 1:dbc44582f2f8 291
tecnosys 0:d8f50b1e384f 292 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5);
tecnosys 1:dbc44582f2f8 293
tecnosys 0:d8f50b1e384f 294 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) {
tecnosys 0:d8f50b1e384f 295 // extended id
tecnosys 0:d8f50b1e384f 296 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03);
tecnosys 0:d8f50b1e384f 297 *can_id <<= 16;
tecnosys 0:d8f50b1e384f 298 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0];
tecnosys 0:d8f50b1e384f 299 *ext = 1;
tecnosys 0:d8f50b1e384f 300 }
tecnosys 0:d8f50b1e384f 301 }
tecnosys 0:d8f50b1e384f 302
tecnosys 0:d8f50b1e384f 303
tecnosys 1:dbc44582f2f8 304 void mcp2515::read_can_idN( uint8_t mcp_addr,
tecnosys 1:dbc44582f2f8 305 CANFormat* ext, unsigned int* can_id ) {
tecnosys 1:dbc44582f2f8 306 uint8_t tbufdata[4];
tecnosys 1:dbc44582f2f8 307
tecnosys 1:dbc44582f2f8 308 *ext = CANStandard;
tecnosys 1:dbc44582f2f8 309 *can_id = 0;
tecnosys 1:dbc44582f2f8 310
tecnosys 1:dbc44582f2f8 311 readRegisterS( mcp_addr, tbufdata, 4 );
tecnosys 1:dbc44582f2f8 312
tecnosys 1:dbc44582f2f8 313 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5);
tecnosys 1:dbc44582f2f8 314
tecnosys 1:dbc44582f2f8 315 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) {
tecnosys 1:dbc44582f2f8 316 // extended id
tecnosys 1:dbc44582f2f8 317 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03);
tecnosys 1:dbc44582f2f8 318 *can_id <<= 16;
tecnosys 1:dbc44582f2f8 319 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0];
tecnosys 1:dbc44582f2f8 320 *ext = CANExtended;//1;
tecnosys 1:dbc44582f2f8 321 }
tecnosys 1:dbc44582f2f8 322 }
tecnosys 1:dbc44582f2f8 323
tecnosys 0:d8f50b1e384f 324 // Buffer can be MCP_RXBUF_0 or MCP_RXBUF_1
tecnosys 1:dbc44582f2f8 325 void mcp2515::read_canMsg( uint8_t buffer_sidh_addr, CANMessage* msg)
tecnosys 1:dbc44582f2f8 326 //CANMessage mcp2515::read_canMsg( uint8_t buffer_sidh_addr)
tecnosys 0:d8f50b1e384f 327 {
tecnosys 1:dbc44582f2f8 328 uint8_t mcp_addr, ctrl,dlc;
tecnosys 1:dbc44582f2f8 329
tecnosys 1:dbc44582f2f8 330
tecnosys 0:d8f50b1e384f 331
tecnosys 0:d8f50b1e384f 332 mcp_addr = buffer_sidh_addr;
tecnosys 1:dbc44582f2f8 333
tecnosys 1:dbc44582f2f8 334 read_can_idN( mcp_addr, &msg->format, &msg->id );
tecnosys 1:dbc44582f2f8 335
tecnosys 0:d8f50b1e384f 336 ctrl = readRegister( mcp_addr-1 );
tecnosys 1:dbc44582f2f8 337 dlc = readRegister( mcp_addr+4 );
tecnosys 1:dbc44582f2f8 338
tecnosys 0:d8f50b1e384f 339 //if ((*dlc & RTR_MASK) || (ctrl & 0x08)) {
tecnosys 0:d8f50b1e384f 340 if ((ctrl & 0x08)) {
tecnosys 1:dbc44582f2f8 341 msg->type = CANRemote; //1 CANRemote
tecnosys 0:d8f50b1e384f 342 } else {
tecnosys 1:dbc44582f2f8 343 msg->type = CANData; //0 CANData
tecnosys 0:d8f50b1e384f 344 }
tecnosys 1:dbc44582f2f8 345
tecnosys 1:dbc44582f2f8 346 dlc &= MCP_DLC_MASK;
tecnosys 1:dbc44582f2f8 347 readRegisterS( mcp_addr+5, &(msg->data[0]), dlc );
tecnosys 1:dbc44582f2f8 348 msg->len =dlc;
tecnosys 1:dbc44582f2f8 349
tecnosys 0:d8f50b1e384f 350 }
tecnosys 0:d8f50b1e384f 351
tecnosys 1:dbc44582f2f8 352 void mcp2515::setDebugConsole(Serial c){
tecnosys 1:dbc44582f2f8 353 //console=c;
tecnosys 1:dbc44582f2f8 354 debug=true;
tecnosys 1:dbc44582f2f8 355 }
tecnosys 0:d8f50b1e384f 356
tecnosys 1:dbc44582f2f8 357 void mcp2515::write_can_id( uint8_t mcp_addr,
tecnosys 1:dbc44582f2f8 358 uint8_t ext, uint32_t can_id ) {
tecnosys 0:d8f50b1e384f 359 uint16_t canid;
tecnosys 0:d8f50b1e384f 360 uint8_t tbufdata[4];
tecnosys 1:dbc44582f2f8 361
tecnosys 0:d8f50b1e384f 362 canid = (uint16_t)(can_id & 0x0FFFF);
tecnosys 1:dbc44582f2f8 363
tecnosys 0:d8f50b1e384f 364 if ( ext == 1) {
tecnosys 0:d8f50b1e384f 365 tbufdata[MCP_EID0] = (uint8_t) (canid & 0xFF);
tecnosys 0:d8f50b1e384f 366 tbufdata[MCP_EID8] = (uint8_t) (canid / 256);
tecnosys 0:d8f50b1e384f 367 canid = (uint16_t)( can_id / 0x10000L );
tecnosys 0:d8f50b1e384f 368 tbufdata[MCP_SIDL] = (uint8_t) (canid & 0x03);
tecnosys 0:d8f50b1e384f 369 tbufdata[MCP_SIDL] += (uint8_t) ((canid & 0x1C )*8);
tecnosys 0:d8f50b1e384f 370 tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M;
tecnosys 0:d8f50b1e384f 371 tbufdata[MCP_SIDH] = (uint8_t) (canid / 32 );
tecnosys 1:dbc44582f2f8 372 } else {
tecnosys 0:d8f50b1e384f 373 tbufdata[MCP_SIDH] = (uint8_t) (canid / 8 );
tecnosys 0:d8f50b1e384f 374 tbufdata[MCP_SIDL] = (uint8_t) ((canid & 0x07 )*32);
tecnosys 0:d8f50b1e384f 375 tbufdata[MCP_EID0] = 0;
tecnosys 0:d8f50b1e384f 376 tbufdata[MCP_EID8] = 0;
tecnosys 0:d8f50b1e384f 377 }
tecnosys 0:d8f50b1e384f 378 setRegisterS( mcp_addr, tbufdata, 4 );
tecnosys 0:d8f50b1e384f 379 }
tecnosys 0:d8f50b1e384f 380
tecnosys 0:d8f50b1e384f 381 // Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2
tecnosys 1:dbc44582f2f8 382 void mcp2515::write_canMsg( uint8_t buffer_sidh_addr,
tecnosys 1:dbc44582f2f8 383 CANMessage* msg) {
tecnosys 0:d8f50b1e384f 384 uint8_t mcp_addr, dlc;
tecnosys 0:d8f50b1e384f 385
tecnosys 0:d8f50b1e384f 386 mcp_addr = buffer_sidh_addr;
tecnosys 0:d8f50b1e384f 387 dlc = msg->len;
tecnosys 1:dbc44582f2f8 388
tecnosys 0:d8f50b1e384f 389 setRegisterS(mcp_addr+5, &(msg->data[0]), dlc ); // write data bytes
tecnosys 0:d8f50b1e384f 390 write_can_id( mcp_addr, msg->format,
tecnosys 1:dbc44582f2f8 391 msg->id ); // write CAN id
tecnosys 0:d8f50b1e384f 392 if ( msg->type == 1) dlc |= MCP_RTR_MASK; // if RTR set bit in byte
tecnosys 0:d8f50b1e384f 393 setRegister( (mcp_addr+4), dlc ); // write the RTR and DLC
tecnosys 0:d8f50b1e384f 394 }
tecnosys 0:d8f50b1e384f 395
tecnosys 1:dbc44582f2f8 396 void mcp2515::start_transmit( uint8_t buffer_sidh_addr) {
tecnosys 1:dbc44582f2f8 397 // TXBnCTRL_addr = TXBnSIDH_addr - 1
tecnosys 1:dbc44582f2f8 398 modifyRegister( buffer_sidh_addr-1 , MCP_TXB_TXREQ_M,
tecnosys 1:dbc44582f2f8 399 MCP_TXB_TXREQ_M );
tecnosys 0:d8f50b1e384f 400 }
tecnosys 0:d8f50b1e384f 401
tecnosys 1:dbc44582f2f8 402 uint8_t mcp2515::getNextFreeTXBuf(uint8_t *txbuf_n) {
tecnosys 1:dbc44582f2f8 403 uint8_t res, i, ctrlval;
tecnosys 1:dbc44582f2f8 404 uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL };
tecnosys 1:dbc44582f2f8 405
tecnosys 1:dbc44582f2f8 406 res = MCP_ALLTXBUSY;
tecnosys 1:dbc44582f2f8 407 *txbuf_n = 0x00;
tecnosys 0:d8f50b1e384f 408
tecnosys 1:dbc44582f2f8 409 // check all 3 TX-Buffers
tecnosys 1:dbc44582f2f8 410 for (i=0; i<MCP_N_TXBUFFERS; i++) {
tecnosys 1:dbc44582f2f8 411 ctrlval = readRegister( ctrlregs[i] );
tecnosys 1:dbc44582f2f8 412 if ( (ctrlval & MCP_TXB_TXREQ_M) == 0 ) {
tecnosys 1:dbc44582f2f8 413
tecnosys 1:dbc44582f2f8 414 *txbuf_n = ctrlregs[i]+1; // return SIDH-address of Buffer
tecnosys 1:dbc44582f2f8 415 res = MCP2515_OK;
tecnosys 1:dbc44582f2f8 416 return res; /* ! function exit */
tecnosys 1:dbc44582f2f8 417 }
tecnosys 1:dbc44582f2f8 418 }
tecnosys 1:dbc44582f2f8 419
tecnosys 1:dbc44582f2f8 420 return res;
tecnosys 0:d8f50b1e384f 421 }
tecnosys 0:d8f50b1e384f 422
tecnosys 1:dbc44582f2f8 423 void mcp2515::initCANBuffers(void) {
tecnosys 1:dbc44582f2f8 424 // uint8_t i, a1, a2, a3;
tecnosys 1:dbc44582f2f8 425
tecnosys 1:dbc44582f2f8 426 // TODO: check why this is needed to receive extended
tecnosys 0:d8f50b1e384f 427 // and standard frames
tecnosys 0:d8f50b1e384f 428 // Mark all filter bits as don't care:
tecnosys 0:d8f50b1e384f 429 write_can_id(MCP_RXM0SIDH, 0, 0);
tecnosys 0:d8f50b1e384f 430 write_can_id(MCP_RXM1SIDH, 0, 0);
tecnosys 0:d8f50b1e384f 431 // Anyway, set all filters to 0:
tecnosys 1:dbc44582f2f8 432 write_can_id(MCP_RXF0SIDH, 1, 0); // RXB0: extended
tecnosys 0:d8f50b1e384f 433 write_can_id(MCP_RXF1SIDH, 0, 0); // AND standard
tecnosys 1:dbc44582f2f8 434 write_can_id(MCP_RXF2SIDH, 1, 0); // RXB1: extended
tecnosys 0:d8f50b1e384f 435 write_can_id(MCP_RXF3SIDH, 0, 0); // AND standard
tecnosys 0:d8f50b1e384f 436 write_can_id(MCP_RXF4SIDH, 0, 0);
tecnosys 0:d8f50b1e384f 437 write_can_id(MCP_RXF5SIDH, 0, 0);
tecnosys 1:dbc44582f2f8 438 /*
tecnosys 0:d8f50b1e384f 439 // Clear, deactivate the three transmit buffers
tecnosys 0:d8f50b1e384f 440 // TXBnCTRL -> TXBnD7
tecnosys 0:d8f50b1e384f 441 a1 = MCP_TXB0CTRL;
tecnosys 0:d8f50b1e384f 442 a2 = MCP_TXB1CTRL;
tecnosys 0:d8f50b1e384f 443 a3 = MCP_TXB2CTRL;
tecnosys 0:d8f50b1e384f 444 for (i = 0; i < 14; i++) { // in-buffer loop
tecnosys 0:d8f50b1e384f 445 setRegister(a1, 0);
tecnosys 0:d8f50b1e384f 446 setRegister(a2, 0);
tecnosys 0:d8f50b1e384f 447 setRegister(a3, 0);
tecnosys 0:d8f50b1e384f 448 a1++;
tecnosys 0:d8f50b1e384f 449 a2++;
tecnosys 0:d8f50b1e384f 450 a3++;
tecnosys 0:d8f50b1e384f 451 }
tecnosys 1:dbc44582f2f8 452 */
tecnosys 0:d8f50b1e384f 453 // and clear, deactivate the two receive buffers.
tecnosys 1:dbc44582f2f8 454 // setRegister(MCP_RXB0CTRL, 0);
tecnosys 1:dbc44582f2f8 455 //setRegister(MCP_RXB1CTRL, 0);
tecnosys 0:d8f50b1e384f 456 }
tecnosys 0:d8f50b1e384f 457
tecnosys 1:dbc44582f2f8 458 uint8_t mcp2515::init( int canSpeed) {
tecnosys 0:d8f50b1e384f 459 uint8_t res;
tecnosys 1:dbc44582f2f8 460
tecnosys 0:d8f50b1e384f 461 _deselect();
tecnosys 0:d8f50b1e384f 462 //MCP_CS_DDR |= ( 1 << MCP_CS_BIT );
tecnosys 1:dbc44582f2f8 463
tecnosys 0:d8f50b1e384f 464 _reset();
tecnosys 1:dbc44582f2f8 465
tecnosys 0:d8f50b1e384f 466
tecnosys 0:d8f50b1e384f 467 res = setCANCTRL_Mode(MODE_CONFIG);
tecnosys 1:dbc44582f2f8 468
tecnosys 1:dbc44582f2f8 469 if ( res == MCP2515_FAIL ) {
tecnosys 1:dbc44582f2f8 470 printf("\r\nCAN init failed %d\n\r",&_ncs);
tecnosys 1:dbc44582f2f8 471 return res; /* function exit on error */
tecnosys 0:d8f50b1e384f 472 }
tecnosys 1:dbc44582f2f8 473 res = configRate2(canSpeed);
tecnosys 1:dbc44582f2f8 474
tecnosys 0:d8f50b1e384f 475 if ( res == MCP2515_OK ) {
tecnosys 0:d8f50b1e384f 476 initCANBuffers();
tecnosys 1:dbc44582f2f8 477
tecnosys 0:d8f50b1e384f 478
tecnosys 0:d8f50b1e384f 479 // enable both receive-buffers to receive messages
tecnosys 0:d8f50b1e384f 480 // with std. and ext. identifiers
tecnosys 0:d8f50b1e384f 481 // and enable rollover
tecnosys 1:dbc44582f2f8 482 modifyRegister(MCP_RXB0CTRL,
tecnosys 1:dbc44582f2f8 483 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
tecnosys 1:dbc44582f2f8 484 MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
tecnosys 1:dbc44582f2f8 485 modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK,
tecnosys 1:dbc44582f2f8 486 MCP_RXB_RX_STDEXT);
tecnosys 0:d8f50b1e384f 487
tecnosys 1:dbc44582f2f8 488 // Prescaler setting of the CLKOUT pin to zero
tecnosys 1:dbc44582f2f8 489 // => Spending clock frequency of the CLKOUT pin MCP2515
tecnosys 1:dbc44582f2f8 490 modifyRegister (MCP_CANCTRL, 0x07, CLKOUT_ENABLE);
tecnosys 0:d8f50b1e384f 491 }
tecnosys 1:dbc44582f2f8 492
tecnosys 0:d8f50b1e384f 493 return res;
tecnosys 0:d8f50b1e384f 494 }
tecnosys 0:d8f50b1e384f 495
tecnosys 0:d8f50b1e384f 496 /*
tecnosys 0:d8f50b1e384f 497 * Select function
tecnosys 0:d8f50b1e384f 498 */
tecnosys 1:dbc44582f2f8 499
tecnosys 0:d8f50b1e384f 500 void mcp2515::_select() {
tecnosys 0:d8f50b1e384f 501 //printf("{");
tecnosys 0:d8f50b1e384f 502 _ncs = 0;
tecnosys 0:d8f50b1e384f 503 }
tecnosys 0:d8f50b1e384f 504
tecnosys 0:d8f50b1e384f 505
tecnosys 0:d8f50b1e384f 506 /*
tecnosys 0:d8f50b1e384f 507 * Deselect function
tecnosys 0:d8f50b1e384f 508 */
tecnosys 0:d8f50b1e384f 509
tecnosys 0:d8f50b1e384f 510 void mcp2515::_deselect() {
tecnosys 0:d8f50b1e384f 511 _ncs = 1;
tecnosys 0:d8f50b1e384f 512 //printf("}");
tecnosys 0:d8f50b1e384f 513 }
tecnosys 0:d8f50b1e384f 514
tecnosys 0:d8f50b1e384f 515 int mcp2515::status() {
tecnosys 0:d8f50b1e384f 516 int status = 0;
tecnosys 0:d8f50b1e384f 517 _select();
tecnosys 1:dbc44582f2f8 518 spi.write(0xd7);
tecnosys 1:dbc44582f2f8 519 status = (spi.write(0x00) << 8 );
tecnosys 1:dbc44582f2f8 520 status |= spi.write(0x00);
tecnosys 0:d8f50b1e384f 521 _deselect();
tecnosys 0:d8f50b1e384f 522 return status;
tecnosys 0:d8f50b1e384f 523 }
tecnosys 0:d8f50b1e384f 524
tecnosys 0:d8f50b1e384f 525 void mcp2515::_pollbusy() {
tecnosys 0:d8f50b1e384f 526 volatile int busy = 1;
tecnosys 0:d8f50b1e384f 527 while (busy) {
tecnosys 0:d8f50b1e384f 528 // if bit 7 is set, we can proceed
tecnosys 0:d8f50b1e384f 529 if ( status() & 0x80 ) {
tecnosys 0:d8f50b1e384f 530 busy = 0;
tecnosys 0:d8f50b1e384f 531 }
tecnosys 0:d8f50b1e384f 532 }
tecnosys 0:d8f50b1e384f 533 }
tecnosys 0:d8f50b1e384f 534
tecnosys 0:d8f50b1e384f 535
tecnosys 1:dbc44582f2f8 536 uint8_t mcp2515::_spi_readwrite(uint8_t data) {
tecnosys 1:dbc44582f2f8 537 //printf("W0x%x ", data);
tecnosys 1:dbc44582f2f8 538 uint8_t ret = spi.write(data);
tecnosys 1:dbc44582f2f8 539 // printf("R0x%x,", ret);
tecnosys 0:d8f50b1e384f 540 return ret;
tecnosys 0:d8f50b1e384f 541 }
tecnosys 0:d8f50b1e384f 542
tecnosys 1:dbc44582f2f8 543 uint8_t mcp2515::_spi_read(void) {
tecnosys 0:d8f50b1e384f 544 return _spi_readwrite(SPI_NULL);
tecnosys 0:d8f50b1e384f 545 }
tecnosys 1:dbc44582f2f8 546
tecnosys 1:dbc44582f2f8 547 void mcp2515::dumpExtendedStatus(void) {
tecnosys 1:dbc44582f2f8 548 uint8_t tec, rec, eflg;
tecnosys 1:dbc44582f2f8 549
tecnosys 1:dbc44582f2f8 550 tec = readRegister(MCP_TEC);
tecnosys 1:dbc44582f2f8 551 rec = readRegister(MCP_REC);
tecnosys 1:dbc44582f2f8 552 eflg = readRegister(MCP_EFLG);
tecnosys 1:dbc44582f2f8 553
tecnosys 1:dbc44582f2f8 554 printf("MCP2515 Extended Status:\n\r");
tecnosys 1:dbc44582f2f8 555 printf("MCP Transmit Error Count %d \r\n", tec);
tecnosys 1:dbc44582f2f8 556 printf("MCP Receiver Error Count %d \n\r", rec);
tecnosys 1:dbc44582f2f8 557 printf("MCP Error Flag %d\n\r", eflg);
tecnosys 1:dbc44582f2f8 558
tecnosys 1:dbc44582f2f8 559 if ( (rec>127) || (tec>127) ) {
tecnosys 1:dbc44582f2f8 560 printf("Error-Passive or Bus-Off\n\r");
tecnosys 1:dbc44582f2f8 561 }
tecnosys 1:dbc44582f2f8 562
tecnosys 1:dbc44582f2f8 563 if (eflg & MCP_EFLG_RX1OVR)
tecnosys 1:dbc44582f2f8 564 printf("Receive Buffer 1 Overflow\r\n");
tecnosys 1:dbc44582f2f8 565 if (eflg & MCP_EFLG_RX0OVR)
tecnosys 1:dbc44582f2f8 566 printf("Receive Buffer 0 Overflow\n\r");
tecnosys 1:dbc44582f2f8 567 if (eflg & MCP_EFLG_TXBO)
tecnosys 1:dbc44582f2f8 568 printf("Bus-Off\n\r");
tecnosys 1:dbc44582f2f8 569 if (eflg & MCP_EFLG_TXEP)
tecnosys 1:dbc44582f2f8 570 printf("Receive Error Passive\n\r");
tecnosys 1:dbc44582f2f8 571 if (eflg & MCP_EFLG_TXWAR)
tecnosys 1:dbc44582f2f8 572 printf("Transmit Error Warning\n\r");
tecnosys 1:dbc44582f2f8 573 if (eflg & MCP_EFLG_RXWAR)
tecnosys 1:dbc44582f2f8 574 printf("Receive Error Warning\r\n");
tecnosys 1:dbc44582f2f8 575 if (eflg & MCP_EFLG_EWARN )
tecnosys 1:dbc44582f2f8 576 printf("Receive Error Warning\n\r");
tecnosys 1:dbc44582f2f8 577 }