MCP2515 CAN library

Fork of mcp2515 by Jason Engelman

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mcp2515.cpp Source File

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 }