MCP2515 CAN library
Fork of mcp2515 by
Embed:
(wiki syntax)
Show/hide line numbers
mcp2515.cpp
00001 /****************************************************************************** 00002 * 00003 * Controller Area Network (CAN) Demo-Application 00004 * Atmel AVR with Microchip MCP2515 00005 * 00006 * Copyright (C) 2005 Martin THOMAS, Kaiserslautern, Germany 00007 * <eversmith@heizung-thomas.de> 00008 * http://www.siwawi.arubi.uni-kl.de/avr_projects 00009 * 00010 ***************************************************************************** 00011 * 00012 * File : mcp2515.c 00013 * Version : 0.9 00014 * 00015 * Summary : MCP2515 "low-level" driver 00016 * 00017 * Parts of this code are adapted from a MCP2510 sample-application 00018 * by KVASER AB, http://www.kvaser.com (KVASER-code is marked as free) 00019 * 00020 * This code-module is free to use but you have to keep the copyright 00021 * notice. 00022 * 00023 * 00024 ***************************************************************************** 00025 * 00026 * File : mcp2515.cpp (mbed LPC1768 version) 00027 * Version : 0.1 00028 * 00029 * All credits to the nerds above, this source has been adapted for the 00030 * LPC1768 platform by J.Engelman. And doesn't require and of the copyrighted 00031 * SPI or AVR controller code that Martin or co have excluded copyright. 00032 * This module remains free. 00033 * 00034 * 00035 *****************************************************************************/ 00036 00037 #include "mcp2515.h" 00038 00039 #include "mbed.h" 00040 #include "mcp2515_can.h" 00041 #include "mcp2515_defs.h" 00042 #include "mcp2515_bittime.h" 00043 00044 #define SPI_NULL (0x00) 00045 00046 #define PHSEG11 4 00047 #define PHSEG21 1 00048 #define BTLMODE2 7 00049 //BTLMODE 0x80 (128) 00050 #define BRP2 2 00051 #define BRP1 1 00052 #define BRP0 0 00053 00054 #define CNF2_BTLMODE 0x80 00055 #define CNF3 0x28 00056 #define CNF3_SOF 0x08 00057 #define CNF3_WAKFIL 0x04 00058 #define CNF3_PHSEG2_MASK 0x07 00059 00060 mcp2515::mcp2515(SPI& _spi, PinName ncs) 00061 : spi(_spi), _ncs(ncs) { 00062 printf("\n\rmcp2515 = %d",this); 00063 printf("\n\rpin = %d",ncs); 00064 00065 } 00066 00067 00068 00069 void mcp2515::_reset() { 00070 00071 _select(); 00072 _spi_readwrite(MCP_RESET); 00073 _deselect(); 00074 wait(0.001); 00075 } 00076 00077 void mcp2515::setRegister( uint8_t address, uint8_t value) { 00078 _select(); 00079 _spi_readwrite(MCP_WRITE); 00080 _spi_readwrite(address); 00081 _spi_readwrite(value); 00082 _deselect(); 00083 } 00084 00085 uint8_t mcp2515::configRate( uint8_t canSpeed) { 00086 uint8_t set, cfg1, cfg2, cfg3; 00087 00088 set = 0; 00089 00090 switch (canSpeed) { 00091 case (CAN_500KBPS_8MHZ) : 00092 cfg1 = 0x04; 00093 cfg2 = 0xA0; 00094 cfg3 = 0x02; 00095 case (CAN_50KBPS_8MHZ) : 00096 cfg1 = 0x04; //0x09; 00097 cfg2 = 0xB8; //0x90; 00098 cfg3 = 0x05; //0x02; 00099 case (CAN_125KBPS) : 00100 cfg1 = MCP_4MHz_125kBPS_CFG1 ; 00101 cfg2 = MCP_4MHz_125kBPS_CFG2 ; 00102 cfg3 = MCP_4MHz_125kBPS_CFG3 ; 00103 set = 1; 00104 break; 00105 case (CAN_20KBPS) : 00106 cfg1 = MCP_4MHz_20kBPS_CFG1 ; 00107 cfg2 = MCP_4MHz_20kBPS_CFG2 ; 00108 cfg3 = MCP_4MHz_20kBPS_CFG3 ; 00109 set = 1; 00110 break; 00111 case (CAN_500KBPS_10MHz) : 00112 cfg1 = 0x00; 00113 cfg2 = 0x92; 00114 cfg3 = 0x02; 00115 set = 1; 00116 break; 00117 default: 00118 set = 0; 00119 break; 00120 } 00121 00122 if (set) { 00123 setRegister(MCP_CNF1, cfg1); 00124 setRegister(MCP_CNF2, cfg2); 00125 setRegister(MCP_CNF3, cfg3); 00126 return MCP2515_OK; 00127 } else { 00128 return MCP2515_FAIL; 00129 } 00130 } 00131 00132 int mcp2515::configRate2(int bit_rate) 00133 { 00134 //struct spi_device *spi = to_spi_device(can->cdev.dev); 00135 //struct mcp251x *chip = dev_get_drvdata(&spi->dev); 00136 //struct mcp251x_platform_data *pdata = spi->dev.platform_data; 00137 printf("\n\rcanspeed=%d",bit_rate); 00138 int f_osc = 20000000; 00139 int tqs; /* tbit/TQ */ 00140 int brp; 00141 int ps1, ps2, propseg, sjw; 00142 00143 /* Determine the BRP value that gives the requested bit rate. */ 00144 for(brp = 0; brp < 8; brp++) { 00145 tqs = f_osc / (2 * (brp + 1)) / bit_rate; 00146 if (tqs >= 5 && tqs <= 25 00147 && (f_osc / (2 * (brp + 1)) / tqs) == bit_rate) 00148 break; 00149 } 00150 if (brp >= 8) printf("Spaztic BRP"); 00151 // return -1; 00152 00153 /* The CAN bus bit time (tbit) is determined by: 00154 * tbit = (SyncSeg + PropSeg + PS1 + PS2) * TQ 00155 * with: 00156 * SyncSeg = 1 00157 * sample point (between PS1 and PS2) must be at 60%-70% of the bit time 00158 * PropSeg + PS1 >= PS2 00159 * PropSeg + PS1 >= Tdelay 00160 * PS2 > SJW 00161 * 1 <= PropSeg <= 8, 1 <= PS1 <=8, 2 <= PS2 <= 8 00162 * SJW = 1 is sufficient in most cases. 00163 * Tdelay is usually 1 or 2 TQ. 00164 */ 00165 00166 propseg = ps1 = ps2 = (tqs - 1) / 3; 00167 if (tqs - (1 + propseg + ps1 + ps2) == 2) 00168 ps1++; 00169 if (tqs - (1 + propseg + ps1 + ps2) == 1) 00170 ps2++; 00171 sjw = 1; 00172 00173 printf("\n\rbit rate: BRP = %d, Tbit = %d TQ, PropSeg = %d, PS1 = %d, PS2 = %d, SJW = %d\n", 00174 brp, tqs, propseg, ps1, ps2, sjw); 00175 00176 /* Since we can only change the bit rate when the network device is 00177 * down the chip must be in sleep mode. Wake it up and put it into 00178 * config mode. */ 00179 //mcp251x_hw_wakeup(spi); 00180 //mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_CONF); 00181 00182 //mcp251x_write_reg(spi, CNF1, ((sjw-1) << 6) | brp); 00183 //mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1)); 00184 //mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, (ps2-1)); 00185 setRegister(MCP_CNF1, ((sjw-1) << 6) | brp ); 00186 setRegister(MCP_CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1) ); 00187 modifyRegister(MCP_CNF3, CNF3_PHSEG2_MASK, (ps2-1) ); 00188 //mcp251x_hw_sleep(spi); 00189 00190 /* Calculate actual bit rate. */ 00191 //chip->bit_rate = pdata->f_osc / (2 * (brp + 1)) / tqs; 00192 00193 return 0; 00194 } 00195 00196 uint8_t mcp2515::readRegister( uint8_t address) { 00197 uint8_t ret; 00198 00199 _select(); 00200 _spi_readwrite(MCP_READ); 00201 _spi_readwrite(address); 00202 ret = _spi_read(); 00203 _deselect(); 00204 00205 return ret; 00206 } 00207 00208 void mcp2515::readRegisterS( uint8_t address, 00209 uint8_t values[], uint8_t n) { 00210 uint8_t i; 00211 00212 _select(); 00213 _spi_readwrite(MCP_READ); 00214 _spi_readwrite(address); 00215 // mcp2515 has auto-increment of address-pointer 00216 for (i=0; i<n; i++) { 00217 values[i] = _spi_read(); 00218 } 00219 _deselect(); 00220 } 00221 00222 void mcp2515::modifyRegister( uint8_t address, 00223 uint8_t mask, uint8_t data) { 00224 _select(); 00225 _spi_readwrite(MCP_BITMOD); 00226 _spi_readwrite(address); 00227 _spi_readwrite(mask); 00228 _spi_readwrite(data); 00229 _deselect(); 00230 } 00231 00232 00233 uint8_t mcp2515::readXXStatus_helper( uint8_t cmd) { 00234 uint8_t i; 00235 00236 _select(); 00237 _spi_readwrite(cmd); 00238 i = _spi_read(); 00239 _deselect(); 00240 00241 return i; 00242 } 00243 00244 uint8_t mcp2515::readStatus(void) { 00245 return readXXStatus_helper(MCP_READ_STATUS); 00246 } 00247 00248 uint8_t mcp2515::RXStatus(void) { 00249 return readXXStatus_helper(MCP_RX_STATUS); 00250 } 00251 00252 // read-modify-write - better: Bit Modify Instruction 00253 uint8_t mcp2515::setCANCTRL_Mode(uint8_t newmode) { 00254 00255 uint8_t i; 00256 00257 i = readRegister(MCP_CANCTRL); 00258 i &= ~(MODE_MASK); 00259 i |= newmode; 00260 setRegister(MCP_CANCTRL, i); 00261 00262 // verify as advised in datasheet 00263 i = readRegister(MCP_CANCTRL); 00264 i &= MODE_MASK; 00265 if ( i == newmode ) { 00266 return MCP2515_OK; 00267 } else { 00268 return MCP2515_FAIL; 00269 } 00270 00271 } 00272 00273 00274 void mcp2515::setRegisterS( uint8_t address, 00275 uint8_t values[], uint8_t n) { 00276 uint8_t i; 00277 00278 _select(); 00279 _spi_readwrite(MCP_WRITE); 00280 _spi_readwrite(address); 00281 // mcp2515 has auto-increment of address-pointer 00282 for (i=0; i<n; i++) { 00283 _spi_readwrite(values[i]); 00284 } 00285 _deselect(); 00286 } 00287 00288 void mcp2515::read_can_id( uint8_t mcp_addr, 00289 uint8_t* ext, uint32_t* can_id ) { 00290 uint8_t tbufdata[4]; 00291 00292 *ext = 0; 00293 *can_id = 0; 00294 00295 readRegisterS( mcp_addr, tbufdata, 4 ); 00296 00297 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5); 00298 00299 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) { 00300 // extended id 00301 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03); 00302 *can_id <<= 16; 00303 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0]; 00304 *ext = 1; 00305 } 00306 } 00307 00308 00309 void mcp2515::read_can_idN( uint8_t mcp_addr, 00310 CANFormat* ext, unsigned int* can_id ) { 00311 uint8_t tbufdata[4]; 00312 00313 *ext = CANStandard; 00314 *can_id = 0; 00315 00316 readRegisterS( mcp_addr, tbufdata, 4 ); 00317 00318 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5); 00319 00320 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) { 00321 // extended id 00322 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03); 00323 *can_id <<= 16; 00324 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0]; 00325 *ext = CANExtended;//1; 00326 } 00327 } 00328 00329 // Buffer can be MCP_RXBUF_0 or MCP_RXBUF_1 00330 void mcp2515::read_canMsg( uint8_t buffer_sidh_addr, CANMessage* msg) 00331 //CANMessage mcp2515::read_canMsg( uint8_t buffer_sidh_addr) 00332 { 00333 uint8_t mcp_addr, ctrl,dlc; 00334 00335 00336 00337 mcp_addr = buffer_sidh_addr; 00338 00339 read_can_idN( mcp_addr, &msg->format, &msg->id ); 00340 00341 ctrl = readRegister( mcp_addr-1 ); 00342 dlc = readRegister( mcp_addr+4 ); 00343 00344 //if ((*dlc & RTR_MASK) || (ctrl & 0x08)) { 00345 if ((ctrl & 0x08)) { 00346 msg->type = CANRemote; //1 CANRemote 00347 } else { 00348 msg->type = CANData; //0 CANData 00349 } 00350 00351 dlc &= MCP_DLC_MASK; 00352 readRegisterS( mcp_addr+5, &(msg->data[0]), dlc ); 00353 msg->len =dlc; 00354 00355 } 00356 00357 void mcp2515::setDebugConsole(Serial c){ 00358 //console=c; 00359 debug=true; 00360 } 00361 00362 void mcp2515::write_can_id( uint8_t mcp_addr, 00363 uint8_t ext, uint32_t can_id ) { 00364 uint16_t canid; 00365 uint8_t tbufdata[4]; 00366 00367 canid = (uint16_t)(can_id & 0x0FFFF); 00368 00369 if ( ext == 1) { 00370 tbufdata[MCP_EID0] = (uint8_t) (canid & 0xFF); 00371 tbufdata[MCP_EID8] = (uint8_t) (canid / 256); 00372 canid = (uint16_t)( can_id / 0x10000L ); 00373 tbufdata[MCP_SIDL] = (uint8_t) (canid & 0x03); 00374 tbufdata[MCP_SIDL] += (uint8_t) ((canid & 0x1C )*8); 00375 tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M; 00376 tbufdata[MCP_SIDH] = (uint8_t) (canid / 32 ); 00377 } else { 00378 tbufdata[MCP_SIDH] = (uint8_t) (canid / 8 ); 00379 tbufdata[MCP_SIDL] = (uint8_t) ((canid & 0x07 )*32); 00380 tbufdata[MCP_EID0] = 0; 00381 tbufdata[MCP_EID8] = 0; 00382 } 00383 setRegisterS( mcp_addr, tbufdata, 4 ); 00384 } 00385 00386 // Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2 00387 void mcp2515::write_canMsg( uint8_t buffer_sidh_addr, 00388 CANMessage* msg) { 00389 uint8_t mcp_addr, dlc; 00390 00391 mcp_addr = buffer_sidh_addr; 00392 dlc = msg->len; 00393 00394 setRegisterS(mcp_addr+5, &(msg->data[0]), dlc ); // write data bytes 00395 write_can_id( mcp_addr, msg->format, 00396 msg->id ); // write CAN id 00397 if ( msg->type == 1) dlc |= MCP_RTR_MASK; // if RTR set bit in byte 00398 setRegister( (mcp_addr+4), dlc ); // write the RTR and DLC 00399 } 00400 00401 void mcp2515::start_transmit( uint8_t buffer_sidh_addr) { 00402 // TXBnCTRL_addr = TXBnSIDH_addr - 1 00403 modifyRegister( buffer_sidh_addr-1 , MCP_TXB_TXREQ_M, 00404 MCP_TXB_TXREQ_M ); 00405 } 00406 00407 uint8_t mcp2515::getNextFreeTXBuf(uint8_t *txbuf_n) { 00408 uint8_t res, i, ctrlval; 00409 uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL }; 00410 00411 res = MCP_ALLTXBUSY; 00412 *txbuf_n = 0x00; 00413 00414 // check all 3 TX-Buffers 00415 for (i=0; i<MCP_N_TXBUFFERS; i++) { 00416 ctrlval = readRegister( ctrlregs[i] ); 00417 if ( (ctrlval & MCP_TXB_TXREQ_M) == 0 ) { 00418 00419 *txbuf_n = ctrlregs[i]+1; // return SIDH-address of Buffer 00420 res = MCP2515_OK; 00421 return res; /* ! function exit */ 00422 } 00423 } 00424 00425 return res; 00426 } 00427 00428 void mcp2515::initCANBuffers(void) { 00429 // uint8_t i, a1, a2, a3; 00430 00431 // TODO: check why this is needed to receive extended 00432 // and standard frames 00433 // Mark all filter bits as don't care: 00434 write_can_id(MCP_RXM0SIDH, 0, 0); 00435 write_can_id(MCP_RXM1SIDH, 0, 0); 00436 // Anyway, set all filters to 0: 00437 write_can_id(MCP_RXF0SIDH, 1, 0); // RXB0: extended 00438 write_can_id(MCP_RXF1SIDH, 0, 0); // AND standard 00439 write_can_id(MCP_RXF2SIDH, 1, 0); // RXB1: extended 00440 write_can_id(MCP_RXF3SIDH, 0, 0); // AND standard 00441 write_can_id(MCP_RXF4SIDH, 0, 0); 00442 write_can_id(MCP_RXF5SIDH, 0, 0); 00443 /* 00444 // Clear, deactivate the three transmit buffers 00445 // TXBnCTRL -> TXBnD7 00446 a1 = MCP_TXB0CTRL; 00447 a2 = MCP_TXB1CTRL; 00448 a3 = MCP_TXB2CTRL; 00449 for (i = 0; i < 14; i++) { // in-buffer loop 00450 setRegister(a1, 0); 00451 setRegister(a2, 0); 00452 setRegister(a3, 0); 00453 a1++; 00454 a2++; 00455 a3++; 00456 } 00457 */ 00458 // and clear, deactivate the two receive buffers. 00459 // setRegister(MCP_RXB0CTRL, 0); 00460 //setRegister(MCP_RXB1CTRL, 0); 00461 } 00462 00463 uint8_t mcp2515::init(int canSpeed) { 00464 uint8_t res; 00465 00466 _deselect(); 00467 //MCP_CS_DDR |= ( 1 << MCP_CS_BIT ); 00468 00469 _reset(); 00470 00471 00472 res = setCANCTRL_Mode(MODE_CONFIG); 00473 00474 if ( res == MCP2515_FAIL ) { 00475 printf("\r\nCAN init failed %d\n\r",&_ncs); 00476 return res; /* function exit on error */ 00477 } 00478 res = configRate2(canSpeed); 00479 //res = configRate(CAN_500KBPS_10MHz); 00480 00481 if ( res == MCP2515_OK ) { 00482 initCANBuffers(); 00483 00484 // enable both receive-buffers to receive messages 00485 // with std. and ext. identifiers 00486 // and enable rollover 00487 modifyRegister(MCP_RXB0CTRL, 00488 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, 00489 MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK ); 00490 modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK, 00491 MCP_RXB_RX_STDEXT); 00492 00493 // Prescaler setting of the CLKOUT pin to zero 00494 // => Spending clock frequency of the CLKOUT pin MCP2515 00495 modifyRegister (MCP_CANCTRL, 0x07, CLKOUT_ENABLE); 00496 } 00497 00498 return res; 00499 } 00500 00501 /* 00502 * Select function 00503 */ 00504 00505 void mcp2515::_select() { 00506 //printf("{"); 00507 _ncs = 0; 00508 } 00509 00510 00511 /* 00512 * Deselect function 00513 */ 00514 00515 void mcp2515::_deselect() { 00516 _ncs = 1; 00517 //printf("}"); 00518 } 00519 00520 int mcp2515::status() { 00521 int status = 0; 00522 _select(); 00523 spi.write(0xd7); 00524 status = (spi.write(0x00) << 8 ); 00525 status |= spi.write(0x00); 00526 _deselect(); 00527 return status; 00528 } 00529 00530 void mcp2515::_pollbusy() { 00531 volatile int busy = 1; 00532 while (busy) { 00533 // if bit 7 is set, we can proceed 00534 if ( status() & 0x80 ) { 00535 busy = 0; 00536 } 00537 } 00538 } 00539 00540 00541 uint8_t mcp2515::_spi_readwrite(uint8_t data) { 00542 //printf("W0x%x ", data); 00543 uint8_t ret = spi.write(data); 00544 // printf("R0x%x,", ret); 00545 return ret; 00546 } 00547 00548 uint8_t mcp2515::_spi_read(void) { 00549 return _spi_readwrite(SPI_NULL); 00550 } 00551 00552 void mcp2515::dumpExtendedStatus(void) { 00553 uint8_t tec, rec, eflg; 00554 00555 tec = readRegister(MCP_TEC); 00556 rec = readRegister(MCP_REC); 00557 eflg = readRegister(MCP_EFLG); 00558 00559 printf("MCP2515 Extended Status:\n\r"); 00560 printf("MCP Transmit Error Count %d \r\n", tec); 00561 printf("MCP Receiver Error Count %d \n\r", rec); 00562 printf("MCP Error Flag %d\n\r", eflg); 00563 00564 if ( (rec>127) || (tec>127) ) { 00565 printf("Error-Passive or Bus-Off\n\r"); 00566 } 00567 00568 if (eflg & MCP_EFLG_RX1OVR) 00569 printf("Receive Buffer 1 Overflow\r\n"); 00570 if (eflg & MCP_EFLG_RX0OVR) 00571 printf("Receive Buffer 0 Overflow\n\r"); 00572 if (eflg & MCP_EFLG_TXBO) 00573 printf("Bus-Off\n\r"); 00574 if (eflg & MCP_EFLG_TXEP) 00575 printf("Receive Error Passive\n\r"); 00576 if (eflg & MCP_EFLG_TXWAR) 00577 printf("Transmit Error Warning\n\r"); 00578 if (eflg & MCP_EFLG_RXWAR) 00579 printf("Receive Error Warning\r\n"); 00580 if (eflg & MCP_EFLG_EWARN ) 00581 printf("Receive Error Warning\n\r"); 00582 }
Generated on Tue Jul 12 2022 22:54:58 by 1.7.2