MCP2515 驱动程序

前段时间接手一个项目一个CAN总线的扩展板,由于CAN口不够用故采用MCP2515扩展,驱动代码如下:


/*! \file MCP2515.h
    \brief API to control the Microchip MCP2515 CAN controller. This CAN
    controller use the SPI link. For that reason, SPI initiation and data
    control should custom by the user.

     \author Sy Sech VONG
             Fr��d��ric Nadeau
             FangZheng @2014.9.10
*/


#ifndef MCP2515_H_
#define MCP2515_H_

#define USE_INT_STAT            1   // use INT pin indicate recived data

//MCP2515 RX/TX buffers selection
#define MCP2515_RX_BUF_0        0
#define MCP2515_RX_BUF_1        1
#define MCP2515_TX_BUF_0        0
#define MCP2515_TX_BUF_1        1
#define MCP2515_TX_BUF_2        2


//MCP2515 SPI instructions
#define MCP2515_RESET                   0xC0
#define MCP2515_READ                    0x03
#define MCP2515_READ_BUF_RXB0SIDH       0x90    //read data from begin address of Standard ID (MSB) of RX buffer 0
#define MCP2515_READ_BUF_RXB0D0         0x92    //read data from begin address of data byte 0 of RX buffer 0
#define MCP2515_READ_BUF_RXB1SIDH       0x94    //...RX buffer 1
#define MCP2515_READ_BUF_RXB1D0         0x96    //...RX buffer 1
#define MCP2515_WRITE                   0x02
#define MCP2515_LOAD_BUF_TXB0SIDH       0x40    //load data from begin address of Standard ID (MSB) of TX buffer 0
#define MCP2515_LOAD_BUF_TXB0D0         0X41    //load data from begin address of data byte 0 of TX buffer 0
#define MCP2515_LOAD_BUF_TXB1SIDH       0x42    //...TX buffer 1
#define MCP2515_LOAD_BUF_TXB1D0         0X43    //...TX buffer 1
#define MCP2515_LOAD_BUF_TXB2SIDH       0x44    //...TX buffer 2
#define MCP2515_LOAD_BUF_TXB2D0         0X45    //...TX buffer 2
#define MCP2515_RTS_TXB0                0x81    //activate the RTS of TX buffer 0.
#define MCP2515_RTS_TXB1                0x82    //...TX buffer 1.
#define MCP2515_RTS_TXB2                0x84    //...TX buffer 2.
#define MCP2515_RTS_ALL                 0x87    //...TX buffer 0, 1 and 2.
#define MCP2515_READ_RXTX_STATUS        0xA0
#define MCP2515_RX_STATUS               0xB0
#define MCP2515_BIT_MODIFY              0x05


//MCP2515 control settings register address.
//All can be used with the Bit Modify command, except the CANSTAT register.
#define MCP2515_BFPCTRL         0x0C    //RXnBF pin control/status
#define MCP2515_TXRTSCTRL       0x0D    //TXnRTS pin control/status
#define MCP2515_CANSTAT         0x0E    //CAN status. any addr of MSB will give the same info???
#define MCP2515_CANCTRL         0x0F    //CAN control status. any addr of MSB will give the same info???
#define MCP2515_TEC             0x1C    //Transmit Error Counter
#define MCP2515_REC             0x1D    //Receive Error Counter
#define MCP2515_CNF3            0x28    //Phase segment 2
#define MCP2515_CNF2            0x29    //Propagation segment & Phase segment 1 & n sample setting
#define MCP2515_CNF1            0x2A    //Baud rate prescaler & Sync Jump Width
#define MCP2515_CANINTE         0x2B    //CAN interrupt enable
#define MCP2515_CANINTF         0x2C    //Interrupt flag
#define MCP2515_EFLG            0x2D    //Error flag
#define MCP2515_TXB0CTRL        0x30    //TX buffer 0 control
#define MCP2515_TXB1CTRL        0x40    //TX buffer 1 control
#define MCP2515_TXB2CTRL        0x50    //TX buffer 2 control
#define MCP2515_RXB0CTRL        0x60    //RX buffer 0 control
#define MCP2515_RXB1CTRL        0x70    //RX buffer 1 control


//MCP2515 relate to CAN settings/status register address.
//Only the most used are listed below. please see the datasheet MCP2515.pdf p61 for complete info.
#define MCP2515_RXF0SIDH        0x00    //RX standard ID (High bits) filter 0
#define MCP2515_RXF0SIDL        0x01    //RX standard ID (Low bits) filter 0
#define MCP2515_RXF0EID8        0x02    //RX Extended ID (High bits) filter 0 ->can be reached by bust read/write Standard ID then Ext. ID
#define MCP2515_RXF0EID0        0x03    //RX Extended ID (Low bits) filter 0
#define MCP2515_RXF1SIDH        0x04    //RX standard ID (High bits) filter 1
#define MCP2515_RXF1SIDL        0x05    //RX standard ID (Low bits) filter 1
#define MCP2515_RXF1EID8        0x06    //RX Extended ID (High bits) filter 1
#define MCP2515_RXF1EID0        0x07    //RX Extended ID (Low bits) filter 1
#define MCP2515_RXF2SIDH        0x08    //RX standard ID (High bits) filter 2
#define MCP2515_RXF2SIDL        0x09    //RX standard ID (Low bits) filter 2
#define MCP2515_RXF2EID8        0x0A    //RX Extended ID (High bits) filter 2
#define MCP2515_RXF2EID0        0x0B    //RX Extended ID (Low bits) filter 2
#define MCP2515_RXF3SIDH        0x10    //RX standard ID (High bits) filter 3
#define MCP2515_RXF3SIDL        0x11    //RX standard ID (Low bits) filter 3
#define MCP2515_RXF3EID8        0x12    //RX Extended ID (High bits) filter 3
#define MCP2515_RXF3EID0        0x13    //RX Extended ID (Low bits) filter 3
#define MCP2515_RXF4SIDH        0x14    //RX standard ID (High bits) filter 4
#define MCP2515_RXF4SIDL        0x15    //RX standard ID (Low bits) filter 4
#define MCP2515_RXF4EID8        0x16    //RX Extended ID (High bits) filter 4
#define MCP2515_RXF4EID0        0x17    //RX Extended ID (Low bits) filter 4
#define MCP2515_RXF5SIDH        0x18    //RX standard ID (High bits) filter 5
#define MCP2515_RXF5SIDL        0x19    //RX standard ID (Low bits) filter 5
#define MCP2515_RXF5EID8        0x1A    //RX Extended ID (High bits) filter 5
#define MCP2515_RXF5EID0        0x1B    //RX Extended ID (Low bits) filter 5
#define MCP2515_RXM0SIDH        0x20    //RX standard ID (High bits) mask filter 0
#define MCP2515_RXM0SIDL        0x21    //RX standard ID (Low bits) mask filter 0
#define MCP2515_RXM0EID8        0x22    //RX Extended ID (High bits) mask filter 0
#define MCP2515_RXM0EID0        0x23    //RX Extended ID (Low bits) mask filter 0
#define MCP2515_RXM1SIDH        0x24    //RX standard ID (High bits) mask filter 1
#define MCP2515_RXM1SIDL        0x25    //RX standard ID (Low bits) mask filter 1
#define MCP2515_RXM1EID8        0x26    //RX Extended ID (High bits) mask filter 1
#define MCP2515_RXM1EID0        0x27    //RX Extended ID (Low bits) mask filter 1
#define MCP2515_RXB0SIDH        0x61    //RX buffer 0 standard ID (High bits)
#define MCP2515_RXB0SIDL        0x62    //RX buffer 0 standard ID (Low bits)
#define MCP2515_RXB0EID8        0x63    //RX buffer 0 Extended ID (High bits) ->can be reached by bust read/write Standard ID then Ext. ID
#define MCP2515_RXB0EID0        0x64    //RX buffer 0 Extended ID (Low bits)
#define MCP2515_RXB0DLC         0x65    //RX buffer 0 DLC  ->can be reached by bust read/write Standard ID, Ext. ID then DLC
#define MCP2515_RXB0D0          0x66    //RX buffer 0 data byte0
#define MCP2515_RXB1SIDH        0x71    //RX buffer 1 standard ID (High bits)
#define MCP2515_RXB1SIDL        0x72    //RX buffer 1 standard ID (Low bits)
#define MCP2515_RXB1EID8        0x73    //RX buffer 1 Extended ID (High bits)
#define MCP2515_RXB1EID0        0x74    //RX buffer 1 Extended ID (Low bits)
#define MCP2515_RXB1DLC         0x75    //RX buffer 1 DLC
#define MCP2515_RXB1D0          0x76    //RX buffer 1 data byte0

#define MCP2515_TXB0SIDH        0x31    //TX buffer 0 standard ID (High bits)
#define MCP2515_TXB0SIDL        0x32    //TX buffer 0 standard ID (Low bits)
#define MCP2515_TXB0EID8        0x33    //TX buffer 0 Extended ID (High bits) ->can be reached by bust read/write Standard ID then Ext. ID
#define MCP2515_TXB0EID0        0x34    //TX buffer 0 Extended ID (Low bits)
#define MCP2515_TXB0DLC         0x35    //TX buffer 0 DLC  ->can be reached by bust read/write Standard ID, Ext. ID then DLC
#define MCP2515_TXB0D0          0x36    //TX buffer 0 data byte0
#define MCP2515_TXB1SIDH        0x41    //TX buffer 1 standard ID (High bits)
#define MCP2515_TXB1SIDL        0x42    //TX buffer 1 standard ID (Low bits)
#define MCP2515_TXB1EID8        0x43    //TX buffer 1 Extended ID (High bits)
#define MCP2515_TXB1EID0        0x44    //TX buffer 1 Extended ID (Low bits)
#define MCP2515_TXB1DLC         0x45    //TX buffer 1 DLC
#define MCP2515_TXB1D0          0x46    //TX buffer 1 data byte0
#define MCP2515_TXB2SIDH        0x51    //TX buffer 2 standard ID (High bits)
#define MCP2515_TXB2SIDL        0x52    //TX buffer 2 standard ID (Low bits)
#define MCP2515_TXB2EID8        0x53    //TX buffer 2 Extended ID (High bits)
#define MCP2515_TXB2EID0        0x54    //TX buffer 2 Extended ID (Low bits)
#define MCP2515_TXB2DLC         0x55    //TX buffer 2 DLC
#define MCP2515_TXB2D0          0x56    //TX buffer 2 data byte0


//MCP2515 limit values
#define MCP2515_MIN_TQ          0x07    //7 = Minimum TQ in 1 bit of CAN bus time
#define MCP2515_MAX_TQ          0x19    //25 = Maximum TQ in 1 bit of CAN bus time
#define MCP2515_MIN_BRP         0x00    //0 = Minimum baud rate prescaler clock
#define MCP2515_MAX_BRP         0x3F    //63 = Maximum baud rate prescaler clock
#define MCP2515_MAX_SJW         0x03    //4 = Maximum Synchronization Jump Width. 4-1 = 3 actually
#define MCP2515_MAX_BYTE_CANFRM 0x08//8 = Maximun bytes in a CAN frame


//MCP2515 register values: CANCTRL register
#define MCP2515_MODE_NORMAL     0x00
#define MCP2515_MODE_SLEEP      0x20
#define MCP2515_MODE_LOOPBACK   0x40
#define MCP2515_MODE_LISTENONLY 0x60
#define MCP2515_MODE_CONFIG     0x80
#define MCP2515_ABORT_TX        0x10
#define MCP2515_MODE_MASK       0xE0
#define MCP2515_MODE_ONESHOT    0x08
#define MCP2515_CLKOUT_ENABLE   0x04
#define MCP2515_CLKOUT_PS1      0x00    //Set CLK out prescaler to 1. Note: not the same as the CAN CLK prescaler.
#define MCP2515_CLKOUT_PS2      0x01    //... to 2
#define MCP2515_CLKOUT_PS4      0x02    //... to 4
#define MCP2515_CLKOUT_PS8      0x03    //... to 8


//MCP2515 CAN Status Register bits (CANSTAT 0xXE, ICOD)
#define MCP2515_CANSTAT_NO_INT   0x00
#define MCP2515_CANSTAT_ERR_INT  0x02
#define MCP2515_CANSTAT_WAK_INT  0x04 //Wake-up Interrupt
#define MCP2515_CANSTAT_TXB0_INT 0x06
#define MCP2515_CANSTAT_TXB1_INT 0x08
#define MCP2515_CANSTAT_TXB2_INT 0x0A
#define MCP2515_CANSTAT_RXB0_INT 0x0C
#define MCP2515_CANSTAT_RXB1_INT 0x0E

//MCP2515 CAN Interrupt Flag Define
#define MCP2515_CANINTF_MERRF   0x80
#define MCP2515_CANINTF_WAKIF   0x40
#define MCP2515_CANINTF_ERRIF   0x20
#define MCP2515_CANINTF_TX2IF   0x10
#define MCP2515_CANINTF_TX1IF   0x08
#define MCP2515_CANINTF_TX0IF   0x04
#define MCP2515_CANINTF_RX1IF   0x02
#define MCP2515_CANINTF_RX0IF   0x01

#define MCP2515_CANINT_MERR     0x80
#define MCP2515_CANINT_WAKI     0x40
#define MCP2515_CANINT_ERRI     0x20
#define MCP2515_CANINT_TX2I     0x10
#define MCP2515_CANINT_TX1I     0x08
#define MCP2515_CANINT_TX0I     0x04
#define MCP2515_CANINT_RX1I     0x02
#define MCP2515_CANINT_RX0I     0x01

// porting for F2808 edit by fz 
#define ASSERT(expr)   ((void)0) //assert function not use here, so ...
typedef unsigned long  uint32_t;
typedef unsigned int   uint8_t;
/*! \struct mcp2515_can_frame_s
 *  Structure of a CANbus frame.
 */
#if 0
typedef struct mcp2515_can_frame_s{
    uint32_t id;        /**< Standard or Extented ID*/
    uint8_t dlc;        /**< Data Length Code*/
    uint8_t data[8];    /**< Data*/
}mcp2515_can_frame_t;   /**< Typedef of #mcp2515_can_frame_s*/
#endif
// end


typedef struct canfd_frame mcp2515_can_frame_t;


typedef enum mcp2515_rx_e
{
        mcp2515_rx_0,
        mcp2515_rx_1
}mcp2515_rx_t;

typedef enum mcp2515_tx_e
{
        mcp2515_tx_0,
        mcp2515_tx_1,
        mcp2515_tx_2
}mcp2515_tx_t;

typedef enum mcp2515_op_mode_e
{
        mcp2515_op_mode_normal = 0,
        mcp2515_op_mode_sleep,
        mcp2515_op_mode_loopback,
        mcp2515_op_mode_listen,
        mcp2515_op_mode_config
}mcp2515_op_mode_t;

typedef enum mcp2515_rx_op_mode_e
{
        mcp2515_rx_op_mode_filter_any = 0,
        mcp2515_rx_op_mode_filter_standard,
        mcp2515_rx_op_mode_filter_extended,
        mcp2515_rx_op_mode_any
}mcp2515_rx_op_mode_t;

typedef enum mcp2515_rx_filter_mask_e
{
        mcp2515_rx_filter_mask_RXF0 = 0x00,
        mcp2515_rx_filter_mask_RXF1 = 0x04,
        mcp2515_rx_filter_mask_RXF2 = 0x08,
        mcp2515_rx_filter_mask_RXF3 = 0x10,
        mcp2515_rx_filter_mask_RXF4 = 0x14,
        mcp2515_rx_filter_mask_RXF5 = 0x18,
        mcp2515_rx_filter_mask_RXM0 = 0x20,
        mcp2515_rx_filter_mask_RXM1 = 0x24
}mcp2515_rx_filter_mask_t;

enum
{
        MCP2515_SPIA = 0,
        MCP2515_SPIB,
        MCP2515_SPIC,
        MCP2515_SPID,
        MCP2515_DBG   
};

extern void mcp2515_spi_port_init(void);
extern void mcp2515_chn_select(uint8_t chn);
extern int16 mcp2515_sendmsg(struct canfd_frame *cf);
extern int16 mcp2515_recvmsg(struct canfd_frame *cf);
extern Uint16 mcp2515_init(uint32_t canID, uint8_t ext);
extern void read(uint8_t regAddr, uint8_t *dataAddr);
extern void write(uint8_t regAddr, uint8_t data);

//extern void mcp2515_init_ext(uint32_t canID, uint32_t mask, uint8_t ext);
extern void mcp2515_init_ext(uint32_t canID1, uint32_t canID2, uint8_t ext);
extern int16 mcp2515_sendext(struct canfd_frame *cf);
extern int16 mcp2515_recvext(struct canfd_frame *cf);

#endif /*MCP2515_H_*/


/*! \file MCP2515.c
    \brief API for Microchip MCP2515 CAN controller.

    This CAN controller use the SPI link. For that reason, SPI initiation and data
    control should custom by the user.

     \author Sy Sech VONG
             Fr��d��ric Nadeau
             FangZheng @2014.9.20
 */


#include "global.h"

#define DEBUG_MCP 1

extern void mcp2515_spi_port_init(void);


//extern void mcp2515_spi_select(void);


//extern void mcp2515_spi_unselect(void);


//extern void mcp2515_spi_transfer(uint8_t dataOut, uint8_t *dataIn);


void mcp2515_reset(void);


void mcp2515_read_rx_buf(mcp2515_rx_t channel, mcp2515_can_frame_t *canData);


void mcp2515_load_tx_buf(uint8_t nBuf, mcp2515_can_frame_t *canData);


void mcp2515_rts(uint8_t nBuf);


void mcp2515_read_rxtx_status(uint8_t* canRxTxStatus);


void mcp2515_rx_status(uint8_t* canRxStatus);

void mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_t regAddr, uint32_t canID, uint8_t ext);

int mcp2515_get_int_flag(void);
void mcp2515_clear_interrupt(void);

void mcp2515_set_op_mode(mcp2515_op_mode_t mode);

void mcp2515_set_rx_op_mode(mcp2515_rx_t channel, mcp2515_rx_op_mode_t mode);

void mcp2515_enable_rx_int(mcp2515_rx_t channel);
void mcp2515_enable_tx_int(mcp2515_tx_t channel);

static void (*mcp2515_spi_select)(void);
static void (*mcp2515_spi_unselect)(void);
//static void (*mcp2515_spi_transfer)(uint8_t ubDataOut, uint8_t *pubDataIn);
static void (*mcp2515_spi_transfer)(uint8_t tdata, uint8_t *prdata);

void mcp2515_chn_select(uint8_t chn)
{
    switch(chn)
    {
        case MCP2515_SPIA:
            mcp2515_spi_select = spi_select_spia;
            mcp2515_spi_unselect = spi_unselect_spia;
            mcp2515_spi_transfer = spi_transfer_spia;
            break;
        case MCP2515_SPIB:
            mcp2515_spi_select = spi_select_spib;
            mcp2515_spi_unselect = spi_unselect_spib;
            mcp2515_spi_transfer = spi_transfer_spib;
            break; 
        case MCP2515_SPIC:
            mcp2515_spi_select = spi_select_spic;
            mcp2515_spi_unselect = spi_unselect_spic;
            mcp2515_spi_transfer = spi_transfer_spic;
            break;
        case MCP2515_SPID:
            mcp2515_spi_select = spi_select_spid;
            mcp2515_spi_unselect = spi_unselect_spid;
            mcp2515_spi_transfer = spi_transfer_spid;
            break;
        case MCP2515_DBG:
            mcp2515_spi_select = spi_select_spic;
            mcp2515_spi_unselect = spi_unselect_spic;
            mcp2515_spi_transfer = spi_dbg_transfer;
            break;   
        default :
            break;
    }
}



void mcp2515_spi_port_init(void)
{
    mcp2515_status_init();
    mcp2515_cs_init();
    mcp2515_en_init();
}

#if 0
void mcp2515_spi_select(void){}
void mcp2515_spi_unselect(void){}

void mcp2515_spi_transfer(uint8_t ubDataOut, uint8_t *pubDataIn)
{
    /*SPDR = ubDataOut;

    loop_until_bit_is_set(SPSR, SPIF);

    if (pubDataIn != (void*) 0)
    {
        *pubDataIn = SPDR;
    }
    else
    {
        uint8_t tmp;
        tmp = SPDR;
    }*/
}
#endif
static void id_read(uint32_t *canID)
{
    uint8_t dataIn;
    volatile uint32_t uwID = 0;

    mcp2515_spi_transfer(0, &dataIn);//read XXXnSIDH
    uwID = (((uint32_t)dataIn) << 21);
    mcp2515_spi_transfer(0, &dataIn);//read XXXnSIDL
    uwID |= ( ((uint32_t)(dataIn & 0xE0)) << 13);
    uwID |= ( ((uint32_t)(dataIn & 0x03)) << 16);

    if (dataIn & 0x08) //Ext. ID? (bit mask on bit3)
        uwID |= 0x80000000;

    mcp2515_spi_transfer(0, &dataIn);//read XXXnEID8
    uwID |= (((uint32_t)dataIn) << 8);
    mcp2515_spi_transfer(0, &dataIn);//read XXXnEID0
    uwID |= (uint32_t)dataIn;
    *canID = uwID;
}


static void id_write(uint32_t canID)
{
    uint8_t ubtempo = 0;

    mcp2515_spi_transfer((uint8_t) (canID >> 21), NULL);//send XXXnSIDH
    ubtempo = ( (uint8_t)(canID >> 13) ) & 0xE0;
    ubtempo |= ( (uint8_t)(canID >> 16) ) & 0x03;

    if (canID & 0x80000000)//Ext. ID?
        ubtempo |= 0x08;

    mcp2515_spi_transfer(ubtempo, NULL);//send XXXnSIDL
    mcp2515_spi_transfer((uint8_t) (canID >> 8), NULL);//Send XXXnEID8
    mcp2515_spi_transfer((uint8_t) canID, NULL);//Send XXXnEID0
}


void read(uint8_t regAddr, uint8_t *dataAddr)
{
    ASSERT(dataAddr != 0);

    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_READ, NULL);
    mcp2515_spi_transfer(regAddr, NULL);
    mcp2515_spi_transfer(0, dataAddr);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void write(uint8_t regAddr, uint8_t data)
{
    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_WRITE, NULL);
    mcp2515_spi_transfer(regAddr, NULL);
    mcp2515_spi_transfer(data, NULL);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

#if 0
static void write_bust(uint8_t regAddr, uint8_t *dataAddr, uint8_t size)
{
    uint8_t i;

    ASSERT(dataAddr != NULL);

    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_WRITE, NULL);
    mcp2515_spi_transfer(regAddr, NULL);

    for (i=0; i < size; i++)
        mcp2515_spi_transfer(dataAddr[i], NULL);

    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

static void read_bust(uint8_t regAddr, uint8_t *dataAddr, uint8_t size)
{
    uint8_t i;

    ASSERT((dataAddr != NULL) && (size != 0));

    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_READ, NULL);
    mcp2515_spi_transfer(regAddr, NULL);

    for (i=0; i <= size; i++)
        mcp2515_spi_transfer(0, dataAddr++);

    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}
#endif

static void bit_modify(uint8_t regAddr, uint8_t bitMask, uint8_t val)
{
    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_BIT_MODIFY, NULL);
    mcp2515_spi_transfer(regAddr, NULL);
    mcp2515_spi_transfer(bitMask, NULL);
    mcp2515_spi_transfer(val, NULL);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void mcp2515_reset(void)
{
    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_RESET, NULL);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void mcp2515_read_rx_buf(mcp2515_rx_t channel, mcp2515_can_frame_t *canData)
{
    uint8_t i;

    ASSERT(canData != NULL);

    mcp2515_spi_select();//Select the MCP2515 on the SPI bus

    switch (channel)
    {
        case mcp2515_rx_0:
            mcp2515_spi_transfer(MCP2515_READ_BUF_RXB0SIDH, NULL);
            break;
        case mcp2515_rx_1:
            mcp2515_spi_transfer(MCP2515_READ_BUF_RXB1SIDH, NULL);
            break;
        default:
            ASSERT(0);
            break;
    }
    id_read(&canData->id);

    // add by fz
    if(canData->id & 0x80000000UL)
    {
        canData->ext = 1;
        canData->id &= 0x1FFFFFFF;
    }
    else
    {
        canData->ext = 0;
        canData->id &= 0x1FFFFFFF;
        canData->id >>= 18;
    }

    mcp2515_spi_transfer(0, &canData->dlc);//read DLC
    canData->dlc &= 0x0F;
    for (i = 0; i < canData->dlc; i++)
    {
        mcp2515_spi_transfer(0, &canData->data[i]);
    }
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}


void mcp2515_load_tx_buf(uint8_t nBuf, mcp2515_can_frame_t *canData)
{
    uint8_t i;

    ASSERT(canData != NULL);

    switch (nBuf)
    {
    case MCP2515_TX_BUF_0:
        mcp2515_spi_select();//Select the MCP2515 on the SPI bus
        mcp2515_spi_transfer(MCP2515_LOAD_BUF_TXB0SIDH, NULL);
        break;
    case MCP2515_TX_BUF_1:
        mcp2515_spi_select();//Select the MCP2515 on the SPI bus
        mcp2515_spi_transfer(MCP2515_LOAD_BUF_TXB1SIDH, NULL);
        break;
    case MCP2515_TX_BUF_2:
        mcp2515_spi_select();//Select the MCP2515 on the SPI bus
        mcp2515_spi_transfer(MCP2515_LOAD_BUF_TXB2SIDH, NULL);
        break;
    default:
        ASSERT(0);
        //break;
    }

    // add by fz
    if(canData->ext)
    {
        canData->id |= 0x80000000UL;
    }
    else
    {
        canData->id &= ~0x80000000UL;
        canData->id <<= 18;
    }
        
    id_write(canData->id);
    mcp2515_spi_transfer(canData->dlc & 0x0F, NULL);
    for (i = 0; (i < canData->dlc) && (i < MCP2515_MAX_BYTE_CANFRM); i++)
    {
        mcp2515_spi_transfer(canData->data[i], NULL);
    }
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void mcp2515_rts(uint8_t nBuf)
{
    //uint8_t ubRetVal = SPI_OK;
    //uint8_t dataIn;

    mcp2515_spi_select();//Select the MCP2515 on the SPI bus

    switch (nBuf)
    {
    case MCP2515_TX_BUF_0:
        //mcp2515_spi_transfer(MCP2515_RTS_TXB0, &dataIn);
        mcp2515_spi_transfer(MCP2515_RTS_TXB0, NULL);
        break;
    case MCP2515_TX_BUF_1:
        //mcp2515_spi_transfer(MCP2515_RTS_TXB1, &dataIn);
        mcp2515_spi_transfer(MCP2515_RTS_TXB1, NULL);
        break;
    case MCP2515_TX_BUF_2:
        //mcp2515_spi_transfer(MCP2515_RTS_TXB2, &dataIn);
        mcp2515_spi_transfer(MCP2515_RTS_TXB2, NULL);
        break;
    default:
        ASSERT(0);
        //break;
    }
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void mcp2515_read_rxtx_status(uint8_t* canRxTxStatus)
{
    ASSERT(canRxTxStatus != NULL);

    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_READ_RXTX_STATUS, NULL);
    mcp2515_spi_transfer(0, canRxTxStatus);

    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void mcp2515_rx_status(uint8_t* canRxStatus)
{

    ASSERT(canRxStatus != NULL);

    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_RX_STATUS, NULL);
    mcp2515_spi_transfer(0, canRxStatus);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void mcp2515_clear_interrupt(void)
{
    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_WRITE, NULL);
    mcp2515_spi_transfer(MCP2515_CANINTF, NULL);
    mcp2515_spi_transfer(0, NULL);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

void mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_t regAddr, uint32_t canID, uint8_t ext)
{
    if(ext)
    {
        canID |= 0x80000000UL;
    }
    else
    {
        canID &= ~0x80000000UL;
        canID <<= 18;
    }
    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_WRITE, NULL);
    mcp2515_spi_transfer((uint8_t)regAddr, NULL);
    id_write(canID);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus
}

int mcp2515_get_int_flag(void)
{
    uint8_t value;
    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_READ, NULL);
    mcp2515_spi_transfer(MCP2515_CANINTF, NULL);
    mcp2515_spi_transfer(0, &value);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus

    return (int)value;
}

void mcp2515_set_op_mode(mcp2515_op_mode_t mode)
{
    bit_modify(MCP2515_CANCTRL, 0xE0, mode<<5);
}

void mcp2515_set_rx_op_mode(mcp2515_rx_t channel, mcp2515_rx_op_mode_t mode)
{
    switch(channel)
    {
        case mcp2515_rx_0:
            bit_modify(MCP2515_RXB0CTRL, 0x60, mode<<5);
            break;
        case mcp2515_rx_1:
            bit_modify(MCP2515_RXB1CTRL, 0x60, mode<<5);
            break;
        default:
            ASSERT(0);
            break;
    }
}

void mcp2515_enable_rx_int(mcp2515_rx_t channel)
{
    switch(channel)
    {
        case mcp2515_rx_0:
            bit_modify(MCP2515_CANINTE, 0x01, 0x01);
            break;
        case mcp2515_rx_1:
            bit_modify(MCP2515_CANINTE, 0x02, 0x02);
            break;
        default:
            ASSERT(0);
            break;
    }
}

void mcp2515_enable_tx_int(mcp2515_tx_t channel)
{
    switch(channel)
    {
        case mcp2515_tx_0:
            bit_modify(MCP2515_CANINTE, 0x04, 0x04);
            break;
        case mcp2515_tx_1:
            bit_modify(MCP2515_CANINTE, 0x08, 0x08);
            break;
        case mcp2515_tx_2:
            bit_modify(MCP2515_CANINTE, 0x10, 0x10);
            break;
        default:
            ASSERT(0);
            break;
    }
}
/* ---- Beispiel zum Einstellen des Bit Timings ----
 *	
 *	Fosc		= 16MHz
 *	BRP			= 1
 *	TQ 			= 2 * (BRP + 1) / Fosc
 *				= 1/4 uS
 *
 *	Sync Seg	= 					= 1 TQ
 *	Prop Seg	= (PRSEG + 1) * TQ	= 5 TQ
 *	Phase Seg1	= (PHSEG1 + 1) * TQ	= 6 TQ
 *	Phase Seg2	= (PHSEG2 + 1) * TQ = 4 TQ
 *									--------
 *									  16 TQ
 *	
 *	Bus speed	= 1 / ((Total # of TQ) * TQ)
 *				= 1 / (4 * TQ) = 250 kHz
 // 250 kbps
	{	0x03, // CNF3
		0xac, // CNF2
		0x81  // CNF1
	},
	// 500 kbps
	{	0x03,
		0xac,
		0x80
	},
 */
int mcp2515_set_baudrate(uint8_t bdr)
{
    Uint16 tmp = 0xFF; 
    #if 0
    static uint8_t prs, phs1, phs2, BRP, sjw;
    
    if(bdr == CAN_BAUD_250K)
    {
        BRP = 1;
        prs = 4;
        phs1 = 5;
        phs2 = 3;
        sjw = 2;
    }
    else
    {

        BRP = 0;
        prs = 4;
        phs1 = 5;
        phs2 = 3;
        sjw = 2;
    }

    //SET ALL THE REGISTER OF THE MCP 2515 FOR THE DESIRED BAUD RATE
    mcp2515_spi_select();//Select the MCP2515 on the SPI bus
    mcp2515_spi_transfer(MCP2515_WRITE, NULL);
    mcp2515_spi_transfer(MCP2515_CNF3, NULL);
    mcp2515_spi_transfer(phs2, NULL);//CF3
    mcp2515_spi_transfer(prs|(phs1<<3)|0x80, NULL);//CF2
    //CF1 : 1TQ for SJW and BRP = 5 for 1TQ = 12/F_CPU
    mcp2515_spi_transfer((sjw<<6)|BRP, NULL);
    mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus

    #else
    write(MCP2515_CNF1, 0x81);
    write(MCP2515_CNF2, 0xAC);
    write(MCP2515_CNF3, 0x03);

    read(MCP2515_CNF1, &tmp);
    if(tmp != 0x81)
    {
        return 1; // err!
    }
    #endif

    return 0;
}

int16 mcp2515_sendmsg(struct canfd_frame *cf)
{
    cf->id = 0x1807E5F4;
    cf->ext = 1;
    mcp2515_load_tx_buf(MCP2515_TX_BUF_0, cf);
    mcp2515_rts(MCP2515_TX_BUF_0);

    return SUCCESS;
}

int16 mcp2515_recvmsg(struct canfd_frame *cf)
{
    Uint16 status;

#if USE_INT_STAT
    if(mcp2515_spi_transfer == spi_transfer_spia)
    {
        if(mcpa_int_stat())
            return FAILURE;
    }
    else if(mcp2515_spi_transfer == spi_transfer_spib)
    {
        if(mcpb_int_stat())
            return FAILURE;
    }
    else if(mcp2515_spi_transfer == spi_transfer_spic)
    {
        if(mcpc_int_stat())
            return FAILURE;
    }
    else if(mcp2515_spi_transfer == spi_transfer_spid)
    {
        if(mcpd_int_stat())
            return FAILURE;
    }
    else
    {
        if(mcpc_int_stat())
            return FAILURE;
    }
    
#else
    mcp2515_read_rxtx_status(&status);
    if((status&0x01) != 0x01) 
        return FAILURE;
        
#endif
    mcp2515_read_rx_buf(mcp2515_rx_0, cf);

    return SUCCESS;  
}
/*
int16 send_data_spia(struct canfd_frame *cf, Uint16 noblock)
{
    mcp2515_chn_select(MCP2515_SPIA);
    return mcp2515_sendmsg(cf);
}

int16 recv_data_spia(struct canfd_frame *cf, Uint16 noblock)
{
    mcp2515_chn_select(MCP2515_SPIA);
    return mcp2515_recvmsg(cf);
}
*/
Uint16 mcp2515_init(uint32_t canID, uint8_t ext)
{
    Uint16 err = 0;
    //mcp2515_spi_port_init();
    mcp2515_reset();
    DELAY_US(1000); // 1ms

    write(MCP2515_CANCTRL, 0);
    mcp2515_set_op_mode(mcp2515_op_mode_config);
    write(MCP2515_TXRTSCTRL, 0); // disable TXnRTS
    write(MCP2515_BFPCTRL, 0);   // disable RxnBF
    
    
#if USE_INT_STAT
    write(MCP2515_CANINTE, MCP2515_CANINT_RX0I); // RX0 interrupt enable
#else
    write(MCP2515_CANINTE, 0);
#endif

    write(MCP2515_RXB0CTRL, 0x60); // receive any message, Rollover disavle
    //mcp2515_set_rx_op_mode(mcp2515_rx_0, mcp2515_rx_op_mode_any);
    err = mcp2515_set_baudrate(CAN_BAUD_RATE);
    bit_modify(MCP2515_CANCTRL, 0x08, 1<<3); // one shot mode

    mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXM0, 0x1FFFFFFF, ext);
    //mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXM1, 0x1FFFFFFF, 0);

    //mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXM0, 0x00000000, 0);
    //mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXM1, 0x00000000, 0);

    mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXF0, canID, ext);
    mcp2515_set_rx_op_mode(mcp2515_rx_0, mcp2515_rx_op_mode_filter_any);

    //mcp2515_set_rx_op_mode(mcp2515_rx_1, mcp2515_rx_op_mode_filter_any);
    //write(MCP2515_RXB0CTRL, 0);

    
    mcp2515_set_op_mode(mcp2515_op_mode_normal); 

    return err;
}

/*
void mcp2515_init_ext(uint32_t canID, uint32_t mask, uint8_t ext)
{
    mcp2515_set_op_mode(mcp2515_op_mode_config);
    write(MCP2515_RXB1CTRL, 0x62); // receive any message, Rollover disavle

    mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXM1, mask, ext);

    mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXF2, canID, ext);

    mcp2515_set_rx_op_mode(mcp2515_rx_1, mcp2515_rx_op_mode_filter_any);

    
    mcp2515_set_op_mode(mcp2515_op_mode_normal); 
}
*/
void mcp2515_init_ext(uint32_t canID1, uint32_t canID2, uint8_t ext)
{
    uint32_t mask = ~(canID1 ^ canID2) & 0x1FFFFFFF;
    //uint32_t mask = 0x00;
    
    mcp2515_set_op_mode(mcp2515_op_mode_config);
    write(MCP2515_RXB1CTRL, 0x62); // receive any message, Rollover disavle

    mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXM1, mask, ext);

    mcp2515_set_rx_filter_mask(mcp2515_rx_filter_mask_RXF2, canID1, ext);

    //mcp2515_set_rx_op_mode(mcp2515_rx_1, mcp2515_rx_op_mode_filter_any);
    mcp2515_set_rx_op_mode(mcp2515_rx_1, mcp2515_rx_op_mode_any);

    
    mcp2515_set_op_mode(mcp2515_op_mode_normal); 
}

int16 mcp2515_sendext(struct canfd_frame *cf)
{

    mcp2515_load_tx_buf(MCP2515_TX_BUF_1, cf);
    mcp2515_rts(MCP2515_TX_BUF_1);

    return SUCCESS;
}

int16 mcp2515_recvext(struct canfd_frame *cf)
{
    Uint16 status;

    mcp2515_read_rxtx_status(&status);
    if((status&0x02) != 0x02) 
        return FAILURE;
        
    mcp2515_read_rx_buf(mcp2515_rx_1, cf);

    return SUCCESS;  
}



void spi_transfer_spia(Uint16 tdata, Uint16 *prdata)
{

    spi_transfer_chn(tdata, prdata, &SpiaRegs);
}
void spi_transfer_chn(Uint16 tdata, Uint16 *prdata, volatile struct SPI_REGS *pREGS)
{
    Uint16 tx = DUMMY_BYTE, rx = DUMMY_BYTE;
    
    if(prdata == NULL) tx = tdata;
    
    pREGS->SPITXBUF = tx << 8; // dummy write
    
    while(pREGS->SPISTS.bit.INT_FLAG != 1);
    // Check against sent data
    rx = pREGS->SPIRXBUF; // right-justified

    if(prdata != NULL) *prdata = rx;
}



给大家提供一个思路,在遇到相同的问题是可以减少码农的工作负担~~

你可能感兴趣的:(DSP)