mirror of
https://github.com/Seeed-Studio/Seeed_Arduino_CAN.git
synced 2026-07-28 04:06:45 +00:00
Add: arbitary baudrate for MCP2518FD, and MCP2515 compatible definitions
This commit is contained in:
+2
-2
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user