| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308 |
- /*
- mcp_can.cpp
- 2012 Copyright (c) Seeed Technology Inc. All right reserved.
- 2017 Copyright (c) Cory J. Fowler All Rights Reserved.
- Author: Loovee
- Contributor: Cory J. Fowler
- 2017-09-25
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-
- 1301 USA
- */
- #include "mcp_can.h"
- #define spi_readwrite SPI.transfer
- #define spi_read() spi_readwrite(0x00)
- /*********************************************************************************************************
- ** Function name: mcp2515_reset
- ** Descriptions: Performs a software reset
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_reset(void)
- {
- SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
- MCP2515_SELECT();
- spi_readwrite(MCP_RESET);
- MCP2515_UNSELECT();
- SPI.endTransaction();
- delayMicroseconds(10);
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_readRegister
- ** Descriptions: Read data register
- *********************************************************************************************************/
- INT8U MCP_CAN::mcp2515_readRegister(const INT8U address)
- {
- INT8U ret;
- SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
- MCP2515_SELECT();
- spi_readwrite(MCP_READ);
- spi_readwrite(address);
- ret = spi_read();
- MCP2515_UNSELECT();
- SPI.endTransaction();
- return ret;
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_readRegisterS
- ** Descriptions: Reads sucessive data registers
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_readRegisterS(const INT8U address, INT8U values[], const INT8U n)
- {
- INT8U i;
- SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
- MCP2515_SELECT();
- spi_readwrite(MCP_READ);
- spi_readwrite(address);
- // mcp2515 has auto-increment of address-pointer
- for (i=0; i<n; i++)
- values[i] = spi_read();
- MCP2515_UNSELECT();
- SPI.endTransaction();
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_setRegister
- ** Descriptions: Sets data register
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_setRegister(const INT8U address, const INT8U value)
- {
- SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
- MCP2515_SELECT();
- spi_readwrite(MCP_WRITE);
- spi_readwrite(address);
- spi_readwrite(value);
- MCP2515_UNSELECT();
- SPI.endTransaction();
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_setRegisterS
- ** Descriptions: Sets sucessive data registers
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_setRegisterS(const INT8U address, const INT8U values[], const INT8U n)
- {
- INT8U i;
- SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
- MCP2515_SELECT();
- spi_readwrite(MCP_WRITE);
- spi_readwrite(address);
-
- for (i=0; i<n; i++)
- spi_readwrite(values[i]);
-
- MCP2515_UNSELECT();
- SPI.endTransaction();
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_modifyRegister
- ** Descriptions: Sets specific bits of a register
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_modifyRegister(const INT8U address, const INT8U mask, const INT8U data)
- {
- SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
- MCP2515_SELECT();
- spi_readwrite(MCP_BITMOD);
- spi_readwrite(address);
- spi_readwrite(mask);
- spi_readwrite(data);
- MCP2515_UNSELECT();
- SPI.endTransaction();
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_readStatus
- ** Descriptions: Reads status register
- *********************************************************************************************************/
- INT8U MCP_CAN::mcp2515_readStatus(void)
- {
- INT8U i;
- SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
- MCP2515_SELECT();
- spi_readwrite(MCP_READ_STATUS);
- i = spi_read();
- MCP2515_UNSELECT();
- SPI.endTransaction();
- return i;
- }
- /*********************************************************************************************************
- ** Function name: setMode
- ** Descriptions: Sets control mode
- *********************************************************************************************************/
- INT8U MCP_CAN::setMode(const INT8U opMode)
- {
- mcpMode = opMode;
- return mcp2515_setCANCTRL_Mode(mcpMode);
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_setCANCTRL_Mode
- ** Descriptions: Set control mode
- *********************************************************************************************************/
- INT8U MCP_CAN::mcp2515_setCANCTRL_Mode(const INT8U newmode)
- {
- INT8U i;
- mcp2515_modifyRegister(MCP_CANCTRL, MODE_MASK, newmode);
- i = mcp2515_readRegister(MCP_CANCTRL);
- i &= MODE_MASK;
- if ( i == newmode )
- return MCP2515_OK;
- return MCP2515_FAIL;
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_configRate
- ** Descriptions: Set baudrate
- *********************************************************************************************************/
- INT8U MCP_CAN::mcp2515_configRate(const INT8U canSpeed, const INT8U canClock)
- {
- INT8U set, cfg1, cfg2, cfg3;
- set = 1;
- switch (canClock)
- {
- case (MCP_8MHZ):
- switch (canSpeed)
- {
- case (CAN_5KBPS): // 5KBPS
- cfg1 = MCP_8MHz_5kBPS_CFG1;
- cfg2 = MCP_8MHz_5kBPS_CFG2;
- cfg3 = MCP_8MHz_5kBPS_CFG3;
- break;
- case (CAN_10KBPS): // 10KBPS
- cfg1 = MCP_8MHz_10kBPS_CFG1;
- cfg2 = MCP_8MHz_10kBPS_CFG2;
- cfg3 = MCP_8MHz_10kBPS_CFG3;
- break;
- case (CAN_20KBPS): // 20KBPS
- cfg1 = MCP_8MHz_20kBPS_CFG1;
- cfg2 = MCP_8MHz_20kBPS_CFG2;
- cfg3 = MCP_8MHz_20kBPS_CFG3;
- break;
- case (CAN_31K25BPS): // 31.25KBPS
- cfg1 = MCP_8MHz_31k25BPS_CFG1;
- cfg2 = MCP_8MHz_31k25BPS_CFG2;
- cfg3 = MCP_8MHz_31k25BPS_CFG3;
- break;
- case (CAN_33K3BPS): // 33.33KBPS
- cfg1 = MCP_8MHz_33k3BPS_CFG1;
- cfg2 = MCP_8MHz_33k3BPS_CFG2;
- cfg3 = MCP_8MHz_33k3BPS_CFG3;
- break;
- case (CAN_40KBPS): // 40Kbps
- cfg1 = MCP_8MHz_40kBPS_CFG1;
- cfg2 = MCP_8MHz_40kBPS_CFG2;
- cfg3 = MCP_8MHz_40kBPS_CFG3;
- break;
- case (CAN_50KBPS): // 50Kbps
- cfg1 = MCP_8MHz_50kBPS_CFG1;
- cfg2 = MCP_8MHz_50kBPS_CFG2;
- cfg3 = MCP_8MHz_50kBPS_CFG3;
- break;
- case (CAN_80KBPS): // 80Kbps
- cfg1 = MCP_8MHz_80kBPS_CFG1;
- cfg2 = MCP_8MHz_80kBPS_CFG2;
- cfg3 = MCP_8MHz_80kBPS_CFG3;
- break;
- case (CAN_100KBPS): // 100Kbps
- cfg1 = MCP_8MHz_100kBPS_CFG1;
- cfg2 = MCP_8MHz_100kBPS_CFG2;
- cfg3 = MCP_8MHz_100kBPS_CFG3;
- break;
- case (CAN_125KBPS): // 125Kbps
- cfg1 = MCP_8MHz_125kBPS_CFG1;
- cfg2 = MCP_8MHz_125kBPS_CFG2;
- cfg3 = MCP_8MHz_125kBPS_CFG3;
- break;
- case (CAN_200KBPS): // 200Kbps
- cfg1 = MCP_8MHz_200kBPS_CFG1;
- cfg2 = MCP_8MHz_200kBPS_CFG2;
- cfg3 = MCP_8MHz_200kBPS_CFG3;
- break;
- case (CAN_250KBPS): // 250Kbps
- cfg1 = MCP_8MHz_250kBPS_CFG1;
- cfg2 = MCP_8MHz_250kBPS_CFG2;
- cfg3 = MCP_8MHz_250kBPS_CFG3;
- break;
- case (CAN_500KBPS): // 500Kbps
- cfg1 = MCP_8MHz_500kBPS_CFG1;
- cfg2 = MCP_8MHz_500kBPS_CFG2;
- cfg3 = MCP_8MHz_500kBPS_CFG3;
- break;
-
- case (CAN_1000KBPS): // 1Mbps
- cfg1 = MCP_8MHz_1000kBPS_CFG1;
- cfg2 = MCP_8MHz_1000kBPS_CFG2;
- cfg3 = MCP_8MHz_1000kBPS_CFG3;
- break;
- default:
- set = 0;
- return MCP2515_FAIL;
- break;
- }
- break;
- case (MCP_16MHZ):
- switch (canSpeed)
- {
- case (CAN_5KBPS): // 5Kbps
- cfg1 = MCP_16MHz_5kBPS_CFG1;
- cfg2 = MCP_16MHz_5kBPS_CFG2;
- cfg3 = MCP_16MHz_5kBPS_CFG3;
- break;
- case (CAN_10KBPS): // 10Kbps
- cfg1 = MCP_16MHz_10kBPS_CFG1;
- cfg2 = MCP_16MHz_10kBPS_CFG2;
- cfg3 = MCP_16MHz_10kBPS_CFG3;
- break;
- case (CAN_20KBPS): // 20Kbps
- cfg1 = MCP_16MHz_20kBPS_CFG1;
- cfg2 = MCP_16MHz_20kBPS_CFG2;
- cfg3 = MCP_16MHz_20kBPS_CFG3;
- break;
- case (CAN_33K3BPS): // 20Kbps
- cfg1 = MCP_16MHz_33k3BPS_CFG1;
- cfg2 = MCP_16MHz_33k3BPS_CFG2;
- cfg3 = MCP_16MHz_33k3BPS_CFG3;
- break;
- case (CAN_40KBPS): // 40Kbps
- cfg1 = MCP_16MHz_40kBPS_CFG1;
- cfg2 = MCP_16MHz_40kBPS_CFG2;
- cfg3 = MCP_16MHz_40kBPS_CFG3;
- break;
- case (CAN_50KBPS): // 50Kbps
- cfg2 = MCP_16MHz_50kBPS_CFG2;
- cfg3 = MCP_16MHz_50kBPS_CFG3;
- break;
- case (CAN_80KBPS): // 80Kbps
- cfg1 = MCP_16MHz_80kBPS_CFG1;
- cfg2 = MCP_16MHz_80kBPS_CFG2;
- cfg3 = MCP_16MHz_80kBPS_CFG3;
- break;
- case (CAN_100KBPS): // 100Kbps
- cfg1 = MCP_16MHz_100kBPS_CFG1;
- cfg2 = MCP_16MHz_100kBPS_CFG2;
- cfg3 = MCP_16MHz_100kBPS_CFG3;
- break;
- case (CAN_125KBPS): // 125Kbps
- cfg1 = MCP_16MHz_125kBPS_CFG1;
- cfg2 = MCP_16MHz_125kBPS_CFG2;
- cfg3 = MCP_16MHz_125kBPS_CFG3;
- break;
- case (CAN_200KBPS): // 200Kbps
- cfg1 = MCP_16MHz_200kBPS_CFG1;
- cfg2 = MCP_16MHz_200kBPS_CFG2;
- cfg3 = MCP_16MHz_200kBPS_CFG3;
- break;
- case (CAN_250KBPS): // 250Kbps
- cfg1 = MCP_16MHz_250kBPS_CFG1;
- cfg2 = MCP_16MHz_250kBPS_CFG2;
- cfg3 = MCP_16MHz_250kBPS_CFG3;
- break;
- case (CAN_500KBPS): // 500Kbps
- cfg1 = MCP_16MHz_500kBPS_CFG1;
- cfg2 = MCP_16MHz_500kBPS_CFG2;
- cfg3 = MCP_16MHz_500kBPS_CFG3;
- break;
-
- case (CAN_1000KBPS): // 1Mbps
- cfg1 = MCP_16MHz_1000kBPS_CFG1;
- cfg2 = MCP_16MHz_1000kBPS_CFG2;
- cfg3 = MCP_16MHz_1000kBPS_CFG3;
- break;
- default:
- set = 0;
- return MCP2515_FAIL;
- break;
- }
- break;
-
- case (MCP_20MHZ):
- switch (canSpeed)
- {
- case (CAN_40KBPS): // 40Kbps
- cfg1 = MCP_20MHz_40kBPS_CFG1;
- cfg2 = MCP_20MHz_40kBPS_CFG2;
- cfg3 = MCP_20MHz_40kBPS_CFG3;
- break;
- case (CAN_50KBPS): // 50Kbps
- cfg1 = MCP_20MHz_50kBPS_CFG1;
- cfg2 = MCP_20MHz_50kBPS_CFG2;
- cfg3 = MCP_20MHz_50kBPS_CFG3;
- break;
- case (CAN_80KBPS): // 80Kbps
- cfg1 = MCP_20MHz_80kBPS_CFG1;
- cfg2 = MCP_20MHz_80kBPS_CFG2;
- cfg3 = MCP_20MHz_80kBPS_CFG3;
- break;
- case (CAN_100KBPS): // 100Kbps
- cfg1 = MCP_20MHz_100kBPS_CFG1;
- cfg2 = MCP_20MHz_100kBPS_CFG2;
- cfg3 = MCP_20MHz_100kBPS_CFG3;
- break;
- case (CAN_125KBPS): // 125Kbps
- cfg1 = MCP_20MHz_125kBPS_CFG1;
- cfg2 = MCP_20MHz_125kBPS_CFG2;
- cfg3 = MCP_20MHz_125kBPS_CFG3;
- break;
- case (CAN_200KBPS): // 200Kbps
- cfg1 = MCP_20MHz_200kBPS_CFG1;
- cfg2 = MCP_20MHz_200kBPS_CFG2;
- cfg3 = MCP_20MHz_200kBPS_CFG3;
- break;
- case (CAN_250KBPS): // 250Kbps
- cfg1 = MCP_20MHz_250kBPS_CFG1;
- cfg2 = MCP_20MHz_250kBPS_CFG2;
- cfg3 = MCP_20MHz_250kBPS_CFG3;
- break;
- case (CAN_500KBPS): // 500Kbps
- cfg1 = MCP_20MHz_500kBPS_CFG1;
- cfg2 = MCP_20MHz_500kBPS_CFG2;
- cfg3 = MCP_20MHz_500kBPS_CFG3;
- break;
-
- case (CAN_1000KBPS): // 1Mbps
- cfg1 = MCP_20MHz_1000kBPS_CFG1;
- cfg2 = MCP_20MHz_1000kBPS_CFG2;
- cfg3 = MCP_20MHz_1000kBPS_CFG3;
- break;
- default:
- set = 0;
- return MCP2515_FAIL;
- break;
- }
- break;
-
- default:
- set = 0;
- return MCP2515_FAIL;
- break;
- }
- if (set) {
- mcp2515_setRegister(MCP_CNF1, cfg1);
- mcp2515_setRegister(MCP_CNF2, cfg2);
- mcp2515_setRegister(MCP_CNF3, cfg3);
- return MCP2515_OK;
- }
-
- return MCP2515_FAIL;
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_initCANBuffers
- ** Descriptions: Initialize Buffers, Masks, and Filters
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_initCANBuffers(void)
- {
- INT8U i, a1, a2, a3;
-
- INT8U std = 0;
- INT8U ext = 1;
- INT32U ulMask = 0x00, ulFilt = 0x00;
- mcp2515_write_mf(MCP_RXM0SIDH, ext, ulMask); /*Set both masks to 0 */
- mcp2515_write_mf(MCP_RXM1SIDH, ext, ulMask); /*Mask register ignores ext bit */
-
- /* Set all filters to 0 */
- mcp2515_write_mf(MCP_RXF0SIDH, ext, ulFilt); /* RXB0: extended */
- mcp2515_write_mf(MCP_RXF1SIDH, std, ulFilt); /* RXB1: standard */
- mcp2515_write_mf(MCP_RXF2SIDH, ext, ulFilt); /* RXB2: extended */
- mcp2515_write_mf(MCP_RXF3SIDH, std, ulFilt); /* RXB3: standard */
- mcp2515_write_mf(MCP_RXF4SIDH, ext, ulFilt);
- mcp2515_write_mf(MCP_RXF5SIDH, std, ulFilt);
- /* Clear, deactivate the three */
- /* transmit buffers */
- /* TXBnCTRL -> TXBnD7 */
- a1 = MCP_TXB0CTRL;
- a2 = MCP_TXB1CTRL;
- a3 = MCP_TXB2CTRL;
- for (i = 0; i < 14; i++) { /* in-buffer loop */
- mcp2515_setRegister(a1, 0);
- mcp2515_setRegister(a2, 0);
- mcp2515_setRegister(a3, 0);
- a1++;
- a2++;
- a3++;
- }
- mcp2515_setRegister(MCP_RXB0CTRL, 0);
- mcp2515_setRegister(MCP_RXB1CTRL, 0);
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_init
- ** Descriptions: Initialize the controller
- *********************************************************************************************************/
- INT8U MCP_CAN::mcp2515_init(const INT8U canIDMode, const INT8U canSpeed, const INT8U canClock)
- {
- INT8U res;
- mcp2515_reset();
-
- mcpMode = MCP_LOOPBACK;
- res = mcp2515_setCANCTRL_Mode(MODE_CONFIG);
- if(res > 0)
- {
- #if DEBUG_MODE
- Serial.print("Entering Configuration Mode Failure...\r\n");
- #endif
- return res;
- }
- #if DEBUG_MODE
- Serial.print("Entering Configuration Mode Successful!\r\n");
- #endif
- // Set Baudrate
- if(mcp2515_configRate(canSpeed, canClock))
- {
- #if DEBUG_MODE
- Serial.print("Setting Baudrate Failure...\r\n");
- #endif
- return res;
- }
- #if DEBUG_MODE
- Serial.print("Setting Baudrate Successful!\r\n");
- #endif
- if ( res == MCP2515_OK ) {
- /* init canbuffers */
- mcp2515_initCANBuffers();
- /* interrupt mode */
- mcp2515_setRegister(MCP_CANINTE, MCP_RX0IF | MCP_RX1IF);
- //Sets BF pins as GPO
- mcp2515_setRegister(MCP_BFPCTRL,MCP_BxBFS_MASK | MCP_BxBFE_MASK);
- //Sets RTS pins as GPI
- mcp2515_setRegister(MCP_TXRTSCTRL,0x00);
- switch(canIDMode)
- {
- case (MCP_ANY):
- mcp2515_modifyRegister(MCP_RXB0CTRL,
- MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
- MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
- mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK,
- MCP_RXB_RX_ANY);
- break;
- /* The followingn two functions of the MCP2515 do not work, there is a bug in the silicon.
- case (MCP_STD):
- mcp2515_modifyRegister(MCP_RXB0CTRL,
- MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
- MCP_RXB_RX_STD | MCP_RXB_BUKT_MASK );
- mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK,
- MCP_RXB_RX_STD);
- break;
- case (MCP_EXT):
- mcp2515_modifyRegister(MCP_RXB0CTRL,
- MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
- MCP_RXB_RX_EXT | MCP_RXB_BUKT_MASK );
- mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK,
- MCP_RXB_RX_EXT);
- break;
- */
- case (MCP_STDEXT):
- mcp2515_modifyRegister(MCP_RXB0CTRL,
- MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
- MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
- mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK,
- MCP_RXB_RX_STDEXT);
- break;
-
- default:
- #if DEBUG_MODE
- Serial.print("`Setting ID Mode Failure...\r\n");
- #endif
- return MCP2515_FAIL;
- break;
- }
- res = mcp2515_setCANCTRL_Mode(mcpMode);
- if(res)
- {
- #if DEBUG_MODE
- Serial.print("Returning to Previous Mode Failure...\r\n");
- #endif
- return res;
- }
- }
- return res;
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_write_id
- ** Descriptions: Write CAN ID
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_write_id( const INT8U mcp_addr, const INT8U ext, const INT32U id )
- {
- uint16_t canid;
- INT8U tbufdata[4];
- canid = (uint16_t)(id & 0x0FFFF);
- if ( ext == 1)
- {
- tbufdata[MCP_EID0] = (INT8U) (canid & 0xFF);
- tbufdata[MCP_EID8] = (INT8U) (canid >> 8);
- canid = (uint16_t)(id >> 16);
- tbufdata[MCP_SIDL] = (INT8U) (canid & 0x03);
- tbufdata[MCP_SIDL] += (INT8U) ((canid & 0x1C) << 3);
- tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M;
- tbufdata[MCP_SIDH] = (INT8U) (canid >> 5 );
- }
- else
- {
- tbufdata[MCP_SIDH] = (INT8U) (canid >> 3 );
- tbufdata[MCP_SIDL] = (INT8U) ((canid & 0x07 ) << 5);
- tbufdata[MCP_EID0] = 0;
- tbufdata[MCP_EID8] = 0;
- }
-
- mcp2515_setRegisterS( mcp_addr, tbufdata, 4 );
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_write_mf
- ** Descriptions: Write Masks and Filters
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_write_mf( const INT8U mcp_addr, const INT8U ext, const INT32U id )
- {
- uint16_t canid;
- INT8U tbufdata[4];
- canid = (uint16_t)(id & 0x0FFFF);
- if ( ext == 1)
- {
- tbufdata[MCP_EID0] = (INT8U) (canid & 0xFF);
- tbufdata[MCP_EID8] = (INT8U) (canid >> 8);
- canid = (uint16_t)(id >> 16);
- tbufdata[MCP_SIDL] = (INT8U) (canid & 0x03);
- tbufdata[MCP_SIDL] += (INT8U) ((canid & 0x1C) << 3);
- tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M;
- tbufdata[MCP_SIDH] = (INT8U) (canid >> 5 );
- }
- else
- {
- tbufdata[MCP_EID0] = (INT8U) (canid & 0xFF);
- tbufdata[MCP_EID8] = (INT8U) (canid >> 8);
- canid = (uint16_t)(id >> 16);
- tbufdata[MCP_SIDL] = (INT8U) ((canid & 0x07) << 5);
- tbufdata[MCP_SIDH] = (INT8U) (canid >> 3 );
- }
-
- mcp2515_setRegisterS( mcp_addr, tbufdata, 4 );
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_read_id
- ** Descriptions: Read CAN ID
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_read_id( const INT8U mcp_addr, INT8U* ext, INT32U* id )
- {
- INT8U tbufdata[4];
- *ext = 0;
- *id = 0;
- mcp2515_readRegisterS( mcp_addr, tbufdata, 4 );
- *id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5);
- if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M )
- {
- /* extended id */
- *id = (*id<<2) + (tbufdata[MCP_SIDL] & 0x03);
- *id = (*id<<8) + tbufdata[MCP_EID8];
- *id = (*id<<8) + tbufdata[MCP_EID0];
- *ext = 1;
- }
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_write_canMsg
- ** Descriptions: Write message
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_write_canMsg( const INT8U buffer_sidh_addr)
- {
- INT8U mcp_addr;
- mcp_addr = buffer_sidh_addr;
- mcp2515_setRegisterS(mcp_addr+5, m_nDta, m_nDlc ); /* write data bytes */
-
- if ( m_nRtr == 1) /* if RTR set bit in byte */
- m_nDlc |= MCP_RTR_MASK;
- mcp2515_setRegister((mcp_addr+4), m_nDlc ); /* write the RTR and DLC */
- mcp2515_write_id(mcp_addr, m_nExtFlg, m_nID ); /* write CAN id */
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_read_canMsg
- ** Descriptions: Read message
- *********************************************************************************************************/
- void MCP_CAN::mcp2515_read_canMsg( const INT8U buffer_sidh_addr) /* read can msg */
- {
- INT8U mcp_addr, ctrl;
- mcp_addr = buffer_sidh_addr;
- mcp2515_read_id( mcp_addr, &m_nExtFlg,&m_nID );
- ctrl = mcp2515_readRegister( mcp_addr-1 );
- m_nDlc = mcp2515_readRegister( mcp_addr+4 );
- if (ctrl & 0x08)
- m_nRtr = 1;
- else
- m_nRtr = 0;
- m_nDlc &= MCP_DLC_MASK;
- mcp2515_readRegisterS( mcp_addr+5, &(m_nDta[0]), m_nDlc );
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_getNextFreeTXBuf
- ** Descriptions: Send message
- *********************************************************************************************************/
- INT8U MCP_CAN::mcp2515_getNextFreeTXBuf(INT8U *txbuf_n) /* get Next free txbuf */
- {
- INT8U res, i, ctrlval;
- INT8U ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL };
- res = MCP_ALLTXBUSY;
- *txbuf_n = 0x00;
- /* check all 3 TX-Buffers */
- for (i=0; i<MCP_N_TXBUFFERS; i++) {
- ctrlval = mcp2515_readRegister( ctrlregs[i] );
- if ( (ctrlval & MCP_TXB_TXREQ_M) == 0 ) {
- *txbuf_n = ctrlregs[i]+1; /* return SIDH-address of Buffer*/
-
- res = MCP2515_OK;
- return res; /* ! function exit */
- }
- }
- return res;
- }
- /*********************************************************************************************************
- ** Function name: MCP_CAN
- ** Descriptions: Public function to declare CAN class and the /CS pin.
- *********************************************************************************************************/
- MCP_CAN::MCP_CAN(INT8U _CS)
- {
- MCPCS = _CS;
- MCP2515_UNSELECT();
- pinMode(MCPCS, OUTPUT);
- }
- /*********************************************************************************************************
- ** Function name: begin
- ** Descriptions: Public function to declare controller initialization parameters.
- *********************************************************************************************************/
- //static inline void initSS() { pinMode(SPI_CS, OUTPUT); }
- //static inline void setSS() { digitalWrite(SPI_CS, LOW); }
- //static inline void resetSS() { digitalWrite(SPI_CS, HIGH); }
- /*void MCP_CAN::setSS() {
- Serial.print(" Set Low ");
- digitalWrite(8, LOW);
- }
- void MCP_CAN::resetSS() {
- digitalWrite(8, HIGH);
- }
- */
- INT8U MCP_CAN::begin(INT8U idmodeset, INT8U speedset, INT8U clockset)
- {
- INT8U res;
- SPI.begin();
- setSS();
- res = mcp2515_init(idmodeset, speedset, clockset);
- resetSS();
- if (res == MCP2515_OK)
- return CAN_OK;
-
- return CAN_FAILINIT;
- }
- /*********************************************************************************************************
- ** Function name: init_Mask
- ** Descriptions: Public function to set mask(s).
- *********************************************************************************************************/
- INT8U MCP_CAN::init_Mask(INT8U num, INT8U ext, INT32U ulData)
- {
- INT8U res = MCP2515_OK;
- #if DEBUG_MODE
- Serial.print("Starting to Set Mask!\r\n");
- #endif
- res = mcp2515_setCANCTRL_Mode(MODE_CONFIG);
- if(res > 0){
- #if DEBUG_MODE
- Serial.print("Entering Configuration Mode Failure...\r\n");
- #endif
- return res;
- }
-
- if (num == 0){
- mcp2515_write_mf(MCP_RXM0SIDH, ext, ulData);
- }
- else if(num == 1){
- mcp2515_write_mf(MCP_RXM1SIDH, ext, ulData);
- }
- else res = MCP2515_FAIL;
-
- res = mcp2515_setCANCTRL_Mode(mcpMode);
- if(res > 0){
- #if DEBUG_MODE
- Serial.print("Entering Previous Mode Failure...\r\nSetting Mask Failure...\r\n");
- #endif
- return res;
- }
- #if DEBUG_MODE
- Serial.print("Setting Mask Successful!\r\n");
- #endif
- return res;
- }
- /*********************************************************************************************************
- ** Function name: init_Mask
- ** Descriptions: Public function to set mask(s).
- *********************************************************************************************************/
- INT8U MCP_CAN::init_Mask(INT8U num, INT32U ulData)
- {
- INT8U res = MCP2515_OK;
- INT8U ext = 0;
- #if DEBUG_MODE
- Serial.print("Starting to Set Mask!\r\n");
- #endif
- res = mcp2515_setCANCTRL_Mode(MODE_CONFIG);
- if(res > 0){
- #if DEBUG_MODE
- Serial.print("Entering Configuration Mode Failure...\r\n");
- #endif
- return res;
- }
-
- if((ulData & 0x80000000) == 0x80000000)
- ext = 1;
-
- if (num == 0){
- mcp2515_write_mf(MCP_RXM0SIDH, ext, ulData);
- }
- else if(num == 1){
- mcp2515_write_mf(MCP_RXM1SIDH, ext, ulData);
- }
- else res = MCP2515_FAIL;
-
- res = mcp2515_setCANCTRL_Mode(mcpMode);
- if(res > 0){
- #if DEBUG_MODE
- Serial.print("Entering Previous Mode Failure...\r\nSetting Mask Failure...\r\n");
- #endif
- return res;
- }
- #if DEBUG_MODE
- Serial.print("Setting Mask Successful!\r\n");
- #endif
- return res;
- }
- /*********************************************************************************************************
- ** Function name: init_Filt
- ** Descriptions: Public function to set filter(s).
- *********************************************************************************************************/
- INT8U MCP_CAN::init_Filt(INT8U num, INT8U ext, INT32U ulData)
- {
- INT8U res = MCP2515_OK;
- #if DEBUG_MODE
- Serial.print("Starting to Set Filter!\r\n");
- #endif
- res = mcp2515_setCANCTRL_Mode(MODE_CONFIG);
- if(res > 0)
- {
- #if DEBUG_MODE
- Serial.print("Enter Configuration Mode Failure...\r\n");
- #endif
- return res;
- }
-
- switch( num )
- {
- case 0:
- mcp2515_write_mf(MCP_RXF0SIDH, ext, ulData);
- break;
- case 1:
- mcp2515_write_mf(MCP_RXF1SIDH, ext, ulData);
- break;
- case 2:
- mcp2515_write_mf(MCP_RXF2SIDH, ext, ulData);
- break;
- case 3:
- mcp2515_write_mf(MCP_RXF3SIDH, ext, ulData);
- break;
- case 4:
- mcp2515_write_mf(MCP_RXF4SIDH, ext, ulData);
- break;
- case 5:
- mcp2515_write_mf(MCP_RXF5SIDH, ext, ulData);
- break;
- default:
- res = MCP2515_FAIL;
- }
-
- res = mcp2515_setCANCTRL_Mode(mcpMode);
- if(res > 0)
- {
- #if DEBUG_MODE
- Serial.print("Entering Previous Mode Failure...\r\nSetting Filter Failure...\r\n");
- #endif
- return res;
- }
- #if DEBUG_MODE
- Serial.print("Setting Filter Successfull!\r\n");
- #endif
-
- return res;
- }
- /*********************************************************************************************************
- ** Function name: init_Filt
- ** Descriptions: Public function to set filter(s).
- *********************************************************************************************************/
- INT8U MCP_CAN::init_Filt(INT8U num, INT32U ulData)
- {
- INT8U res = MCP2515_OK;
- INT8U ext = 0;
-
- #if DEBUG_MODE
- Serial.print("Starting to Set Filter!\r\n");
- #endif
- res = mcp2515_setCANCTRL_Mode(MODE_CONFIG);
- if(res > 0)
- {
- #if DEBUG_MODE
- Serial.print("Enter Configuration Mode Failure...\r\n");
- #endif
- return res;
- }
-
- if((ulData & 0x80000000) == 0x80000000)
- ext = 1;
-
- switch( num )
- {
- case 0:
- mcp2515_write_mf(MCP_RXF0SIDH, ext, ulData);
- break;
- case 1:
- mcp2515_write_mf(MCP_RXF1SIDH, ext, ulData);
- break;
- case 2:
- mcp2515_write_mf(MCP_RXF2SIDH, ext, ulData);
- break;
- case 3:
- mcp2515_write_mf(MCP_RXF3SIDH, ext, ulData);
- break;
- case 4:
- mcp2515_write_mf(MCP_RXF4SIDH, ext, ulData);
- break;
- case 5:
- mcp2515_write_mf(MCP_RXF5SIDH, ext, ulData);
- break;
- default:
- res = MCP2515_FAIL;
- }
-
- res = mcp2515_setCANCTRL_Mode(mcpMode);
- if(res > 0)
- {
- #if DEBUG_MODE
- Serial.print("Entering Previous Mode Failure...\r\nSetting Filter Failure...\r\n");
- #endif
- return res;
- }
- #if DEBUG_MODE
- Serial.print("Setting Filter Successfull!\r\n");
- #endif
-
- return res;
- }
- /*********************************************************************************************************
- ** Function name: setMsg
- ** Descriptions: Set can message, such as dlc, id, dta[] and so on
- *********************************************************************************************************/
- INT8U MCP_CAN::setMsg(INT32U id, INT8U rtr, INT8U ext, INT8U len, INT8U *pData)
- {
- int i = 0;
- m_nID = id;
- m_nRtr = rtr;
- m_nExtFlg = ext;
- m_nDlc = len;
- for(i = 0; i<MAX_CHAR_IN_MESSAGE; i++)
- m_nDta[i] = *(pData+i);
-
- return MCP2515_OK;
- }
- /*********************************************************************************************************
- ** Function name: clearMsg
- ** Descriptions: Set all messages to zero
- *********************************************************************************************************/
- INT8U MCP_CAN::clearMsg()
- {
- m_nID = 0;
- m_nDlc = 0;
- m_nExtFlg = 0;
- m_nRtr = 0;
- m_nfilhit = 0;
- for(int i = 0; i<m_nDlc; i++ )
- m_nDta[i] = 0x00;
- return MCP2515_OK;
- }
- /*********************************************************************************************************
- ** Function name: sendMsg
- ** Descriptions: Send message
- *********************************************************************************************************/
- INT8U MCP_CAN::sendMsg()
- {
- INT8U res, res1, txbuf_n;
- uint16_t uiTimeOut = 0;
- do {
- res = mcp2515_getNextFreeTXBuf(&txbuf_n); /* info = addr. */
- uiTimeOut++;
- } while (res == MCP_ALLTXBUSY && (uiTimeOut < TIMEOUTVALUE));
- if(uiTimeOut == TIMEOUTVALUE)
- {
- return CAN_GETTXBFTIMEOUT; /* get tx buff time out */
- }
- uiTimeOut = 0;
- mcp2515_write_canMsg( txbuf_n);
- mcp2515_modifyRegister( txbuf_n-1 , MCP_TXB_TXREQ_M, MCP_TXB_TXREQ_M );
-
- do
- {
- uiTimeOut++;
- res1 = mcp2515_readRegister(txbuf_n-1); /* read send buff ctrl reg */
- res1 = res1 & 0x08;
- } while (res1 && (uiTimeOut < TIMEOUTVALUE));
-
- if(uiTimeOut == TIMEOUTVALUE) /* send msg timeout */
- return CAN_SENDMSGTIMEOUT;
-
- return CAN_OK;
- }
- /*********************************************************************************************************
- ** Function name: sendMsgBuf
- ** Descriptions: Send message to transmitt buffer
- *********************************************************************************************************/
- INT8U MCP_CAN::sendMsgBuf(INT32U id, INT8U ext, INT8U len, INT8U *buf)
- {
- INT8U res;
-
- setMsg(id, 0, ext, len, buf);
- res = sendMsg();
-
- return res;
- }
- /*********************************************************************************************************
- ** Function name: sendMsgBuf
- ** Descriptions: Send message to transmitt buffer
- *********************************************************************************************************/
- INT8U MCP_CAN::sendMsgBuf(INT32U id, INT8U len, INT8U *buf)
- {
- INT8U ext = 0, rtr = 0;
- INT8U res;
-
- if((id & 0x80000000) == 0x80000000)
- ext = 1;
-
- if((id & 0x40000000) == 0x40000000)
- rtr = 1;
-
- setMsg(id, rtr, ext, len, buf);
- res = sendMsg();
-
- return res;
- }
- /*********************************************************************************************************
- ** Function name: readMsg
- ** Descriptions: Read message
- *********************************************************************************************************/
- INT8U MCP_CAN::readMsg()
- {
- INT8U stat, res;
- stat = mcp2515_readStatus();
- if ( stat & MCP_STAT_RX0IF ) /* Msg in Buffer 0 */
- {
- mcp2515_read_canMsg( MCP_RXBUF_0);
- mcp2515_modifyRegister(MCP_CANINTF, MCP_RX0IF, 0);
- res = CAN_OK;
- }
- else if ( stat & MCP_STAT_RX1IF ) /* Msg in Buffer 1 */
- {
- mcp2515_read_canMsg( MCP_RXBUF_1);
- mcp2515_modifyRegister(MCP_CANINTF, MCP_RX1IF, 0);
- res = CAN_OK;
- }
- else
- res = CAN_NOMSG;
-
- return res;
- }
- /*********************************************************************************************************
- ** Function name: readMsgBuf
- ** Descriptions: Public function, Reads message from receive buffer.
- *********************************************************************************************************/
- INT8U MCP_CAN::readMsgBuf(INT32U *id, INT8U *ext, INT8U *len, INT8U buf[])
- {
- if(readMsg() == CAN_NOMSG)
- return CAN_NOMSG;
-
- *id = m_nID;
- *len = m_nDlc;
- *ext = m_nExtFlg;
- for(int i = 0; i<m_nDlc; i++)
- buf[i] = m_nDta[i];
- return CAN_OK;
- }
- /*********************************************************************************************************
- ** Function name: readMsgBuf
- ** Descriptions: Public function, Reads message from receive buffer.
- *********************************************************************************************************/
- INT8U MCP_CAN::readMsgBuf(INT32U *id, INT8U *len, INT8U buf[])
- {
- if(readMsg() == CAN_NOMSG)
- return CAN_NOMSG;
- if (m_nExtFlg)
- m_nID |= 0x80000000;
- if (m_nRtr)
- m_nID |= 0x40000000;
-
- *id = m_nID;
- *len = m_nDlc;
-
- for(int i = 0; i<m_nDlc; i++)
- buf[i] = m_nDta[i];
- return CAN_OK;
- }
- /*********************************************************************************************************
- ** Function name: checkReceive
- ** Descriptions: Public function, Checks for received data. (Used if not using the interrupt output)
- *********************************************************************************************************/
- INT8U MCP_CAN::checkReceive(void)
- {
- INT8U res;
- res = mcp2515_readStatus(); /* RXnIF in Bit 1 and 0 */
- if ( res & MCP_STAT_RXIF_MASK )
- return CAN_MSGAVAIL;
- else
- return CAN_NOMSG;
- }
- /*********************************************************************************************************
- ** Function name: checkError
- ** Descriptions: Public function, Returns error register data.
- *********************************************************************************************************/
- INT8U MCP_CAN::checkError(void)
- {
- INT8U eflg = mcp2515_readRegister(MCP_EFLG);
- if ( eflg & MCP_EFLG_ERRORMASK )
- return CAN_CTRLERROR;
- else
- return CAN_OK;
- }
- /*********************************************************************************************************
- ** Function name: getError
- ** Descriptions: Returns error register value.
- *********************************************************************************************************/
- INT8U MCP_CAN::getError(void)
- {
- return mcp2515_readRegister(MCP_EFLG);
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_errorCountRX
- ** Descriptions: Returns REC register value
- *********************************************************************************************************/
- INT8U MCP_CAN::errorCountRX(void)
- {
- return mcp2515_readRegister(MCP_REC);
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_errorCountTX
- ** Descriptions: Returns TEC register value
- *********************************************************************************************************/
- INT8U MCP_CAN::errorCountTX(void)
- {
- return mcp2515_readRegister(MCP_TEC);
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_enOneShotTX
- ** Descriptions: Enables one shot transmission mode
- *********************************************************************************************************/
- INT8U MCP_CAN::enOneShotTX(void)
- {
- mcp2515_modifyRegister(MCP_CANCTRL, MODE_ONESHOT, MODE_ONESHOT);
- if((mcp2515_readRegister(MCP_CANCTRL) & MODE_ONESHOT) != MODE_ONESHOT)
- return CAN_FAIL;
- else
- return CAN_OK;
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_disOneShotTX
- ** Descriptions: Disables one shot transmission mode
- *********************************************************************************************************/
- INT8U MCP_CAN::disOneShotTX(void)
- {
- mcp2515_modifyRegister(MCP_CANCTRL, MODE_ONESHOT, 0);
- if((mcp2515_readRegister(MCP_CANCTRL) & MODE_ONESHOT) != 0)
- return CAN_FAIL;
- else
- return CAN_OK;
- }
- /*********************************************************************************************************
- ** Function name: mcp2515_abortTX
- ** Descriptions: Aborts any queued transmissions
- *********************************************************************************************************/
- INT8U MCP_CAN::abortTX(void)
- {
- mcp2515_modifyRegister(MCP_CANCTRL, ABORT_TX, ABORT_TX);
-
- // Maybe check to see if the TX buffer transmission request bits are cleared instead?
- if((mcp2515_readRegister(MCP_CANCTRL) & ABORT_TX) != ABORT_TX)
- return CAN_FAIL;
- else
- return CAN_OK;
- }
- /*********************************************************************************************************
- ** Function name: setGPO
- ** Descriptions: Public function, Checks for r
- *********************************************************************************************************/
- INT8U MCP_CAN::setGPO(INT8U data)
- {
- mcp2515_modifyRegister(MCP_BFPCTRL, MCP_BxBFS_MASK, (data<<4));
-
- return 0;
- }
- /*********************************************************************************************************
- ** Function name: getGPI
- ** Descriptions: Public function, Checks for r
- *********************************************************************************************************/
- INT8U MCP_CAN::getGPI(void)
- {
- INT8U res;
- res = mcp2515_readRegister(MCP_TXRTSCTRL) & MCP_BxRTS_MASK;
- return (res >> 3);
- }
- /*********************************************************************************************************
- END FILE
- *********************************************************************************************************/
|