Transplantation from Arduino MCP2515 Library which is made by Kyle Crockett. http://code.google.com/p/canduino/source/browse/trunk/Library/CAN/CAN.h?r=24
Dependents: DISCO-F746NG_rtos_test
Revision 0:b65cb1bbf0ce, committed 2013-01-18
- Comitter:
- FalconOnishi
- Date:
- Fri Jan 18 17:00:28 2013 +0000
- Commit message:
- Add some utility methods
Changed in this revision
MCP2515.cpp | Show annotated file Show diff for this revision Revisions of this file |
MCP2515.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MCP2515.cpp Fri Jan 18 17:00:28 2013 +0000 @@ -0,0 +1,474 @@ + +#include "MCP2515.h" + +MCP2515::MCP2515(SPI& spi, PinName cs) : spi(spi), cs(cs) +{ + /* + reset = 0; // RESET MCP2515 CONTROLLER + wait_ms(10); + reset = 1; + wait_ms(100); + */ +} + +void MCP2515::baudConfig(int bitRate)//sets bitrate for MCP2515 node +{ + byte config0 = 0x00; + byte config1 = 0x00; + byte config2 = 0x00; + + switch (bitRate) + { +case 10: + config0 = 0x31; + config1 = 0xB8; + config2 = 0x05; + break; + +case 20: + config0 = 0x18; + config1 = 0xB8; + config2 = 0x05; + break; + +case 50: + config0 = 0x09; + config1 = 0xB8; + config2 = 0x05; + break; + +case 100: + config0 = 0x04; + config1 = 0xB8; + config2 = 0x05; + break; + +case 125: + config0 = 0x03; + config1 = 0xB8; + config2 = 0x05; + break; + +case 250: + config0 = 0x01; + config1 = 0xB8; + config2 = 0x05; + break; + +case 500: + config0 = 0x00; + config1 = 0xB8; + config2 = 0x05; + break; +case 1000: + //1 megabit mode added by Patrick Cruce(pcruce_at_igpp.ucla.edu) + //Faster communications enabled by shortening bit timing phases(3 Tq. PS1 & 3 Tq. PS2) Note that this may exacerbate errors due to synchronization or arbitration. + config0 = 0x80; + config1 = 0x90; + config2 = 0x02; + } + cs = 0; + wait_ms(10); + spi.write(WRITE); + spi.write(CNF0); + spi.write(config0); + wait_ms(10); + cs = 1; + wait_ms(10); + + cs = 0; + wait_ms(10); + spi.write(WRITE); + spi.write(CNF1); + spi.write(config1); + wait_ms(10); + cs = 1; + wait_ms(10); + + cs = 0; + wait_ms(10); + spi.write(WRITE); + spi.write(CNF2); + spi.write(config2); + wait_ms(10); + cs = 1; + wait_ms(10); +} + +//Method added to enable testing in loopback mode.(pcruce_at_igpp.ucla.edu) +void MCP2515::setMode(MCP2515Mode mode) { //put MCP2515 controller in one of five modes + + //byte writeVal,mask,readVal; + byte writeVal = 0x00; + byte mask = 0x00; + + switch(mode) { + case CONFIGURATION: + writeVal = 0x80; + break; + case NORMAL: + writeVal = 0x00; + break; + case SLEEP: + writeVal = 0x20; + break; + case LISTEN: + writeVal = 0x60; + break; + case LOOPBACK: + writeVal = 0x40; + break; + } + + mask = 0xE0; + + cs = 0; + spi.write(BIT_MODIFY); + spi.write(MCP2515CTRL); + spi.write(mask); + spi.write(writeVal); + cs = 1; + +} + + +void MCP2515::send_0()//transmits buffer 0 +{ + + //wait_mss removed from SEND command(pcruce_at_igpp.ucla.edu) + //In testing we found that any lost data was from PC<->Serial wait_mss, + //Not MCP2515 Controller/AVR wait_mss. Thus removing the wait_mss at this level + //allows maximum flexibility and performance. + cs = 0; + spi.write(SEND_TX_BUF_0); + cs = 1; +} + +void MCP2515::send_1()//transmits buffer 1 +{ + cs = 0; + spi.write(SEND_TX_BUF_1); + cs = 1; +} + +void MCP2515::send_2()//transmits buffer 2 +{ + cs = 0; + spi.write(SEND_TX_BUF_2); + cs = 1; +} + +char MCP2515::readID_0()//reads ID in recieve buffer 0 +{ + char retVal; + cs = 0; + wait_ms(10); + spi.write(READ_RX_BUF_0_ID); + retVal = spi.write(0xFF); + wait_ms(10); + cs = 1; + wait_ms(10); + return retVal; +} + +char MCP2515::readID_1()//reads ID in reciever buffer 1 +{ + char retVal; + cs = 0; + wait_ms(10); + spi.write(READ_RX_BUF_1_ID); + retVal = spi.write(0xFF); + wait_ms(10); + cs = 1; + wait_ms(10); + return retVal; +} + +char MCP2515::readDATA_0()//reads DATA in recieve buffer 0 +{ + char retVal; + cs = 0; + wait_ms(10); + spi.write( READ_RX_BUF_0_DATA); + retVal = spi.write(0xFF); + wait_ms(10); + cs = 1; + wait_ms(10); + return retVal; +} + +char MCP2515::readDATA_1()//reads data in recieve buffer 1 +{ + char retVal; + cs = 0; + wait_ms(10); + spi.write( READ_RX_BUF_1_DATA); + retVal = spi.write(0xFF); + wait_ms(10); + cs = 1; + wait_ms(10); + return retVal; +} + + //extending MCP2515 data read to full frames(pcruce_at_igpp.ucla.edu) + //It is the responsibility of the user to allocate memory for output. + //If you don't know what length the bus frames will be, data_out should be 8-bytes +void MCP2515::readDATA_ff_0(byte* length_out,byte *data_out,unsigned short *id_out){ + + byte len,i; + unsigned short id_h,id_l; + + cs = 0; + spi.write(READ_RX_BUF_0_ID); + id_h = (unsigned short) spi.write(0xFF); //id high + id_l = (unsigned short) spi.write(0xFF); //id low + spi.write(0xFF); //extended id high(unused) + spi.write(0xFF); //extended id low(unused) + len = (spi.write(0xFF) & 0x0F); //data length code + for (i = 0;i<len;i++) { + data_out[i] = spi.write(0xFF); + } + cs = 1; + (*length_out) = len; + (*id_out) = ((id_h << 3) + ((id_l & 0xE0) >> 5)); //repack identifier + +} + +void MCP2515::readDATA_ff_1(byte* length_out,byte *data_out,unsigned short *id_out){ + + byte id_h,id_l,len,i; + + cs = 0; + spi.write(READ_RX_BUF_1_ID); + id_h = spi.write(0xFF); //id high + id_l = spi.write(0xFF); //id low + spi.write(0xFF); //extended id high(unused) + spi.write(0xFF); //extended id low(unused) + len = (spi.write(0xFF) & 0x0F); //data length code + for (i = 0;i<len;i++) { + data_out[i] = spi.write(0xFF); + } + cs = 1; + + (*length_out) = len; + (*id_out) = ((((unsigned short) id_h) << 3) + ((id_l & 0xE0) >> 5)); //repack identifier +} + + //Adding method to read status register + //MCP2515 be used to determine whether a frame was received. + //(readStatus() & 0x80) == 0x80 means frame in buffer 0 + //(readStatus() & 0x40) == 0x40 means frame in buffer 1 +byte MCP2515::readStatus() +{ + byte retVal; + cs = 0; + spi.write(READ_STATUS); + retVal = spi.write(0xFF); + cs = 1; + return retVal; + +} + +void MCP2515::load_0(byte identifier, byte data)//loads ID and DATA into transmit buffer 0 +{ + cs = 0; + wait_ms(10); + spi.write(LOAD_TX_BUF_0_ID); + spi.write(identifier); + wait_ms(10); + cs = 1; + wait_ms(10); + + cs = 0; + wait_ms(10); + spi.write(LOAD_TX_BUF_0_DATA); + spi.write(data); + wait_ms(10); + cs = 1; + wait_ms(10); +} + +void MCP2515::load_1(byte identifier, byte data)//loads ID and DATA into transmit buffer 1 +{ + cs = 0; + wait_ms(10); + spi.write(LOAD_TX_BUF_1_ID); + spi.write(identifier); + wait_ms(10); + cs = 1; + wait_ms(10); + + cs = 0; + wait_ms(10); + spi.write(LOAD_TX_BUF_1_DATA); + spi.write(data); + wait_ms(10); + cs = 1; + wait_ms(10); +} + +void MCP2515::load_2(byte identifier, byte data)//loads ID and DATA into transmit buffer 2 +{ + cs = 0; + wait_ms(10); + spi.write(LOAD_TX_BUF_2_ID); + spi.write(identifier); + wait_ms(10); + cs = 1; + wait_ms(10); + + cs = 0; + wait_ms(10); + spi.write(LOAD_TX_BUF_2_DATA); + spi.write(data); + wait_ms(10); + cs = 1; + wait_ms(10); +} + +void MCP2515::load_ff_0(byte length,unsigned short identifier,byte *data) +{ + + byte i,id_high,id_low; + + //generate id bytes before spi write + id_high = (byte) (identifier >> 3); + id_low = (byte) ((identifier << 5) & 0x00E0); + + cs = 0; + spi.write(LOAD_TX_BUF_0_ID); + spi.write(id_high); //identifier high bits + spi.write(id_low); //identifier low bits + spi.write(0x00); //extended identifier registers(unused) + spi.write(0x00); + spi.write(length); + for (i=0;i<length;i++) { //load data buffer + spi.write(data[i]); + } + + cs = 1; + +} + +void MCP2515::load_ff_1(byte length,unsigned short identifier,byte *data) +{ + + byte i,id_high,id_low; + + //generate id bytes before spi write + id_high = (byte) (identifier >> 3); + id_low = (byte) ((identifier << 5) & 0x00E0); + + cs = 0; + spi.write(LOAD_TX_BUF_1_ID); + spi.write(id_high); //identifier high bits + spi.write(id_low); //identifier low bits + spi.write(0x00); //extended identifier registers(unused) + spi.write(0x00); + spi.write(length); + for (i=0;i<length;i++) { //load data buffer + spi.write(data[i]); + } + + cs = 1; + + +} + +void MCP2515::load_ff_2(byte length,unsigned short identifier,byte *data) +{ + + byte i,id_high,id_low; + + //generate id bytes before spi write + id_high = (byte) (identifier >> 3); + id_low = (byte) ((identifier << 5) & 0x00E0); + + cs = 0; + + spi.write(LOAD_TX_BUF_2_ID); + spi.write(id_high); //identifier high bits + spi.write(id_low); //identifier low bits + spi.write(0x00); //extended identifier registers(unused) + spi.write(0x00); + spi.write(length); //data length code + for (i=0;i<length;i++) { //load data buffer + spi.write(data[i]); + } + + cs = 1; + +} + +//------------------------------------------------------------------------------ +//Added for ram +void MCP2515::writeRegister(byte address, byte data) +{ + cs = 0; + wait_ms(10); + spi.write(WRITE); + spi.write(address); + spi.write(data); + wait_ms(10); + cs = 1; + wait_ms(10); +} +void MCP2515::readRegister(byte address, byte *data_out) +{ + cs = 0; + wait_ms(10); + spi.write(READ); + spi.write(address); + *data_out = spi.write(0xFF); + wait_ms(10); + cs = 1; + wait_ms(10); +} + +void MCP2515::reset() +{ + cs = 0; + wait_ms(10); + spi.write(RESET_REG); + wait_ms(10); + cs = 1; + wait_ms(10); +} + +byte MCP2515::readRXStatus() +{ + byte retVal; + cs = 0; + spi.write(RX_STATUS); + retVal = spi.write(0xFF); + cs = 1; + return retVal; +} + +void MCP2515::bitModify(byte address, byte mask, byte data) +{ + cs = 0; + spi.write(BIT_MODIFY); + spi.write(address); + spi.write(mask); + spi.write(data); + cs = 1; +} + +void MCP2515::setMask(unsigned short identifier) +{ + setMask_0(identifier); + setMask_1(identifier); +} + +void MCP2515::setMask_0(unsigned short identifier) +{ + writeRegister(RXM0SIDH, (byte)(identifier>>3)); + writeRegister(RXM0SIDL, (byte)(identifier<<5)); +} + +void MCP2515::setMask_1(unsigned short identifier) +{ + writeRegister(RXM1SIDH, (byte)(identifier>>3)); + writeRegister(RXM1SIDL, (byte)(identifier<<5)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MCP2515.h Fri Jan 18 17:00:28 2013 +0000 @@ -0,0 +1,268 @@ +#include "mbed.h" + +/* +Created by: Kyle Crockett +For MCP2515duino with 16MHz oscillator. +CNFx register values. +use preprocessor command "_XXkbps" +"XX" is the baud rate. + +10 kbps +CNF1/BRGCON1 b'00110001' 0x31 +CNF2/BRGCON2 b'10111000' 0xB8 +CNF3/BRGCON3 b'00000101' 0x05 + +20 kbps +CNF1/BRGCON1 b'00011000' 0x18 +CNF2/BRGCON2 b'10111000' 0xB8 +CNF3/BRGCON3 b'00000101' 0x05 + +50 kbps +CNF1/BRGCON1 b'00001001' 0x09 +CNF2/BRGCON2 b'10111000' 0xB8 +CNF3/BRGCON3 b'00000101' 0x05 + +100 kbps +CNF1/BRGCON1 b'00000100' 0x04 +CNF2/BRGCON2 b'10111000' 0xB8 +CNF3/BRGCON3 b'00000101' 0x05 + +125 kbps +CNF1/BRGCON1 b'00000011' 0x03 +CNF2/BRGCON2 b'10111000' 0xB8 +CNF3/BRGCON3 b'00000101' 0x05 + +250 kbps +CNF1/BRGCON1 b'00000001' 0x01 +CNF2/BRGCON2 b'10111000' 0xB8 +CNF3/BRGCON3 b'00000101' 0x05 + +500 kbps +CNF1/BRGCON1 b'00000000' 0x00 +CNF2/BRGCON2 b'10111000' 0xB8 +CNF3/BRGCON3 b'00000101' 0x05 + +800 kbps +Not yet supported + +1000 kbps +Settings added by Patrick Cruce(pcruce_at_igpp.ucla.edu) +CNF1=b'10000000'=0x80 = SJW = 3 Tq. & BRP = 0 +CNF2=b'10010000'=0x90 = BLTMode = 1 & SAM = 0 & PS1 = 3 & PR = 1 +CNF3=b'00000010'=0x02 = SOF = 0 & WAKFIL = 0 & PS2 = 3 + +*/ +#ifndef MCP2515_h +#define MCP2515_h + +#define SCK 13 //spi +#define MISO 12 +#define MOSI 11 +#define SS 10 +#define RESET 2//reset pin + +#define RESET_REG 0xc0 +#define READ 0x03 +#define WRITE 0x02 //read and write comands for SPI + +#define READ_RX_BUF_0_ID 0x90 +#define READ_RX_BUF_0_DATA 0x92 +#define READ_RX_BUF_1_ID 0x94 +#define READ_RX_BUF_1_DATA 0x96 //SPI commands for reading MCP2515 RX buffers + +#define LOAD_TX_BUF_0_ID 0x40 +#define LOAD_TX_BUF_0_DATA 0x41 +#define LOAD_TX_BUF_1_ID 0x42 +#define LOAD_TX_BUF_1_DATA 0x43 +#define LOAD_TX_BUF_2_ID 0x44 +#define LOAD_TX_BUF_2_DATA 0x45 //SPI commands for loading MCP2515 TX buffers + +#define SEND_TX_BUF_0 0x81 +#define SEND_TX_BUF_1 0x82 +#define SEND_TX_BUF_2 0x83 //SPI commands for transmitting MCP2515 TX buffers + +#define READ_STATUS 0xA0 +#define RX_STATUS 0xB0 +#define BIT_MODIFY 0x05 //Other commands + + +//Registers +#define CNF0 0x2A +#define CNF1 0x29 +#define CNF2 0x28 +#define TXB0CTRL 0x30 +#define TXB1CTRL 0x40 +#define TXB2CTRL 0x50 //TRANSMIT BUFFER CONTROL REGISTER +#define TXB0DLC 0x35 //Data length code registers +#define TXB1DLC 0x45 +#define TXB2DLC 0x55 +#define MCP2515CTRL 0x0F //Mode control register +#define MCP2515STAT 0x0E //Mode status register + +//------------------------------------------------------------------------------ +//Added for ram +// Register Bit Masks +// MCP2515STAT +#define MODE_CONFIG 0x80 +#define MODE_LISTEN 0x60 +#define MODE_LOOPBACK 0x40 +#define MODE_SLEEP 0x20 +#define MODE_NORMAL 0x00 + +//MCP2515 bus error counter +#define TEC 0x1C +#define REC 0x1D + +//Mask 0 +#define RXM0SIDH 0x20 //Mask0 normal ID high +#define RXM0SIDL 0x21 //Mask0 normal ID low +#define RXM0EID8 0x22 //Mask0 extended ID high +#define RXM0EID0 0x23 //Mask0 extended ID low + +//Mask 1 +#define RXM1SIDH 0x24 //Mask1 normal ID high +#define RXM1SIDL 0x25 //Mask1 normal ID low +#define RXM1EID8 0x26 //Mask1 extended ID high +#define RXM1EID0 0x27 //Mask1 extended ID low + +#define MCP2515INTE 0x2B //Interept permission +#define MCP2515INTF 0x2C //Interept flag +#define EFLG 0x2D //Error flag + +#define MASK_SID_ALL_HIT 0x0000 //Mask all +#define MASK_SID_CPL_MATCH 0x07FF //Disable mask + + +#define MCP2515_RTS 0x80 +#define MCP2515_READ_BUFFER 0x90 +#define MCP2515_LOAD_BUFFER 0X40 + +//.............................................................................. +//test +// MCP2515INTF +#define RX0IF 0x01 +#define RX1IF 0x02 +#define TX0IF 0x04 +#define TX1IF 0x08 +#define TX2IF 0x10 +#define ERRIF 0x20 +#define WAKIF 0x40 +#define MERRF 0x80 + +// Configuration Registers +#define BFPCTRL 0x0C +#define TXRTSCTRL 0x0D + +// TX Buffer 0 +#define TXB0CTRL 0x30 +#define TXB0SIDH 0x31 +#define TXB0SIDL 0x32 +#define TXB0EID8 0x33 +#define TXB0EID0 0x34 +#define TXB0DLC 0x35 + +// TX Buffer 1 +#define TXB1CTRL 0x40 +#define TXB1SIDH 0x41 +#define TXB1SIDL 0x42 +#define TXB1EID8 0x43 +#define TXB1EID0 0x44 +#define TXB1DLC 0x45 + +// TX Buffer 2 +#define TXB2CTRL 0x50 +#define TXB2SIDH 0x51 +#define TXB2SIDL 0x52 +#define TXB2EID8 0x53 +#define TXB2EID0 0x54 +#define TXB2DLC 0x55 + +// RX Buffer 0 +#define RXB0CTRL 0x60 +#define RXB0SIDH 0x61 +#define RXB0SIDL 0x62 +#define RXB0EID8 0x63 +#define RXB0EID0 0x64 +#define RXB0DLC 0x65 + +// RX Buffer 1 +#define RXB1CTRL 0x70 +#define RXB1SIDH 0x71 +#define RXB1SIDL 0x72 +#define RXB1EID8 0x73 +#define RXB1EID0 0x74 +#define RXB1DLC 0x75 + +// Buffer Bit Masks +#define RXB0 0x00 +#define RXB1 0x02 +#define TXB0 0x01 +#define TXB1 0x02 +#define TXB2 0x04 +#define TXB_ALL TXB0 | TXB1 | TXB2 + +#define RXB_RX_STDEXT 0x00 +#define RXB_RX_MASK 0x60 +#define RXB_BUKT_MASK (1<<2) + +typedef unsigned char byte; + +enum MCP2515Mode {CONFIGURATION,NORMAL,SLEEP,LISTEN,LOOPBACK}; + +class MCP2515 +{ +public: + MCP2515(SPI& spi, PinName cs); + //void begin();//sets up MCP2515 + void baudConfig(int bitRate);//sets up baud + + //Method added to enable testing in loopback mode.(pcruce_at_igpp.ucla.edu) + void setMode(MCP2515Mode mode) ;//put MCP2515 controller in one of five modes + + void send_0();//request to transmit buffer X + void send_1(); + void send_2(); + + char readID_0();//read ID/DATA of recieve buffer X + char readID_1(); + + char readDATA_0(); + char readDATA_1(); + + //extending MCP2515 data read to full frames(pcruce_at_igpp.ucla.edu) + //data_out should be array of 8-bytes or frame length. + void readDATA_ff_0(byte* length_out,byte *data_out,unsigned short *id_out); + void readDATA_ff_1(byte* length_out,byte *data_out,unsigned short *id_out); + + //Adding MCP2515 to read status register(pcruce_at_igpp.ucla.edu) + //MCP2515 be used to determine whether a frame was received. + //(readStatus() & 0x80) == 0x80 means frame in buffer 0 + //(readStatus() & 0x40) == 0x40 means frame in buffer 1 + byte readStatus(); + + void load_0(byte identifier, byte data);//load transmit buffer X + void load_1(byte identifier, byte data); + void load_2(byte identifier, byte data); + + //extending MCP2515 write to full frame(pcruce_at_igpp.ucla.edu) + //Identifier should be a value between 0 and 2^11-1, longer identifiers will be truncated(ie does not support extended frames) + void load_ff_0(byte length,unsigned short identifier,byte *data); + void load_ff_1(byte length,unsigned short identifier,byte *data); + void load_ff_2(byte length,unsigned short identifier,byte *data); + + //-------------------------------------------------------------------------- + //Added for ram + void writeRegister(byte address, byte data); + void readRegister(byte address, byte *data_out); + void reset(); + byte readRXStatus(); + void bitModify(byte address, byte mask, byte data); + void setMask(unsigned short identifier); + void setMask_0(unsigned short identifier); + void setMask_1(unsigned short identifier); +private: + DigitalOut cs; + SPI &spi; +}; + +#endif