📄 can.c
字号:
#ifdef TargetA
#define ID0 0x100
#define ID1 0x101
#else
#define ID0 0x101
#define ID1 0x100
#endif
#include "MAIN.H"
// Structure for a single TwinCAN object
// A total of 31 such object structures exists
struct stCanObj
{
ubyte ubData[8]; // Message Data 0..7
ulong ulCANAR; // Arbitration Register
ulong ulCANAMR; // Acceptance Mask Register
uword uwMSGCTR; // Message Control Register
uword uwCounter; // Frame Counter
uword uwMSGCFG; // Message Configuration Register
uword uwINP; // Interrupt Node Pointer
uword uwCANFCR; // FIFO / Gateway Control Register
uword uwCANPTR; // FIFO Pointer
ulong ulReserved; // Reserved
};
#define CAN_HWOBJ ((struct stCanObj volatile far *) 0x200300)
static ubyte aubFIFOWritePtr[16];
static ubyte aubFIFOReadPtr[16];
void CAN_vInit(void)
{
ubyte i;
/// -----------------------------------------------------------------------
/// Configuration of CAN Node A:
/// -----------------------------------------------------------------------
/// General Configuration of the Node A:
/// - set INIT and CCE
CAN_ACR = 0x0041; // load global control register
CAN_AGINP = 0x0000; // load global interrupt node pointer
// register
/// Configuration of the Node A Error Counter:
/// - the error warning threshold value (warning level) is 96
CAN_AECNTH = 0x0060; // load error counter register high
/// Configuration of the used CAN Port Pins:
/// - P4.5 is used for CAN Interface Input (RXDCA)
/// - P4.6 is used for CAN Interface Output (TXDCA)
ALTSEL0P4 |= 0x0040; // select alternate output function
DP4 = (DP4 & ~(uword)0x0040) | 0x0040; //set direction register
/// Configuration of the Node A Baud Rate:
/// - required baud rate = 100,000 kbaud
/// - real baud rate = 100,000 kbaud
/// - sample point = 60,00 %
/// - there are 5 time quanta before sample point
/// - there are 4 time quanta after sample point
/// - the (re)synchronization jump width is 2 time quanta
CAN_ABTRL = 0x3453; // load bit timing register low
CAN_ABTRH = 0x0000; // load bit timing register high
CAN_AFCRL = 0x0000; // load frame counter timing register low
CAN_AFCRH = 0x0000; // load frame counter timing register high
/// -----------------------------------------------------------------------
/// Configuration of CAN Node B:
/// -----------------------------------------------------------------------
/// General Configuration of the Node B:
/// - set INIT and CCE
CAN_BCR = 0x0041; // load global control register
/// -----------------------------------------------------------------------
/// Configuration of the CAN Message Objects 0 - 31:
/// -----------------------------------------------------------------------
/// -----------------------------------------------------------------------
/// Configuration of Message Object 0:
/// -----------------------------------------------------------------------
/// - message object 0 is valid
CAN_MSGCTRL0 = 0x5595; // load message control register low
CAN_MSGCTRH0 = 0x0000; // load message control register high
/// - message object is used as transmit object
/// - extended 29-bit identifier
/// - 1 valid data bytes
/// - this message object works with CAN node A
/// - remote monitoring is disabled
CAN_MSGCFGL0 = 0x001C; // load message configuration register low
CAN_MSGCFGH0 = 0x0000; // load message configuration register high
/// - acceptance mask 29-bit: 0xFFFF
/// - identifier 29-bit: 0x0100
CAN_MSGAMRL0 = 0xFFFF; // load acceptance mask register low
CAN_MSGAMRH0 = 0x1FFF; // load acceptance mask register high
CAN_MSGARL0 = ID1; // load arbitration register low
CAN_MSGARH0 = 0x0000; // load arbitration register high
CAN_MSGDRL00 = 0x0000; // load data register 0 low
CAN_MSGDRH00 = 0x0000; // load data register 0 high
CAN_MSGDRL04 = 0x0000; // load data register 4 low
CAN_MSGDRH04 = 0x0000; // load data register 4 high
/// - functionality of standard message object
CAN_MSGFGCRL0 = 0x0000; // load FIFO/gateway control register low
CAN_MSGFGCRH0 = 0x0000; // load FIFO/gateway control register high
/// -----------------------------------------------------------------------
/// Configuration of Message Object 1:
/// -----------------------------------------------------------------------
/// - message object 1 is valid
CAN_MSGCTRL1 = 0x5595; // load message control register low
CAN_MSGCTRH1 = 0x0000; // load message control register high
/// - message object is used as receive object
/// - extended 29-bit identifier
/// - 1 valid data bytes
/// - this message object works with CAN node A
/// - remote monitoring is disabled
CAN_MSGCFGL1 = 0x0014; // load message configuration register low
CAN_MSGCFGH1 = 0x0000; // load message configuration register high
/// - acceptance mask 29-bit: 0xFFFF
/// - identifier 29-bit: 0x0101
CAN_MSGAMRL1 = 0xFFFF; // load acceptance mask register low
CAN_MSGAMRH1 = 0x1FFF; // load acceptance mask register high
CAN_MSGARL1 = ID0; // load arbitration register low
CAN_MSGARH1 = 0x0000; // load arbitration register high
CAN_MSGDRL10 = 0x0000; // load data register 0 low
CAN_MSGDRH10 = 0x0000; // load data register 0 high
CAN_MSGDRL14 = 0x0000; // load data register 4 low
CAN_MSGDRH14 = 0x0000; // load data register 4 high
/// - functionality of standard message object
CAN_MSGFGCRL1 = 0x0000; // load FIFO/gateway control register low
CAN_MSGFGCRH1 = 0x0001; // load FIFO/gateway control register high
/// -----------------------------------------------------------------------
/// Configuration of Service Request Nodes 0 - 7:
/// -----------------------------------------------------------------------
/// -----------------------------------------------------------------------
/// Initialization of the FIFO Pointer:
/// -----------------------------------------------------------------------
for (i = 0; i < 16; i++)
{
aubFIFOWritePtr[i] = i * 2;
aubFIFOReadPtr[i] = i * 2;
}
CAN_PISEL = 0x0000; // load port input select register
// -----------------------------------------------------------------------
// Start the CAN Nodes:
// -----------------------------------------------------------------------
CAN_ACR &= ~(uword)0x0041; // reset INIT and CCE
}
void CAN_vGetMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
ubyte i;
for(i = 0; i < (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x00f0) >> 4; i++)
{
pstObj->ubData[i] = CAN_HWOBJ[ubObjNr].ubData[i];
}
if(CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x04) // extended identifier
{
pstObj->ulID = CAN_HWOBJ[ubObjNr].ulCANAR;
pstObj->ulMask = CAN_HWOBJ[ubObjNr].ulCANAMR;
}
else // standard identifier
{
pstObj->ulID = CAN_HWOBJ[ubObjNr].ulCANAR >> 18;
pstObj->ulMask = CAN_HWOBJ[ubObjNr].ulCANAMR >> 18;
}
pstObj->uwCounter = CAN_HWOBJ[ubObjNr].uwCounter;
pstObj->uwMsgCfg = CAN_HWOBJ[ubObjNr].uwMSGCFG;
}
ubyte CAN_ubRequestMsgObj(ubyte ubObjNr)
{
ubyte ubReturn;
ubReturn = 0;
if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x3000) == 0x1000) // if reset TXRQ
{
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfbff; // set CPUUPD
ubReturn = 1;
}
return(ubReturn);
}
ubyte CAN_ubNewData(ubyte ubObjNr)
{
ubyte ubReturn;
ubReturn = 0;
if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x0300) == 0x0200) // if NEWDAT
{
ubReturn = 1;
}
return(ubReturn);
}
void CAN_vTransmit(ubyte ubObjNr)
{
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xe7ff; // set TXRQ, reset CPUUPD
}
void CAN_vConfigMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
ubyte i;
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfb7f; // set CPUUPD, reset MSGVAL
if(pstObj->uwMsgCfg & 0x0004) // extended identifier
{
CAN_HWOBJ[ubObjNr].uwMSGCFG |= 0x0004;
CAN_HWOBJ[ubObjNr].ulCANAR = pstObj->ulID ;
CAN_HWOBJ[ubObjNr].ulCANAMR = pstObj->ulMask ;
}
else // standard identifier
{
CAN_HWOBJ[ubObjNr].uwMSGCFG &= ~(uword)0x0004;
CAN_HWOBJ[ubObjNr].ulCANAR = pstObj->ulID << 18;
CAN_HWOBJ[ubObjNr].ulCANAMR = pstObj->ulMask << 18;
}
CAN_HWOBJ[ubObjNr].uwCounter = pstObj->uwCounter;
CAN_HWOBJ[ubObjNr].uwMSGCFG = (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x000f) | (pstObj->uwMsgCfg & 0x00f0);
if(CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x0008) // if transmit direction
{
for(i = 0; i < (pstObj->uwMsgCfg & 0x00f0) >> 4; i++)
{
CAN_HWOBJ[ubObjNr].ubData[i] = pstObj->ubData[i];
}
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf6bf; // set NEWDAT, reset CPUUPD,
} // set MSGVAL
else // if receive direction
{
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf7bf; // reset CPUUPD, set MSGVAL
}
}
void CAN_vLoadData(ubyte ubObjNr, ubyte *pubData)
{
ubyte i;
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfaff; // set CPUUPD and NEWDAT
for(i = 0; i < (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0xf0) >> 4; i++)
{
CAN_HWOBJ[ubObjNr].ubData[i] = *(pubData++);
}
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf7ff; // reset CPUUPD
}
ubyte CAN_ubMsgLost(ubyte ubObjNr)
{
ubyte ubReturn;
ubReturn = 0;
if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x0c00) == 0x0800) // if set MSGLST
{
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf7ff; // reset MSGLST
ubReturn = 1;
}
return(ubReturn);
}
ubyte CAN_ubDelMsgObj(ubyte ubObjNr)
{
ubyte ubReturn;
ubReturn = 0;
if(!(CAN_HWOBJ[ubObjNr].uwMSGCTR & 0xa200)) // if set RMTPND, TXRQ or NEWDAT
{
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xff7f; // reset MSGVAL
ubReturn = 1;
}
return(ubReturn);
}
void CAN_vReleaseObj(ubyte ubObjNr)
{
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfdff; // reset NEWDAT
}
void CAN_vSetMSGVAL(ubyte ubObjNr)
{
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xffbf; // set MSGVAL
} // End of function CAN_vSetMSGVAL
ubyte CAN_ubWriteFIFO(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
ubyte i,j;
ubyte ubReturn;
ubReturn = 2;
if((CAN_HWOBJ[ubObjNr].uwCANPTR & 0x0700) == 0x0200) // if FIFO base object
{
j = aubFIFOWritePtr[ubObjNr / 2];
ubReturn = 0;
if((CAN_HWOBJ[j].uwMSGCTR & 0x3000) == 0x1000) // if reset TXRQ
{
// CANPTRn(new) = CANPTR(old) & ~(uword)FSIZEn | (CANPTRn(old) + 1) & FZIZEn
aubFIFOWritePtr[ubObjNr / 2] = ((aubFIFOWritePtr[ubObjNr / 2] & ~(uword)(CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)) |
((aubFIFOWritePtr[ubObjNr / 2] + 1) & (CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)));
CAN_HWOBJ[j].uwMSGCTR = 0xf9ff; // set CPUUPD, reset NEWDAT
if(CAN_HWOBJ[j].uwMSGCFG & 0x0004) // if extended identifier
{
CAN_HWOBJ[j].ulCANAR = pstObj->ulID ;
}
else // if standard identifier
{
CAN_HWOBJ[j].ulCANAR = pstObj->ulID << 18;
}
CAN_HWOBJ[j].uwMSGCFG = (CAN_HWOBJ[j].uwMSGCFG & 0x000f) |
(pstObj->uwMsgCfg & 0x00f0); // set DLC
for(i = 0; i < (pstObj->uwMsgCfg & 0x00f0) >> 4; i++)
{
CAN_HWOBJ[j].ubData[i] = pstObj->ubData[i];
}
CAN_HWOBJ[j].uwMSGCTR = 0x66bf; // set TXRQ, NEWDAT, MSGVAL
// reset CPUUPD, RMTPND
ubReturn = 1;
}
}
return(ubReturn);
}
ubyte CAN_ubReadFIFO(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
ubyte i,j;
ubyte ubReturn;
ubReturn = 2;
if((CAN_HWOBJ[ubObjNr].uwCANPTR & 0x0700) == 0x0200) // if FIFO base object
{
j = aubFIFOReadPtr[ubObjNr / 2];
ubReturn = 0;
if((CAN_HWOBJ[j].uwMSGCTR & 0x0300) == 0x0200) // if NEWDAT
{
CAN_HWOBJ[j].uwMSGCTR = 0xfdff; // clear NEWDAT
// CANPTRn(new) = CANPTR(old) & ~(uword)FSIZEn | (CANPTRn(old) + 1) & FZIZEn
aubFIFOReadPtr[ubObjNr / 2] = ((aubFIFOReadPtr[ubObjNr / 2] & ~(uword)(CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)) |
((aubFIFOReadPtr[ubObjNr / 2] + 1) & (CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)));
// check if the previous message was lost
if((CAN_HWOBJ[j].uwMSGCTR & 0x0c00) == 0x0800) // if set MSGLST
{
CAN_HWOBJ[j].uwMSGCTR = 0xf7ff; // reset MSGLST
return(3);
}
for(i = 0; i < (CAN_HWOBJ[j].uwMSGCFG & 0x00f0) >> 4; i++)
{
pstObj->ubData[i] = CAN_HWOBJ[j].ubData[i];
}
if(CAN_HWOBJ[j].uwMSGCFG & 0x04) // if extended identifier
{
pstObj->ulID = CAN_HWOBJ[j].ulCANAR;
}
else // if standard identifier
{
pstObj->ulID = CAN_HWOBJ[j].ulCANAR >> 18;
}
pstObj->uwMsgCfg = CAN_HWOBJ[j].uwMSGCFG;
// check if the message was corrupted
if((CAN_HWOBJ[j].uwMSGCTR & 0x0300) == 0x0200) // if NEWDAT
{
CAN_HWOBJ[j].uwMSGCTR = 0xfdff; // clear NEWDAT
return(4);
}
ubReturn = 1;
}
}
return(ubReturn);
}
ubyte CAN_ubFlushReadFIFO(ubyte ubObjNr)
{
ubyte j;
ubyte ubReturn;
ubReturn = 0;
if((CAN_HWOBJ[ubObjNr].uwCANPTR & 0x0700) == 0x0200) // if FIFO base object
{
aubFIFOReadPtr[ubObjNr / 2] = ubObjNr;
CAN_HWOBJ[ubObjNr].uwCANPTR = (CAN_HWOBJ[ubObjNr].uwCANPTR & ~(uword)0x001F) | ubObjNr;
for(j = ubObjNr; j < ubObjNr + (CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f); j++)
{
CAN_HWOBJ[j].uwMSGCTR = 0xf5ff; // reset MSGLST, NEWDAT
}
// make sure that no new frame was received
CAN_HWOBJ[ubObjNr].uwCANPTR = (CAN_HWOBJ[ubObjNr].uwCANPTR & ~(uword)0x001F) | ubObjNr;
CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf5ff; // reset MSGLST, NEWDAT
ubReturn = 1;
}
return(ubReturn);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -