⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can18xx8.c

📁 一个CAN学习程序
💻 C
📖 第 1 页 / 共 2 页
字号:
 *
 * 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 + -