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
MCP2515.cpp
- Committer:
- FalconOnishi
- Date:
- 2013-01-18
- Revision:
- 0:b65cb1bbf0ce
File content as of revision 0:b65cb1bbf0ce:
#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));
}