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.
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 does'nt 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 default: 00112 set = 0; 00113 break; 00114 } 00115 00116 if (set) { 00117 setRegister(MCP_CNF1, cfg1); 00118 setRegister(MCP_CNF2, cfg2); 00119 setRegister(MCP_CNF3, cfg3); 00120 return MCP2515_OK; 00121 } else { 00122 return MCP2515_FAIL; 00123 } 00124 } 00125 00126 int mcp2515::configRate2(int bit_rate) 00127 { 00128 //struct spi_device *spi = to_spi_device(can->cdev.dev); 00129 //struct mcp251x *chip = dev_get_drvdata(&spi->dev); 00130 //struct mcp251x_platform_data *pdata = spi->dev.platform_data; 00131 00132 printf("\n\rcanspeed=%d",bit_rate); 00133 int f_osc = 16000000; //4000000; //4Mhz 00134 int tqs; /* tbit/TQ */ 00135 int brp; 00136 int ps1, ps2, propseg, sjw; 00137 00138 /* Determine the BRP value that gives the requested bit rate. */ 00139 for(brp = 0; brp < 8; brp++) { 00140 tqs = f_osc / (2 * (brp + 1)) / bit_rate; 00141 if (tqs >= 5 && tqs <= 25 00142 && (f_osc / (2 * (brp + 1)) / tqs) == bit_rate) 00143 break; 00144 } 00145 if (brp >= 8) printf("Spaztic BRP"); 00146 // return -1; 00147 00148 /* The CAN bus bit time (tbit) is determined by: 00149 * tbit = (SyncSeg + PropSeg + PS1 + PS2) * TQ 00150 * with: 00151 * SyncSeg = 1 00152 * sample point (between PS1 and PS2) must be at 60%-70% of the bit time 00153 * PropSeg + PS1 >= PS2 00154 * PropSeg + PS1 >= Tdelay 00155 * PS2 > SJW 00156 * 1 <= PropSeg <= 8, 1 <= PS1 <=8, 2 <= PS2 <= 8 00157 * SJW = 1 is sufficient in most cases. 00158 * Tdelay is usually 1 or 2 TQ. 00159 */ 00160 00161 propseg = ps1 = ps2 = (tqs - 1) / 3; 00162 if (tqs - (1 + propseg + ps1 + ps2) == 2) 00163 ps1++; 00164 if (tqs - (1 + propseg + ps1 + ps2) == 1) 00165 ps2++; 00166 sjw = 1; 00167 00168 printf("\n\rbit rate: BRP = %d, Tbit = %d TQ, PropSeg = %d, PS1 = %d, PS2 = %d, SJW = %d\n", 00169 brp, tqs, propseg, ps1, ps2, sjw); 00170 00171 /* Since we can only change the bit rate when the network device is 00172 * down the chip must be in sleep mode. Wake it up and put it into 00173 * config mode. */ 00174 //mcp251x_hw_wakeup(spi); 00175 //mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, CANCTRL_REQOP_CONF); 00176 00177 //mcp251x_write_reg(spi, CNF1, ((sjw-1) << 6) | brp); 00178 //mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1)); 00179 //mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, (ps2-1)); 00180 setRegister(MCP_CNF1, ((sjw-1) << 6) | brp ); 00181 setRegister(MCP_CNF2, CNF2_BTLMODE | ((ps1-1) << 3) | (propseg-1) ); 00182 modifyRegister(MCP_CNF3, CNF3_PHSEG2_MASK, (ps2-1) ); 00183 //mcp251x_hw_sleep(spi); 00184 00185 /* Calculate actual bit rate. */ 00186 //chip->bit_rate = pdata->f_osc / (2 * (brp + 1)) / tqs; 00187 00188 return 0; 00189 } 00190 00191 uint8_t mcp2515::readRegister( uint8_t address) { 00192 uint8_t ret; 00193 00194 _select(); 00195 _spi_readwrite(MCP_READ); 00196 _spi_readwrite(address); 00197 ret = _spi_read(); 00198 _deselect(); 00199 00200 return ret; 00201 } 00202 00203 void mcp2515::readRegisterS( uint8_t address, 00204 uint8_t values[], uint8_t n) { 00205 uint8_t i; 00206 00207 _select(); 00208 _spi_readwrite(MCP_READ); 00209 _spi_readwrite(address); 00210 // mcp2515 has auto-increment of address-pointer 00211 for (i=0; i<n; i++) { 00212 values[i] = _spi_read(); 00213 } 00214 _deselect(); 00215 } 00216 00217 void mcp2515::modifyRegister( uint8_t address, 00218 uint8_t mask, uint8_t data) { 00219 _select(); 00220 _spi_readwrite(MCP_BITMOD); 00221 _spi_readwrite(address); 00222 _spi_readwrite(mask); 00223 _spi_readwrite(data); 00224 _deselect(); 00225 } 00226 00227 00228 uint8_t mcp2515::readXXStatus_helper( uint8_t cmd) { 00229 uint8_t i; 00230 00231 _select(); 00232 _spi_readwrite(cmd); 00233 i = _spi_read(); 00234 _deselect(); 00235 00236 return i; 00237 } 00238 00239 uint8_t mcp2515::readStatus(void) { 00240 return readXXStatus_helper(MCP_READ_STATUS); 00241 } 00242 00243 uint8_t mcp2515::RXStatus(void) { 00244 return readXXStatus_helper(MCP_RX_STATUS); 00245 } 00246 00247 // read-modify-write - better: Bit Modify Instruction 00248 uint8_t mcp2515::setCANCTRL_Mode(uint8_t newmode) { 00249 00250 uint8_t i; 00251 00252 i = readRegister(MCP_CANCTRL); 00253 i &= ~(MODE_MASK); 00254 i |= newmode; 00255 setRegister(MCP_CANCTRL, i); 00256 00257 // verify as advised in datasheet 00258 i = readRegister(MCP_CANCTRL); 00259 i &= MODE_MASK; 00260 if ( i == newmode ) { 00261 return MCP2515_OK; 00262 } else { 00263 return MCP2515_FAIL; 00264 } 00265 00266 } 00267 00268 00269 void mcp2515::setRegisterS( uint8_t address, 00270 uint8_t values[], uint8_t n) { 00271 uint8_t i; 00272 00273 _select(); 00274 _spi_readwrite(MCP_WRITE); 00275 _spi_readwrite(address); 00276 // mcp2515 has auto-increment of address-pointer 00277 for (i=0; i<n; i++) { 00278 _spi_readwrite(values[i]); 00279 } 00280 _deselect(); 00281 } 00282 00283 void mcp2515::read_can_id( uint8_t mcp_addr, 00284 uint8_t* ext, uint32_t* can_id ) { 00285 uint8_t tbufdata[4]; 00286 00287 *ext = 0; 00288 *can_id = 0; 00289 00290 readRegisterS( mcp_addr, tbufdata, 4 ); 00291 00292 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5); 00293 00294 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) { 00295 // extended id 00296 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03); 00297 *can_id <<= 16; 00298 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0]; 00299 *ext = 1; 00300 } 00301 } 00302 00303 00304 void mcp2515::read_can_idN( uint8_t mcp_addr, 00305 CANFormat* ext, unsigned int* can_id ) { 00306 uint8_t tbufdata[4]; 00307 00308 *ext = CANStandard; 00309 *can_id = 0; 00310 00311 readRegisterS( mcp_addr, tbufdata, 4 ); 00312 00313 *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5); 00314 00315 if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) { 00316 // extended id 00317 *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03); 00318 *can_id <<= 16; 00319 *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0]; 00320 *ext = CANExtended;//1; 00321 } 00322 } 00323 00324 // Buffer can be MCP_RXBUF_0 or MCP_RXBUF_1 00325 void mcp2515::read_canMsg( uint8_t buffer_sidh_addr, CANMessage* msg) 00326 //CANMessage mcp2515::read_canMsg( uint8_t buffer_sidh_addr) 00327 { 00328 uint8_t mcp_addr, ctrl,dlc; 00329 00330 00331 00332 mcp_addr = buffer_sidh_addr; 00333 00334 read_can_idN( mcp_addr, &msg->format, &msg->id ); 00335 00336 ctrl = readRegister( mcp_addr-1 ); 00337 dlc = readRegister( mcp_addr+4 ); 00338 00339 //if ((*dlc & RTR_MASK) || (ctrl & 0x08)) { 00340 if ((ctrl & 0x08)) { 00341 msg->type = CANRemote; //1 CANRemote 00342 } else { 00343 msg->type = CANData; //0 CANData 00344 } 00345 00346 dlc &= MCP_DLC_MASK; 00347 readRegisterS( mcp_addr+5, &(msg->data[0]), dlc ); 00348 msg->len =dlc; 00349 00350 } 00351 00352 void mcp2515::setDebugConsole(Serial c){ 00353 //console=c; 00354 debug=true; 00355 } 00356 00357 void mcp2515::write_can_id( uint8_t mcp_addr, 00358 uint8_t ext, uint32_t can_id ) { 00359 uint16_t canid; 00360 uint8_t tbufdata[4]; 00361 00362 canid = (uint16_t)(can_id & 0x0FFFF); 00363 00364 if ( ext == 1) { 00365 tbufdata[MCP_EID0] = (uint8_t) (canid & 0xFF); 00366 tbufdata[MCP_EID8] = (uint8_t) (canid / 256); 00367 canid = (uint16_t)( can_id / 0x10000L ); 00368 tbufdata[MCP_SIDL] = (uint8_t) (canid & 0x03); 00369 tbufdata[MCP_SIDL] += (uint8_t) ((canid & 0x1C )*8); 00370 tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M; 00371 tbufdata[MCP_SIDH] = (uint8_t) (canid / 32 ); 00372 } else { 00373 tbufdata[MCP_SIDH] = (uint8_t) (canid / 8 ); 00374 tbufdata[MCP_SIDL] = (uint8_t) ((canid & 0x07 )*32); 00375 tbufdata[MCP_EID0] = 0; 00376 tbufdata[MCP_EID8] = 0; 00377 } 00378 setRegisterS( mcp_addr, tbufdata, 4 ); 00379 } 00380 00381 // Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2 00382 void mcp2515::write_canMsg( uint8_t buffer_sidh_addr, 00383 CANMessage* msg) { 00384 uint8_t mcp_addr, dlc; 00385 00386 mcp_addr = buffer_sidh_addr; 00387 dlc = msg->len; 00388 00389 setRegisterS(mcp_addr+5, &(msg->data[0]), dlc ); // write data bytes 00390 write_can_id( mcp_addr, msg->format, 00391 msg->id ); // write CAN id 00392 if ( msg->type == 1) dlc |= MCP_RTR_MASK; // if RTR set bit in byte 00393 setRegister( (mcp_addr+4), dlc ); // write the RTR and DLC 00394 } 00395 00396 void mcp2515::start_transmit( uint8_t buffer_sidh_addr) { 00397 // TXBnCTRL_addr = TXBnSIDH_addr - 1 00398 modifyRegister( buffer_sidh_addr-1 , MCP_TXB_TXREQ_M, 00399 MCP_TXB_TXREQ_M ); 00400 } 00401 00402 uint8_t mcp2515::getNextFreeTXBuf(uint8_t *txbuf_n) { 00403 uint8_t res, i, ctrlval; 00404 uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL }; 00405 00406 res = MCP_ALLTXBUSY; 00407 *txbuf_n = 0x00; 00408 00409 // check all 3 TX-Buffers 00410 for (i=0; i<MCP_N_TXBUFFERS; i++) { 00411 ctrlval = readRegister( ctrlregs[i] ); 00412 if ( (ctrlval & MCP_TXB_TXREQ_M) == 0 ) { 00413 00414 *txbuf_n = ctrlregs[i]+1; // return SIDH-address of Buffer 00415 res = MCP2515_OK; 00416 return res; /* ! function exit */ 00417 } 00418 } 00419 00420 return res; 00421 } 00422 00423 void mcp2515::initCANBuffers(void) { 00424 // uint8_t i, a1, a2, a3; 00425 00426 // TODO: check why this is needed to receive extended 00427 // and standard frames 00428 // Mark all filter bits as don't care: 00429 write_can_id(MCP_RXM0SIDH, 0, 0); 00430 write_can_id(MCP_RXM1SIDH, 0, 0); 00431 // Anyway, set all filters to 0: 00432 write_can_id(MCP_RXF0SIDH, 1, 0); // RXB0: extended 00433 write_can_id(MCP_RXF1SIDH, 0, 0); // AND standard 00434 write_can_id(MCP_RXF2SIDH, 1, 0); // RXB1: extended 00435 write_can_id(MCP_RXF3SIDH, 0, 0); // AND standard 00436 write_can_id(MCP_RXF4SIDH, 0, 0); 00437 write_can_id(MCP_RXF5SIDH, 0, 0); 00438 /* 00439 // Clear, deactivate the three transmit buffers 00440 // TXBnCTRL -> TXBnD7 00441 a1 = MCP_TXB0CTRL; 00442 a2 = MCP_TXB1CTRL; 00443 a3 = MCP_TXB2CTRL; 00444 for (i = 0; i < 14; i++) { // in-buffer loop 00445 setRegister(a1, 0); 00446 setRegister(a2, 0); 00447 setRegister(a3, 0); 00448 a1++; 00449 a2++; 00450 a3++; 00451 } 00452 */ 00453 // and clear, deactivate the two receive buffers. 00454 // setRegister(MCP_RXB0CTRL, 0); 00455 //setRegister(MCP_RXB1CTRL, 0); 00456 } 00457 00458 uint8_t mcp2515::init( int canSpeed) { 00459 uint8_t res; 00460 00461 _deselect(); 00462 //MCP_CS_DDR |= ( 1 << MCP_CS_BIT ); 00463 00464 _reset(); 00465 00466 00467 res = setCANCTRL_Mode(MODE_CONFIG); 00468 00469 if ( res == MCP2515_FAIL ) { 00470 printf("\r\nCAN init failed %d\n\r",&_ncs); 00471 return res; /* function exit on error */ 00472 } 00473 res = configRate2(canSpeed); 00474 00475 if ( res == MCP2515_OK ) { 00476 initCANBuffers(); 00477 00478 00479 // enable both receive-buffers to receive messages 00480 // with std. and ext. identifiers 00481 // and enable rollover 00482 modifyRegister(MCP_RXB0CTRL, 00483 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, 00484 MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK ); 00485 modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK, 00486 MCP_RXB_RX_STDEXT); 00487 00488 // Prescaler setting of the CLKOUT pin to zero 00489 // => Spending clock frequency of the CLKOUT pin MCP2515 00490 modifyRegister (MCP_CANCTRL, 0x07, CLKOUT_ENABLE); 00491 } 00492 00493 return res; 00494 } 00495 00496 /* 00497 * Select function 00498 */ 00499 00500 void mcp2515::_select() { 00501 //printf("{"); 00502 _ncs = 0; 00503 } 00504 00505 00506 /* 00507 * Deselect function 00508 */ 00509 00510 void mcp2515::_deselect() { 00511 _ncs = 1; 00512 //printf("}"); 00513 } 00514 00515 int mcp2515::status() { 00516 int status = 0; 00517 _select(); 00518 spi.write(0xd7); 00519 status = (spi.write(0x00) << 8 ); 00520 status |= spi.write(0x00); 00521 _deselect(); 00522 return status; 00523 } 00524 00525 void mcp2515::_pollbusy() { 00526 volatile int busy = 1; 00527 while (busy) { 00528 // if bit 7 is set, we can proceed 00529 if ( status() & 0x80 ) { 00530 busy = 0; 00531 } 00532 } 00533 } 00534 00535 00536 uint8_t mcp2515::_spi_readwrite(uint8_t data) { 00537 //printf("W0x%x ", data); 00538 uint8_t ret = spi.write(data); 00539 // printf("R0x%x,", ret); 00540 return ret; 00541 } 00542 00543 uint8_t mcp2515::_spi_read(void) { 00544 return _spi_readwrite(SPI_NULL); 00545 } 00546 00547 void mcp2515::dumpExtendedStatus(void) { 00548 uint8_t tec, rec, eflg; 00549 00550 tec = readRegister(MCP_TEC); 00551 rec = readRegister(MCP_REC); 00552 eflg = readRegister(MCP_EFLG); 00553 00554 printf("MCP2515 Extended Status:\n\r"); 00555 printf("MCP Transmit Error Count %d \r\n", tec); 00556 printf("MCP Receiver Error Count %d \n\r", rec); 00557 printf("MCP Error Flag %d\n\r", eflg); 00558 00559 if ( (rec>127) || (tec>127) ) { 00560 printf("Error-Passive or Bus-Off\n\r"); 00561 } 00562 00563 if (eflg & MCP_EFLG_RX1OVR) 00564 printf("Receive Buffer 1 Overflow\r\n"); 00565 if (eflg & MCP_EFLG_RX0OVR) 00566 printf("Receive Buffer 0 Overflow\n\r"); 00567 if (eflg & MCP_EFLG_TXBO) 00568 printf("Bus-Off\n\r"); 00569 if (eflg & MCP_EFLG_TXEP) 00570 printf("Receive Error Passive\n\r"); 00571 if (eflg & MCP_EFLG_TXWAR) 00572 printf("Transmit Error Warning\n\r"); 00573 if (eflg & MCP_EFLG_RXWAR) 00574 printf("Receive Error Warning\r\n"); 00575 if (eflg & MCP_EFLG_EWARN ) 00576 printf("Receive Error Warning\n\r"); 00577 }
Generated on Mon Sep 26 2022 07:41:12 by
1.7.2