前段时间接手一个项目一个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;
}