Add: arbitary baudrate for MCP2518FD, and MCP2515 compatible definitions

This commit is contained in:
turmary
2021-01-29 23:32:51 +08:00
parent 9826a04cae
commit b2247a8436
6 changed files with 270 additions and 726 deletions
+2 -2
View File
@@ -931,9 +931,9 @@ byte mcp2515_can::mcp2515_getNextFreeTXBuf(byte* txbuf_n) { // get
** Function name: begin
** Descriptions: init can and set speed
*********************************************************************************************************/
byte mcp2515_can::begin(byte speedset, const byte clockset) {
byte mcp2515_can::begin(uint32_t speedset, const byte clockset) {
pSPI->begin();
byte res = mcp2515_init(speedset, clockset);
byte res = mcp2515_init((byte)speedset, clockset);
return ((res == MCP2515_OK) ? CAN_OK : CAN_FAILINIT);
}
+1 -1
View File
@@ -69,7 +69,7 @@ public:
{
return MCP_N_TXBUFFERS - 1; // read index of last tx buffer
}
virtual byte begin(byte speedset, const byte clockset = MCP_16MHz); // init can
virtual byte begin(uint32_t speedset, const byte clockset = MCP_16MHz); // init can
virtual byte init_Mask(byte num, byte ext, unsigned long ulData); // init Masks
virtual byte init_Filt(byte num, byte ext, unsigned long ulData); // init filters
virtual void setSleepWakeup(byte enable); // Enable or disable the wake up interrupt (If disabled the MCP2515 will not be woken up by CAN bus activity, making it send only)
+211 -663
View File
@@ -55,8 +55,12 @@ uint16_t DRV_CANFDSPI_CalculateCRC16(uint8_t *data, uint16_t size) {
** Function name: begin
** Descriptions: init can and set speed
*********************************************************************************************************/
byte mcp2518fd::begin(byte speedset, const byte clockset) {
byte mcp2518fd::begin(uint32_t speedset, const byte clockset) {
SPI.begin();
/* compatible layer translation */
speedset = bittime_compat_to_mcp2518fd(speedset);
byte res = mcp2518fd_init(speedset, clockset);
return res;
}
@@ -809,318 +813,164 @@ int8_t mcp2518fd::mcp2518fd_FilterToFifoLink(CAN_FILTER filter,
return spiTransferError;
}
int8_t mcp2518fd::mcp2518fd_BitTimeConfigureNominal40MHz(
MCP2518FD_BITTIME_SETUP bitTime) {
/*
* bittime calculation code from
* https://github.com/pierremolinaro/acan2517FD
*
*/
static const uint16_t MAX_BRP = 256 ;
static const uint16_t MAX_ARBITRATION_PHASE_SEGMENT_1 = 256 ;
static const uint8_t MAX_ARBITRATION_PHASE_SEGMENT_2 = 128 ;
static const uint8_t MAX_ARBITRATION_SJW = 128 ;
static const uint16_t MAX_DATA_PHASE_SEGMENT_1 = 32 ;
static const uint8_t MAX_DATA_PHASE_SEGMENT_2 = 16 ;
static const uint8_t MAX_DATA_SJW = 16 ;
int mcp2518fd::calcBittime(const uint32_t inDesiredArbitrationBitRate,
const uint32_t inTolerancePPM)
{
if (mDataBitRateFactor <= 1) { // Single bit rate
const uint32_t maxTQCount = MAX_ARBITRATION_PHASE_SEGMENT_1 + MAX_ARBITRATION_PHASE_SEGMENT_2 + 1 ; // Setting for slowest bit rate
uint32_t BRP = MAX_BRP ;
uint32_t smallestError = UINT32_MAX ;
uint32_t bestBRP = 1 ; // Setting for highest bit rate
uint32_t bestTQCount = 4 ; // Setting for highest bit rate
uint32_t TQCount = mSysClock / inDesiredArbitrationBitRate / BRP ;
//--- Loop for finding best BRP and best TQCount
while ((TQCount <= (MAX_ARBITRATION_PHASE_SEGMENT_1 + MAX_ARBITRATION_PHASE_SEGMENT_2 + 1)) && (BRP > 0)) {
//--- Compute error using TQCount
if ((TQCount >= 4) && (TQCount <= maxTQCount)) {
const uint32_t error = mSysClock - inDesiredArbitrationBitRate * TQCount * BRP ; // error is always >= 0
if (error <= smallestError) {
smallestError = error ;
bestBRP = BRP ;
bestTQCount = TQCount ;
}
}
//--- Compute error using TQCount+1
if ((TQCount >= 3) && (TQCount < maxTQCount)) {
const uint32_t error = inDesiredArbitrationBitRate * (TQCount + 1) * BRP - mSysClock ; // error is always >= 0
if (error <= smallestError) {
smallestError = error ;
bestBRP = BRP ;
bestTQCount = TQCount + 1 ;
}
}
//--- Continue with next value of BRP
BRP -- ;
TQCount = (BRP == 0) ? (maxTQCount + 1) : (mSysClock / inDesiredArbitrationBitRate / BRP) ;
}
//--- Compute PS2 (1 <= PS2 <= 128)
uint32_t PS2 = bestTQCount / 5 ; // For sampling point at 80%
if (PS2 == 0) {
PS2 = 1 ;
}else if (PS2 > MAX_ARBITRATION_PHASE_SEGMENT_2) {
PS2 = MAX_ARBITRATION_PHASE_SEGMENT_2 ;
}
//--- Compute PS1 (1 <= PS1 <= 256)
uint32_t PS1 = bestTQCount - PS2 - 1 /* Sync Seg */ ;
if (PS1 > MAX_ARBITRATION_PHASE_SEGMENT_1) {
PS2 += PS1 - MAX_ARBITRATION_PHASE_SEGMENT_1 ;
PS1 = MAX_ARBITRATION_PHASE_SEGMENT_1 ;
}
//---
mBitRatePrescaler = (uint16_t) bestBRP ;
mArbitrationPhaseSegment1 = (uint16_t) PS1 ;
mArbitrationPhaseSegment2 = (uint8_t) PS2 ;
mArbitrationSJW = mArbitrationPhaseSegment2 ; // Always 1 <= SJW <= 128, and SJW <= mArbitrationPhaseSegment2
//--- Final check of the nominal configuration
const uint32_t W = bestTQCount * inDesiredArbitrationBitRate * bestBRP ;
const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ;
const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno
mArbitrationBitRateClosedToDesiredRate = (diff * ppm) <= (((uint64_t) W) * inTolerancePPM) ;
}else{ // Dual bit rate, first compute data bit rate
const uint32_t maxDataTQCount = MAX_DATA_PHASE_SEGMENT_1 + MAX_DATA_PHASE_SEGMENT_2 ; // Setting for slowest bit rate
const uint32_t desiredDataBitRate = inDesiredArbitrationBitRate * uint8_t (mDataBitRateFactor) ;
uint32_t smallestError = UINT32_MAX ;
uint32_t bestBRP = MAX_BRP ; // Setting for lowest bit rate
uint32_t bestDataTQCount = maxDataTQCount ; // Setting for lowest bit rate
uint32_t dataTQCount = 4 ;
uint32_t brp = mSysClock / desiredDataBitRate / dataTQCount ;
//--- Loop for finding best BRP and best TQCount
while ((dataTQCount <= maxDataTQCount) && (brp > 0)) {
//--- Compute error using brp
if (brp <= MAX_BRP) {
const uint32_t error = mSysClock - desiredDataBitRate * dataTQCount * brp ; // error is always >= 0
if (error <= smallestError) {
smallestError = error ;
bestBRP = brp ;
bestDataTQCount = dataTQCount ;
}
}
//--- Compute error using brp+1
if (brp < MAX_BRP) {
const uint32_t error = desiredDataBitRate * dataTQCount * (brp + 1) - mSysClock ; // error is always >= 0
if (error <= smallestError) {
smallestError = error ;
bestBRP = brp + 1 ;
bestDataTQCount = dataTQCount ;
}
}
//--- Continue with next value of BRP
dataTQCount += 1 ;
brp = mSysClock / desiredDataBitRate / dataTQCount ;
}
//--- Compute data PS2 (1 <= PS2 <= 16)
uint32_t dataPS2 = bestDataTQCount / 5 ; // For sampling point at 80%
if (dataPS2 == 0) {
dataPS2 = 1 ;
}
//--- Compute data PS1 (1 <= PS1 <= 32)
uint32_t dataPS1 = bestDataTQCount - dataPS2 - 1 /* Sync Seg */ ;
if (dataPS1 > MAX_DATA_PHASE_SEGMENT_1) {
dataPS2 += dataPS1 - MAX_DATA_PHASE_SEGMENT_1 ;
dataPS1 = MAX_DATA_PHASE_SEGMENT_1 ;
}
//---
const int TDCO = bestBRP * dataPS1 ; // According to DS20005678D, §3.4.8 Page 20
mTDCO = (TDCO > 63) ? 63 : (int8_t) TDCO ;
mDataPhaseSegment1 = (uint8_t) dataPS1 ;
mDataPhaseSegment2 = (uint8_t) dataPS2 ;
mDataSJW = mDataPhaseSegment2 ;
const uint32_t arbitrationTQCount = bestDataTQCount * uint8_t (mDataBitRateFactor) ;
//--- Compute arbiration PS2 (1 <= PS2 <= 128)
uint32_t arbitrationPS2 = arbitrationTQCount / 5 ; // For sampling point at 80%
if (arbitrationPS2 == 0) {
arbitrationPS2 = 1 ;
}
//--- Compute PS1 (1 <= PS1 <= 256)
uint32_t arbitrationPS1 = arbitrationTQCount - arbitrationPS2 - 1 /* Sync Seg */ ;
if (arbitrationPS1 > MAX_ARBITRATION_PHASE_SEGMENT_1) {
arbitrationPS2 += arbitrationPS1 - MAX_ARBITRATION_PHASE_SEGMENT_1 ;
arbitrationPS1 = MAX_ARBITRATION_PHASE_SEGMENT_1 ;
}
//---
mBitRatePrescaler = (uint16_t) bestBRP ;
mArbitrationPhaseSegment1 = (uint16_t) arbitrationPS1 ;
mArbitrationPhaseSegment2 = (uint8_t) arbitrationPS2 ;
mArbitrationSJW = mArbitrationPhaseSegment2 ; // Always 1 <= SJW <= 128, and SJW <= mArbitrationPhaseSegment2
//--- Final check of the nominal configuration
const uint32_t W = arbitrationTQCount * inDesiredArbitrationBitRate * bestBRP ;
const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ;
const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno
mArbitrationBitRateClosedToDesiredRate = (diff * ppm) <= (((uint64_t) W) * inTolerancePPM) ;
}
return mArbitrationBitRateClosedToDesiredRate;
}
int8_t mcp2518fd::mcp2518fd_BitTimeConfigureNominal() {
int8_t spiTransferError = 0;
REG_CiNBTCFG ciNbtcfg;
ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4];
// Arbitration Bit rate
switch (bitTime) {
// All 500K
case CAN_500K_1M:
case CAN_500K_2M:
case CAN_500K_3M:
case CAN_500K_4M:
case CAN_500K_5M:
case CAN_500K_6M7:
case CAN_500K_8M:
case CAN_500K_10M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 62;
ciNbtcfg.bF.TSEG2 = 15;
ciNbtcfg.bF.SJW = 15;
break;
// All 250K
case CAN_250K_500K:
case CAN_250K_833K:
case CAN_250K_1M:
case CAN_250K_1M5:
case CAN_250K_2M:
case CAN_250K_3M:
case CAN_250K_4M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 126;
ciNbtcfg.bF.TSEG2 = 31;
ciNbtcfg.bF.SJW = 31;
break;
case CAN_1000K_4M:
case CAN_1000K_8M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 30;
ciNbtcfg.bF.TSEG2 = 7;
ciNbtcfg.bF.SJW = 7;
break;
case CAN_125K_500K:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 254;
ciNbtcfg.bF.TSEG2 = 63;
ciNbtcfg.bF.SJW = 63;
break;
default:
return -1;
break;
}
// Write Bit time registers
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiNBTCFG, ciNbtcfg.word);
return spiTransferError;
}
int8_t
mcp2518fd::mcp2518fd_BitTimeConfigureData40MHz(MCP2518FD_BITTIME_SETUP bitTime,
CAN_SSP_MODE sspMode) {
int8_t spiTransferError = 0;
REG_CiDBTCFG ciDbtcfg;
REG_CiTDC ciTdc;
(void)sspMode;
ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4];
ciTdc.word = 0;
// Configure Bit time and sample point
ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO;
uint32_t tdcValue = 0;
// Data Bit rate and SSP
switch (bitTime) {
case CAN_500K_1M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 30;
ciDbtcfg.bF.TSEG2 = 7;
ciDbtcfg.bF.SJW = 7;
// SSP
ciTdc.bF.TDCOffset = 31;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_2M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 14;
ciDbtcfg.bF.TSEG2 = 3;
ciDbtcfg.bF.SJW = 3;
// SSP
ciTdc.bF.TDCOffset = 15;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_3M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 8;
ciDbtcfg.bF.TSEG2 = 2;
ciDbtcfg.bF.SJW = 2;
// SSP
ciTdc.bF.TDCOffset = 9;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_4M:
case CAN_1000K_4M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 6;
ciDbtcfg.bF.TSEG2 = 1;
ciDbtcfg.bF.SJW = 1;
// SSP
ciTdc.bF.TDCOffset = 7;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_5M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 4;
ciDbtcfg.bF.TSEG2 = 1;
ciDbtcfg.bF.SJW = 1;
// SSP
ciTdc.bF.TDCOffset = 5;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_6M7:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 3;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 4;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_8M:
case CAN_1000K_8M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 2;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 3;
ciTdc.bF.TDCValue = 1;
break;
case CAN_500K_10M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 1;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 2;
ciTdc.bF.TDCValue = 0;
break;
case CAN_250K_500K:
case CAN_125K_500K:
ciDbtcfg.bF.BRP = 1;
ciDbtcfg.bF.TSEG1 = 30;
ciDbtcfg.bF.TSEG2 = 7;
ciDbtcfg.bF.SJW = 7;
// SSP
ciTdc.bF.TDCOffset = 31;
ciTdc.bF.TDCValue = tdcValue;
ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF;
break;
case CAN_250K_833K:
ciDbtcfg.bF.BRP = 1;
ciDbtcfg.bF.TSEG1 = 17;
ciDbtcfg.bF.TSEG2 = 4;
ciDbtcfg.bF.SJW = 4;
// SSP
ciTdc.bF.TDCOffset = 18;
ciTdc.bF.TDCValue = tdcValue;
ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF;
break;
case CAN_250K_1M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 30;
ciDbtcfg.bF.TSEG2 = 7;
ciDbtcfg.bF.SJW = 7;
// SSP
ciTdc.bF.TDCOffset = 31;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_1M5:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 18;
ciDbtcfg.bF.TSEG2 = 5;
ciDbtcfg.bF.SJW = 5;
// SSP
ciTdc.bF.TDCOffset = 19;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_2M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 14;
ciDbtcfg.bF.TSEG2 = 3;
ciDbtcfg.bF.SJW = 3;
// SSP
ciTdc.bF.TDCOffset = 15;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_3M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 8;
ciDbtcfg.bF.TSEG2 = 2;
ciDbtcfg.bF.SJW = 2;
// SSP
ciTdc.bF.TDCOffset = 9;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_4M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 6;
ciDbtcfg.bF.TSEG2 = 1;
ciDbtcfg.bF.SJW = 1;
// SSP
ciTdc.bF.TDCOffset = 7;
ciTdc.bF.TDCValue = tdcValue;
break;
default:
return -1;
break;
}
// Write Bit time registers
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiDBTCFG, ciDbtcfg.word);
if (spiTransferError) {
return -2;
}
// Write Transmitter Delay Compensation
#ifdef REV_A
ciTdc.bF.TDCOffset = 0;
ciTdc.bF.TDCValue = 0;
#endif
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiTDC, ciTdc.word);
if (spiTransferError) {
return -3;
}
return spiTransferError;
}
int8_t mcp2518fd::mcp2518fd_BitTimeConfigureNominal20MHz(
MCP2518FD_BITTIME_SETUP bitTime) {
int8_t spiTransferError = 0;
REG_CiNBTCFG ciNbtcfg;
ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4];
// Arbitration Bit rate
switch (bitTime) {
// All 500K
case CAN_500K_1M:
case CAN_500K_2M:
case CAN_500K_4M:
case CAN_500K_5M:
case CAN_500K_6M7:
case CAN_500K_8M:
case CAN_500K_10M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 30;
ciNbtcfg.bF.TSEG2 = 7;
ciNbtcfg.bF.SJW = 7;
break;
// All 250K
case CAN_250K_500K:
case CAN_250K_833K:
case CAN_250K_1M:
case CAN_250K_1M5:
case CAN_250K_2M:
case CAN_250K_3M:
case CAN_250K_4M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 62;
ciNbtcfg.bF.TSEG2 = 15;
ciNbtcfg.bF.SJW = 15;
break;
case CAN_1000K_4M:
case CAN_1000K_8M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 14;
ciNbtcfg.bF.TSEG2 = 3;
ciNbtcfg.bF.SJW = 3;
break;
case CAN_125K_500K:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 126;
ciNbtcfg.bF.TSEG2 = 31;
ciNbtcfg.bF.SJW = 31;
break;
default:
return -1;
break;
}
ciNbtcfg.bF.BRP = mBitRatePrescaler - 1;
ciNbtcfg.bF.TSEG1 = mArbitrationPhaseSegment1 - 1;
ciNbtcfg.bF.TSEG2 = mArbitrationPhaseSegment2 - 1;
ciNbtcfg.bF.SJW = mArbitrationSJW - 1;
// Write Bit time registers
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiNBTCFG, ciNbtcfg.word);
@@ -1132,149 +982,28 @@ int8_t mcp2518fd::mcp2518fd_BitTimeConfigureNominal20MHz(
}
int8_t
mcp2518fd::mcp2518fd_BitTimeConfigureData20MHz(MCP2518FD_BITTIME_SETUP bitTime,
CAN_SSP_MODE sspMode) {
mcp2518fd::mcp2518fd_BitTimeConfigureData(CAN_SSP_MODE sspMode) {
int8_t spiTransferError = 0;
REG_CiDBTCFG ciDbtcfg;
REG_CiTDC ciTdc;
(void)sspMode;
ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4];
ciTdc.word = 0;
// Configure Bit time and sample point
ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO;
uint32_t tdcValue = 0;
// Data Bit rate and SSP
switch (bitTime) {
case CAN_500K_1M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 14;
ciDbtcfg.bF.TSEG2 = 3;
ciDbtcfg.bF.SJW = 3;
// SSP
ciTdc.bF.TDCOffset = 15;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_2M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 6;
ciDbtcfg.bF.TSEG2 = 1;
ciDbtcfg.bF.SJW = 1;
// SSP
ciTdc.bF.TDCOffset = 7;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_4M:
case CAN_1000K_4M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 2;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 3;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_5M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 1;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 2;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_6M7:
case CAN_500K_8M:
case CAN_500K_10M:
case CAN_1000K_8M:
// qDebug("Data Bitrate not feasible with this clock!");
return -1;
break;
case CAN_250K_500K:
case CAN_125K_500K:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 30;
ciDbtcfg.bF.TSEG2 = 7;
ciDbtcfg.bF.SJW = 7;
// SSP
ciTdc.bF.TDCOffset = 31;
ciTdc.bF.TDCValue = tdcValue;
ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF;
break;
case CAN_250K_833K:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 17;
ciDbtcfg.bF.TSEG2 = 4;
ciDbtcfg.bF.SJW = 4;
// SSP
ciTdc.bF.TDCOffset = 18;
ciTdc.bF.TDCValue = tdcValue;
ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF;
break;
case CAN_250K_1M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 14;
ciDbtcfg.bF.TSEG2 = 3;
ciDbtcfg.bF.SJW = 3;
// SSP
ciTdc.bF.TDCOffset = 15;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_1M5:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 8;
ciDbtcfg.bF.TSEG2 = 2;
ciDbtcfg.bF.SJW = 2;
// SSP
ciTdc.bF.TDCOffset = 9;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_2M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 6;
ciDbtcfg.bF.TSEG2 = 1;
ciDbtcfg.bF.SJW = 1;
// SSP
ciTdc.bF.TDCOffset = 7;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_3M:
// qDebug("Data Bitrate not feasible with this clock!");
return -1;
break;
case CAN_250K_4M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 2;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 3;
ciTdc.bF.TDCValue = tdcValue;
break;
default:
return -1;
break;
}
// Write Bit time registers
ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4];
ciDbtcfg.bF.BRP = mBitRatePrescaler - 1;
ciDbtcfg.bF.TSEG1 = mDataPhaseSegment1 - 1;
ciDbtcfg.bF.TSEG2 = mDataPhaseSegment2 - 1;
ciDbtcfg.bF.SJW = mDataSJW - 1;
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiDBTCFG, ciDbtcfg.word);
if (spiTransferError) {
return -2;
}
// Write Transmitter Delay Compensation
#ifdef REV_A
ciTdc.bF.TDCOffset = 0;
ciTdc.bF.TDCValue = 0;
#endif
// Configure Bit time and sample point, SSP
ciTdc.word = canControlResetValues[cREGADDR_CiTDC / 4];
ciTdc.bF.TDCMode = sspMode;
ciTdc.bF.TDCOffset = mTDCO;
// ciTdc.bF.TDCValue = ?;
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiTDC, ciTdc.word);
if (spiTransferError) {
@@ -1284,226 +1013,30 @@ mcp2518fd::mcp2518fd_BitTimeConfigureData20MHz(MCP2518FD_BITTIME_SETUP bitTime,
return spiTransferError;
}
int8_t mcp2518fd::mcp2518fd_BitTimeConfigureNominal10MHz(
MCP2518FD_BITTIME_SETUP bitTime) {
int8_t spiTransferError = 0;
REG_CiNBTCFG ciNbtcfg;
ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4];
// Arbitration Bit rate
switch (bitTime) {
// All 500K
case CAN_500K_1M:
case CAN_500K_2M:
case CAN_500K_4M:
case CAN_500K_5M:
case CAN_500K_6M7:
case CAN_500K_8M:
case CAN_500K_10M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 14;
ciNbtcfg.bF.TSEG2 = 3;
ciNbtcfg.bF.SJW = 3;
break;
// All 250K
case CAN_250K_500K:
case CAN_250K_833K:
case CAN_250K_1M:
case CAN_250K_1M5:
case CAN_250K_2M:
case CAN_250K_3M:
case CAN_250K_4M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 30;
ciNbtcfg.bF.TSEG2 = 7;
ciNbtcfg.bF.SJW = 7;
break;
case CAN_1000K_4M:
case CAN_1000K_8M:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 7;
ciNbtcfg.bF.TSEG2 = 2;
ciNbtcfg.bF.SJW = 2;
break;
case CAN_125K_500K:
ciNbtcfg.bF.BRP = 0;
ciNbtcfg.bF.TSEG1 = 62;
ciNbtcfg.bF.TSEG2 = 15;
ciNbtcfg.bF.SJW = 15;
break;
default:
return -1;
break;
}
// Write Bit time registers
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiNBTCFG, ciNbtcfg.word);
if (spiTransferError) {
return -2;
}
return spiTransferError;
}
int8_t
mcp2518fd::mcp2518fd_BitTimeConfigureData10MHz(MCP2518FD_BITTIME_SETUP bitTime,
CAN_SSP_MODE sspMode) {
int8_t spiTransferError = 0;
REG_CiDBTCFG ciDbtcfg;
REG_CiTDC ciTdc;
(void)sspMode;
ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4];
ciTdc.word = 0;
// Configure Bit time and sample point
ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO;
uint32_t tdcValue = 0;
// Data Bit rate and SSP
switch (bitTime) {
case CAN_500K_1M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 6;
ciDbtcfg.bF.TSEG2 = 1;
ciDbtcfg.bF.SJW = 1;
// SSP
ciTdc.bF.TDCOffset = 7;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_2M:
// Data BR
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 2;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 3;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_500K_4M:
case CAN_500K_5M:
case CAN_500K_6M7:
case CAN_500K_8M:
case CAN_500K_10M:
case CAN_1000K_4M:
case CAN_1000K_8M:
// qDebug("Data Bitrate not feasible with this clock!");
return -1;
break;
case CAN_250K_500K:
case CAN_125K_500K:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 14;
ciDbtcfg.bF.TSEG2 = 3;
ciDbtcfg.bF.SJW = 3;
// SSP
ciTdc.bF.TDCOffset = 15;
ciTdc.bF.TDCValue = tdcValue;
ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF;
break;
case CAN_250K_833K:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 7;
ciDbtcfg.bF.TSEG2 = 2;
ciDbtcfg.bF.SJW = 2;
// SSP
ciTdc.bF.TDCOffset = 8;
ciTdc.bF.TDCValue = tdcValue;
ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF;
break;
case CAN_250K_1M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 6;
ciDbtcfg.bF.TSEG2 = 1;
ciDbtcfg.bF.SJW = 1;
// SSP
ciTdc.bF.TDCOffset = 7;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_1M5:
// qDebug("Data Bitrate not feasible with this clock!");
return -1;
break;
case CAN_250K_2M:
ciDbtcfg.bF.BRP = 0;
ciDbtcfg.bF.TSEG1 = 2;
ciDbtcfg.bF.TSEG2 = 0;
ciDbtcfg.bF.SJW = 0;
// SSP
ciTdc.bF.TDCOffset = 3;
ciTdc.bF.TDCValue = tdcValue;
break;
case CAN_250K_3M:
case CAN_250K_4M:
// qDebug("Data Bitrate not feasible with this clock!");
return -1;
break;
default:
return -1;
break;
}
// Write Bit time registers
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiDBTCFG, ciDbtcfg.word);
if (spiTransferError) {
return -2;
}
// Write Transmitter Delay Compensation
#ifdef REV_A
ciTdc.bF.TDCOffset = 0;
ciTdc.bF.TDCValue = 0;
#endif
spiTransferError = mcp2518fd_WriteWord(cREGADDR_CiTDC, ciTdc.word);
if (spiTransferError) {
return -3;
}
return spiTransferError;
}
int8_t mcp2518fd::mcp2518fd_BitTimeConfigure(MCP2518FD_BITTIME_SETUP bitTime,
int8_t mcp2518fd::mcp2518fd_BitTimeConfigure(uint32_t speedset,
CAN_SSP_MODE sspMode,
CAN_SYSCLK_SPEED clk) {
int8_t spiTransferError = 0;
// Decode bitrate
mDesiredArbitrationBitRate = speedset & 0xFFFFFUL;
mDataBitRateFactor = (speedset >> 24) & 0xFF;
// Decode clk
switch (clk) {
case CAN_SYSCLK_40M:
spiTransferError = mcp2518fd_BitTimeConfigureNominal40MHz(bitTime);
if (spiTransferError)
return spiTransferError;
spiTransferError = mcp2518fd_BitTimeConfigureData40MHz(bitTime, sspMode);
break;
case CAN_SYSCLK_20M:
spiTransferError = mcp2518fd_BitTimeConfigureNominal20MHz(bitTime);
if (spiTransferError)
return spiTransferError;
spiTransferError = mcp2518fd_BitTimeConfigureData20MHz(bitTime, sspMode);
break;
case CAN_SYSCLK_10M:
spiTransferError = mcp2518fd_BitTimeConfigureNominal10MHz(bitTime);
if (spiTransferError)
return spiTransferError;
spiTransferError = mcp2518fd_BitTimeConfigureData10MHz(bitTime, sspMode);
break;
mSysClock = 10UL * 1000UL * 1000UL; break;
case CAN_SYSCLK_20M:
mSysClock = 20UL * 1000UL * 1000UL; break;
case CAN_SYSCLK_40M:
default:
spiTransferError = -1;
break;
mSysClock = 40UL * 1000UL * 1000UL; break;
}
calcBittime(mDesiredArbitrationBitRate);
mcp2518fd_BitTimeConfigureNominal();
mcp2518fd_BitTimeConfigureData(sspMode);
return spiTransferError;
}
@@ -2264,18 +1797,32 @@ int8_t mcp2518fd::mcp2518fd_receiveMsg() {
return 0;
}
static MCP2518FD_BITTIME_SETUP bittime_compat_to_mcp2518fd(byte speedset) {
MCP2518FD_BITTIME_SETUP r;
uint32_t mcp2518fd::bittime_compat_to_mcp2518fd(uint32_t speedset) {
uint32_t r;
if (speedset > 0x100) {
return speedset;
}
switch (speedset) {
case CAN_125KBPS:
r = CAN_125K_500K; break;
case CAN_250KBPS:
r = CAN_250K_500K; break;
case CAN_500KBPS:
r = CAN_500K_1M; break;
case CAN_1000KBPS:
case CAN_5KBPS: r = CANFD::BITRATE( 5000UL, 0); break;
case CAN_10KBPS: r = CANFD::BITRATE( 10000UL, 0); break;
case CAN_20KBPS: r = CANFD::BITRATE( 20000UL, 0); break;
case CAN_25KBPS: r = CANFD::BITRATE( 25000UL, 0); break;
case CAN_31K25BPS:r = CANFD::BITRATE( 31250UL, 0); break;
case CAN_33KBPS: r = CANFD::BITRATE( 33000UL, 0); break;
case CAN_40KBPS: r = CANFD::BITRATE( 40000UL, 0); break;
case CAN_50KBPS: r = CANFD::BITRATE( 50000UL, 0); break;
case CAN_80KBPS: r = CANFD::BITRATE( 80000UL, 0); break;
case CAN_83K3BPS: r = CANFD::BITRATE( 83300UL, 0); break;
case CAN_95KBPS: r = CANFD::BITRATE( 95000UL, 0); break;
case CAN_100KBPS: r = CANFD::BITRATE( 100000UL, 0); break;
case CAN_125KBPS: r = CANFD::BITRATE( 125000UL, 0); break;
case CAN_200KBPS: r = CANFD::BITRATE( 200000UL, 0); break;
case CAN_250KBPS: r = CANFD::BITRATE( 250000UL, 0); break;
default:
r = CAN_1000K_4M; break;
case CAN_500KBPS: r = CANFD::BITRATE( 500000UL, 0); break;
case CAN_666KBPS: r = CANFD::BITRATE( 666000UL, 0); break;
case CAN_1000KBPS:r = CANFD::BITRATE(1000000UL, 0); break;
}
return r;
}
@@ -2283,8 +1830,10 @@ static MCP2518FD_BITTIME_SETUP bittime_compat_to_mcp2518fd(byte speedset) {
/*********************************************************************************************************
** Function name: mcp2515_init
** Descriptions: init the device
** speedset msb 8 bits = factor (0 or 1 is no bit rate switch)
** lsb 24 bits = arbitration bitrate
*********************************************************************************************************/
uint8_t mcp2518fd::mcp2518fd_init(byte speedset, const byte clock) {
uint8_t mcp2518fd::mcp2518fd_init(uint32_t speedset, const byte clock) {
// Reset device
mcp2518fd_reset();
@@ -2324,8 +1873,7 @@ uint8_t mcp2518fd::mcp2518fd_init(byte speedset, const byte clock) {
mcp2518fd_FilterToFifoLink(CAN_FILTER0, APP_RX_FIFO, true);
// Setup Bit Time
mcp2518fd_BitTimeConfigure(bittime_compat_to_mcp2518fd(speedset),
CAN_SSP_MODE_AUTO, CAN_SYSCLK_SPEED(clock));
mcp2518fd_BitTimeConfigure(speedset, CAN_SSP_MODE_AUTO, CAN_SYSCLK_SPEED(clock));
// Setup Transmit and Receive Interrupts
mcp2518fd_GpioModeConfigure(GPIO_MODE_INT, GPIO_MODE_INT);
+34 -14
View File
@@ -107,7 +107,11 @@ public:
virtual byte getLastTxBuffer() {
return 3 - 1; // read index of last tx buffer
}
virtual byte begin(byte speedset,
/*
* speedset could be in MCP_BITTIME_SETUP,
* or fill by CANFD::BITRATE()
*/
virtual byte begin(uint32_t speedset,
const byte clockset = MCP2518FD_40MHz); // init can
virtual byte init_Mask(byte num, byte ext, unsigned long ulData);
virtual byte init_Filt(byte num, byte ext,
@@ -170,7 +174,7 @@ private:
int8_t mcp2518fd_receiveMsg();
private:
uint8_t mcp2518fd_init(byte speedset, const byte clock); // mcp2518fdinit
uint8_t mcp2518fd_init(uint32_t speedset, const byte clock); // mcp2518fdinit
int8_t mcp2518fd_reset(void); // reset mcp2518fd
int8_t mcp2518fd_EccEnable(void); // Section: ECC
int8_t mcp2518fd_RamInit(uint8_t d);
@@ -189,7 +193,7 @@ private:
int8_t mcp2518fd_FilterMaskConfigure(CAN_FILTER filter, CAN_MASKOBJ_ID *mask);
int8_t mcp2518fd_FilterToFifoLink(CAN_FILTER filter, CAN_FIFO_CHANNEL channel,
bool enable);
int8_t mcp2518fd_BitTimeConfigure(MCP2518FD_BITTIME_SETUP bitTime,
int8_t mcp2518fd_BitTimeConfigure(uint32_t speedset,
CAN_SSP_MODE sspMode, CAN_SYSCLK_SPEED clk);
int8_t mcp2518fd_GpioModeConfigure(GPIO_PIN_MODE gpio0, GPIO_PIN_MODE gpio1);
int8_t mcp2518fd_TransmitChannelEventEnable(CAN_FIFO_CHANNEL channel,
@@ -248,20 +252,33 @@ private:
private:
int8_t
mcp2518fd_BitTimeConfigureNominal40MHz(MCP2518FD_BITTIME_SETUP bitTime);
int8_t mcp2518fd_BitTimeConfigureData40MHz(MCP2518FD_BITTIME_SETUP bitTime,
CAN_SSP_MODE sspMode);
int8_t
mcp2518fd_BitTimeConfigureNominal20MHz(MCP2518FD_BITTIME_SETUP bitTime);
int8_t mcp2518fd_BitTimeConfigureData20MHz(MCP2518FD_BITTIME_SETUP bitTime,
CAN_SSP_MODE sspMode);
int8_t
mcp2518fd_BitTimeConfigureNominal10MHz(MCP2518FD_BITTIME_SETUP bitTime);
int8_t mcp2518fd_BitTimeConfigureData10MHz(MCP2518FD_BITTIME_SETUP bitTime,
CAN_SSP_MODE sspMode);
mcp2518fd_BitTimeConfigureNominal(void);
int8_t mcp2518fd_BitTimeConfigureData(CAN_SSP_MODE sspMode);
byte nReservedTx; // Count of tx buffers for reserved send
CAN_OPERATION_MODE mcpMode = CAN_CLASSIC_MODE; // Current controller mode
uint32_t bittime_compat_to_mcp2518fd(uint32_t speedset);
int calcBittime(const uint32_t inDesiredArbitrationBitRate,
const uint32_t inTolerancePPM = 10000/* 1% */);
uint32_t mSysClock; // PLL disabled, mSysClock = Oscillator Frequency
uint32_t mDesiredArbitrationBitRate; // desired ArbitrationBitRate
uint8_t mDataBitRateFactor; // multiplier between ArbitrationBitRate and DataBitrate
//--- Data bit rate; if mDataBitRateFactor==1, theses properties are not used for configuring the MCP2517FD.
uint8_t mDataPhaseSegment1 = 0 ; // if mDataBitRateFactor > 1: 2...32, else equal to mArbitrationPhaseSegment1
uint8_t mDataPhaseSegment2 = 0 ; // if mDataBitRateFactor > 1: 1...16, else equal to mArbitrationPhaseSegment2
uint8_t mDataSJW = 0 ; // if mDataBitRateFactor > 1: 1...16, else equal to mArbitrationSJW
//--- Bit rate prescaler is common to arbitration and data bit rates
uint16_t mBitRatePrescaler = 0 ; // 1...256
//--- Arbitration bit rate
uint16_t mArbitrationPhaseSegment1 = 0 ; // 2...256
uint8_t mArbitrationPhaseSegment2 = 0 ; // 1...128
uint8_t mArbitrationSJW = 0 ; // 1...128
bool mArbitrationBitRateClosedToDesiredRate = false ; // The above configuration is not correct
//--- Transmitter Delay Compensation Offset
int8_t mTDCO = 0 ; // -64 ... +63
};
/* CANFD Auxiliary helper */
@@ -269,6 +286,9 @@ class CANFD {
public:
static byte dlc2len(byte dlc);
static byte len2dlc(byte len);
static uint32_t BITRATE(uint32_t arbitration, uint8_t factor) {
return ((uint32_t)factor << 24) | (arbitration & 0xFFFFFUL);
}
};
#endif
+21 -45
View File
@@ -589,51 +589,27 @@ typedef enum {
//! CAN Bit Time Setup: Arbitration/Data Bit Phase
typedef enum {
CAN_500K_1M, // 0x00
CAN_500K_2M, // 0x01
CAN_500K_3M,
CAN_500K_4M,
CAN_500K_5M, // 0x04
CAN_500K_6M7,
CAN_500K_8M, // 0x06
CAN_500K_10M,
CAN_250K_500K, // 0x08
CAN_250K_833K,
CAN_250K_1M,
CAN_250K_1M5,
CAN_250K_2M,
CAN_250K_3M,
CAN_250K_4M,
CAN_1000K_4M, // 0x0f
CAN_1000K_8M,
CAN_125K_500K // 0x11
} MCP2518FD_BITTIME_SETUP;
//! CAN Nominal Bit Time Setup
typedef enum {
CAN_NBT_125K,
CAN_NBT_250K,
CAN_NBT_500K,
CAN_NBT_1M
} CAN_NOMINAL_BITTIME_SETUP;
//! CAN Data Bit Time Setup
typedef enum {
CAN_DBT_500K,
CAN_DBT_833K,
CAN_DBT_1M,
CAN_DBT_1M5,
CAN_DBT_2M,
CAN_DBT_3M,
CAN_DBT_4M,
CAN_DBT_5M,
CAN_DBT_6M7,
CAN_DBT_8M,
CAN_DBT_10M
} CAN_DATA_BITTIME_SETUP;
/* not apply to AVR platform */
// typedef enum {
static const uint32_t CAN_125K_500K = ( 4UL << 24) | (125000UL);
static const uint32_t CAN_250K_500K = ( 2UL << 24) | (250000UL);
static const uint32_t CAN_250K_750K = ( 3UL << 24) | (250000UL);
static const uint32_t CAN_250K_1M = ( 4UL << 24) | (250000UL);
static const uint32_t CAN_250K_1M5 = ( 6UL << 24) | (250000UL);
static const uint32_t CAN_250K_2M = ( 8UL << 24) | (250000UL);
static const uint32_t CAN_250K_3M = (12UL << 24) | (250000UL);
static const uint32_t CAN_250K_4M = (16UL << 24) | (250000UL);
static const uint32_t CAN_500K_1M = ( 2UL << 24) | (500000UL);
static const uint32_t CAN_500K_2M = ( 4UL << 24) | (500000UL);
static const uint32_t CAN_500K_3M = ( 6UL << 24) | (500000UL);
static const uint32_t CAN_500K_4M = ( 8UL << 24) | (500000UL);
static const uint32_t CAN_500K_5M = (10UL << 24) | (500000UL);
static const uint32_t CAN_500K_6M5 = (13UL << 24) | (500000UL);
static const uint32_t CAN_500K_8M = (16UL << 24) | (500000UL);
static const uint32_t CAN_500K_10M = (20UL << 24) | (500000UL);
static const uint32_t CAN_1000K_4M = ( 4UL << 24) |(1000000UL);
static const uint32_t CAN_1000K_8M = ( 8UL << 24) |(1000000UL);
//} MCP2518FD_BITTIME_SETUP;
//! Secondary Sample Point Mode
+1 -1
View File
@@ -60,7 +60,7 @@ public:
* speedset be in MCP_BITTIME_SETUP
* clockset be in MCP_CLOCK_T
*/
virtual byte begin(byte speedset, const byte clockset) = 0; // init can
virtual byte begin(uint32_t speedset, const byte clockset) = 0; // init can
virtual byte init_Mask(byte num, byte ext, unsigned long ulData) = 0; // init Masks
virtual byte init_Filt(byte num, byte ext, unsigned long ulData) = 0; // init filters
virtual void setSleepWakeup(byte enable) = 0; // Enable or disable the wake up interrupt