📄 can18xx8.c
字号:
*
* Output: CAN registers starting at given address are bit
* adjusted and copied into 'val'
*
* Side Effects: None
*
* Overview: If given id is of type standard identifier,
* only SIDH and SIDL are used
* If given id is of type extended identifier,
* bits EIDH, EIDL and SIDL<1:0> is copied to val<17:0>
* bits SIDH and SIDL is copied to val<28:18>
*
********************************************************************/
static void RegsToCANID(BYTE* ptr,
unsigned long *val,
enum CAN_CONFIG_FLAGS type)
{
CAN_MESSAGE_ID *Value;
Value = (CAN_MESSAGE_ID*)val;
if ( type & CAN_CONFIG_MSG_TYPE_BIT )
{
// Standard Identifier
Value->BYTES.BYTE_1 = (*ptr << 3); // Copy SIDH<4:0> to SID<7:3>
Value->BYTES.BYTE_2 = *ptr >> 5; // Copy SIDH<7:5> to SID<10:8>
ptr++; // Point to SIDL
Value->BYTES.BYTE_1 |= (*ptr >> 5); // Copy SIDL<7:6> to SID<2:0>
Value->BYTES.BYTE_3 = 0x00;
Value->BYTES.BYTE_4 = 0x00;
}
else
{
// Extended Identifier
Value->BYTES.BYTE_3 = (*ptr << 5); // Copy SIDH<2:0> to EID<23:21>
Value->BYTES.BYTE_4 = (*ptr >> 3); // Copy SIDH<7:3> to EID<29:25>
ptr++; // Point to SIDL
Value->BYTES.BYTE_3 |= (*ptr & 0x03); // Copy SIDH<1:0> to EID<17:16>
// Bug-Fix NKR 11/20/00
Value->BYTES.BYTE_3 |= ((*ptr & 0xe0) >> 3); // Copy SIDL<7:6> to EID<20:18>
ptr++; // Point to EIDH
Value->BYTES.BYTE_2 = *ptr; // Copy EIDH<15:8> to EID<15:8>
ptr++; // Point to EIDL
Value->BYTES.BYTE_1 = *ptr; // Copy EIDH<7:0> to EID<7:0>
}
}
/*********************************************************************
* Function: void CANSetMask(enum CAN_MASK code,
* unsigned long val,
* enum CAN_CONFIG_FLAGS type)
*
* PreCondition: MCU must be in Configuration mode. If not, all
* values will be ignored.
*
* Input: code - One of CAN_MASK value
* val - Actual mask register value.
* type - Type of message to filter either
* CAN_CONFIG_XTD_MSG or CAN_CONFIG_STD_MSG
*
* Output: Given value is bit adjusted to appropriate buffer
* mask registers.
*
* Side Effects: None
*
********************************************************************/
void CANSetMask(enum CAN_MASK code,
unsigned long val,
enum CAN_CONFIG_FLAGS type)
{
BYTE *ptr;
// Select appropriate starting address based on given CAN_MASK
// value.
if ( code == CAN_MASK_B1 )
ptr = (BYTE*)&RXM0SIDH;
else
ptr = (BYTE*)&RXM1SIDH;
// Convert given 32-bit id value into corresponding register values.
CANIDToRegs(ptr, val, type);
}
//////////////////////////////////////////////////////////////////////
/*********************************************************************
* Function: void CANSetFilter(enum CAN_FILTER code,
* unsigned long val,
* enum CAN_CONFIG type)
*
* PreCondition: MCU must be in Configuration mode. If not, all
* values will be ignored.
*
*
Input: code - One of CAN_FILTER value
* val - Actual filter register value.
* type - Type of message to filter either
* CAN_CONFIG_XTD_MSG or CAN_CONFIG_STD_MSG
*
* Output: Given value is bit adjusted to appropriate buffer
* filter registers.
*
* Side Effects: None
********************************************************************/
void CANSetFilter(enum CAN_FILTER code,
unsigned long val,
enum CAN_CONFIG_FLAGS type)
{
BYTE *ptr;
// Select appropriate starting address based on given CAN_FILTER
// code.
switch(code)
{
case CAN_FILTER_B1_F1:
ptr = (BYTE*)&RXF0SIDH;
break;
case CAN_FILTER_B1_F2:
ptr = (BYTE*)&RXF1SIDH;
break;
case CAN_FILTER_B2_F1:
ptr = (BYTE*)&RXF2SIDH;
break;
case CAN_FILTER_B2_F2:
ptr = (BYTE*)&RXF3SIDH;
break;
case CAN_FILTER_B2_F3:
ptr = (BYTE*)&RXF4SIDH;
break;
default:
ptr = (BYTE*)&RXF5SIDH;
break;
}
// Convert 32-bit value into register values.
CANIDToRegs(ptr, val, type);
}
//////////////////////////////////////////////////////////////////////
/*********************************************************************
* Function: BOOL CANSendMessage(unsigned long id,
* BYTE *Data,
* BYTE DataLen,
* enum CAN_TX_MSG_FLAGS MsgFlags)
*
* PreCondition: None
*
* Input: id - CAN message identifier.
* Only 11 or 29 bits may be used
* depending on standard or extended
* message type.
* Data - Data bytes of upto 8 bytes in length
* DataLen - Data length from 1 thru 8.
* MsgFlags - One or CAN_TX_MSG_FLAGS values ANDed
* together
*
* Output: If at least one empty transmit buffer is found,
* given message is queued to be transmitted. If none
* found FALSE value is returned.
*
* Side Effects: None
*
********************************************************************/
BOOL CANSendMessage(unsigned long id,
BYTE* Data,
BYTE DataLen,
enum CAN_TX_MSG_FLAGS MsgFlags)
{
BYTE i;
BYTE *ptr;
// Find the first empty transmitter.
if ( TXB0CON_TXREQ == 0 )
{
// TxBuffer0 is empty. Set WIN bits to point to TXB0
CANCON &= 0b11110001;
CANCON |= 0b00001000;
}
else if ( TXB1CON_TXREQ == 0 )
{
// TxBuffer1 is empty. Set WIN bits to point to TXB1
CANCON &= 0b11110001;
CANCON |= 0b00000110;
}
else if ( TXB2CON_TXREQ == 0 )
{
// TxBuffer2 is empty. Set WIN bits to point to TXB2
CANCON &= 0b11110001;
CANCON |= 0b00000100;
}
else
// None of the transmit buffers were empty.
return FALSE;
/*
* Now that WIN has remapped RXB0 to empty buffer, simply
* populate RXB0 buffer
*/
// Set transmit priority.
RXB0CON = MsgFlags & CAN_TX_PRIORITY_BITS;
// Populate Extended identifier information only if it is
// desired.
if ( !(MsgFlags & CAN_TX_FRAME_BIT) )
CANIDToRegs((BYTE*)&RXB0SIDH, id, CAN_CONFIG_XTD_MSG);
else
CANIDToRegs((BYTE*)&RXB0SIDH, id, CAN_CONFIG_STD_MSG);
RXB0DLC = DataLen;
if ( !(MsgFlags & CAN_TX_RTR_BIT) )
RXB0DLC |= 0b01000000;
// Populate data values.
ptr = (BYTE*)&RXB0D0;
for ( i = 0; i < DataLen; i++ )
ptr[i] = Data[i];
/*
* Mark this buffer as ready to start transmit.
* We are not using C bit field structure because RXB0 registers
* are remapped to one of the empty transmit buffers and their
* bit3 is not same as RXB0CON bit3. To avoid confusion, in-line
* assembly is used to directly set bit 3 of corresponding TXBnCON
* register.
*/
#if defined(MCHP_C18)
_asm
bsf RXB0CON, 3, 0
_endasm
#endif
#if defined(HITECH_C18)
asm("bsf _RXB0CON,3");
#endif
/*
* Restore CAN buffer mapping so that subsequent access to RXB0
* buffers are to the real RXB0 buffer.
*/
CANCON &= 0b11110001;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
/*********************************************************************
* Function: BOOL CANReceiveMessage(unsigned long *id,
* BYTE *Data,
* BYTE DataLen,
* enum CAN_RX_MSG_FLAGS MsgFlags)
*
* PreCondition: None
*
* Input: None
*
* Output: id - CAN message identifier.
* Data - Data bytes of upto 8 bytes in length
* DataLen - Data length from 1 thru 8.
* MsgFlags - One or CAN_RX_MSG_FLAGS values ANDed
* together
*
* Output: If at least one full receive buffer is found,
* it is extrated and returned.
* If none found FALSE value is returned.
*
* Side Effects: None
*
********************************************************************/
BOOL CANReceiveMessage(unsigned long *id,
BYTE *Data,
BYTE *DataLen,
enum CAN_RX_MSG_FLAGS *MsgFlags)
{
BYTE i;
BYTE *ptr;
BOOL lbIsItBuffer0;
// Start with no error or flags set.
*MsgFlags = 0x0;
// Find which buffer is ready.
if ( RXB0CON_RXFUL )
{
// RXBuffer0 is full.
CANCON &= 0b11110001;
lbIsItBuffer0 = TRUE;
// Clear the received flag.
PIR3_RXB0IF = 0;
// Record and forget any previous overflow
if ( COMSTAT_RX0OVFL )
{
*MsgFlags |= CAN_RX_OVERFLOW;
COMSTAT_RX0OVFL = 0;
}
if ( RXB0CON_RX0DBEN )
{
*MsgFlags |= RXB0CON & CAN_RX_FILTER_BITS;
*MsgFlags &= 0x01;
}
}
else if ( RXB1CON_RXFUL )
{
// RXBuffer1 is full
CANCON &= 0b11110001;
CANCON |= 0b00001010;
lbIsItBuffer0 = FALSE;
// Clear the received flag.
PIR3_RXB1IF = 0;
// Record and forget any previous overflow
if ( COMSTAT_RX1OVFL )
{
*MsgFlags |= CAN_RX_OVERFLOW;
COMSTAT_RX1OVFL = 0;
}
*MsgFlags |= RXB1CON & CAN_RX_FILTER_BITS;
if ( *MsgFlags < 0x02 )
*MsgFlags |= CAN_RX_DBL_BUFFERED;
}
else
return FALSE;
// Retrieve message length.
*DataLen = RXB0DLC & 0b00001111;
// Determine whether this was RTR or not.
if ( RXB0DLC_RTR )
*MsgFlags |= CAN_RX_RTR_FRAME;
// Retrieve EIDX bytes only if this is extended message
if ( RXB0SIDL_EXID )
{
*MsgFlags |= CAN_RX_XTD_FRAME;
RegsToCANID((BYTE*)&RXB0SIDH, id, CAN_CONFIG_XTD_MSG);
}
else
RegsToCANID((BYTE*)&RXB0SIDH, id, CAN_CONFIG_STD_MSG);
// Get message data itself
ptr = (BYTE*)&RXB0D0;
for ( i = 0; i < *DataLen; i++ )
Data[i] = ptr[i];
// Restore default RXB0 mapping.
CANCON &= 0b11110001;
// Record and Clear any previous invalid message bit flag.
if ( PIR3_IRXIF )
{
*MsgFlags |= CAN_RX_INVALID_MSG;
PIR3_IRXIF = 0;
}
if ( lbIsItBuffer0 )
RXB0CON_RXFUL = 0;
else
RXB1CON_RXFUL = 0;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -