Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mcp2515 by
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
