MCP2515 驱动程序
前段时间接手一个项目一个CAN总线的扩展板,由于CAN口不够用故采用MCP2515扩展,驱动代码如下:
/*! \file MCP2515.h\brief API to control the Microchip MCP2515 CAN controller. This CANcontroller use the SPI link. For that reason, SPI initiation and datacontrol should custom by the user.\author Sy Sech VONGFr��d��ric NadeauFangZheng @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
// endtypedef 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 datacontrol should custom by the user.\author Sy Sech VONGFr��d��ric NadeauFangZheng @2014.9.20*/#include "global.h"#define DEBUG_MCP 1extern 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 XXXnSIDHuwID = (((uint32_t)dataIn) << 21);mcp2515_spi_transfer(0, &dataIn);//read XXXnSIDLuwID |= ( ((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 XXXnEID8uwID |= (((uint32_t)dataIn) << 8);mcp2515_spi_transfer(0, &dataIn);//read XXXnEID0uwID |= (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 XXXnSIDHubtempo = ( (uint8_t)(canID >> 13) ) & 0xE0;ubtempo |= ( (uint8_t)(canID >> 16) ) & 0x03;if (canID & 0x80000000)//Ext. ID?ubtempo |= 0x08;mcp2515_spi_transfer(ubtempo, NULL);//send XXXnSIDLmcp2515_spi_transfer((uint8_t) (canID >> 8), NULL);//Send XXXnEID8mcp2515_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 busmcp2515_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 busmcp2515_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 busmcp2515_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 busmcp2515_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
}
#endifstatic void bit_modify(uint8_t regAddr, uint8_t bitMask, uint8_t val)
{mcp2515_spi_select();//Select the MCP2515 on the SPI busmcp2515_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 busmcp2515_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 busswitch (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 fzif(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 DLCcanData->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 busmcp2515_spi_transfer(MCP2515_LOAD_BUF_TXB0SIDH, NULL);break;case MCP2515_TX_BUF_1:mcp2515_spi_select();//Select the MCP2515 on the SPI busmcp2515_spi_transfer(MCP2515_LOAD_BUF_TXB1SIDH, NULL);break;case MCP2515_TX_BUF_2:mcp2515_spi_select();//Select the MCP2515 on the SPI busmcp2515_spi_transfer(MCP2515_LOAD_BUF_TXB2SIDH, NULL);break;default:ASSERT(0);//break;}// add by fzif(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 busswitch (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 busmcp2515_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 busmcp2515_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 busmcp2515_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 busmcp2515_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 busmcp2515_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 busreturn (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, // CNF30xac, // CNF20x81 // CNF1},// 500 kbps{ 0x03,0xac,0x80},*/
int mcp2515_set_baudrate(uint8_t bdr)
{Uint16 tmp = 0xFF; #if 0static 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 RATEmcp2515_spi_select();//Select the MCP2515 on the SPI busmcp2515_spi_transfer(MCP2515_WRITE, NULL);mcp2515_spi_transfer(MCP2515_CNF3, NULL);mcp2515_spi_transfer(phs2, NULL);//CF3mcp2515_spi_transfer(prs|(phs1<<3)|0x80, NULL);//CF2//CF1 : 1TQ for SJW and BRP = 5 for 1TQ = 12/F_CPUmcp2515_spi_transfer((sjw<<6)|BRP, NULL);mcp2515_spi_unselect();//Unselect the MCP2515 on the SPI bus#elsewrite(MCP2515_CNF1, 0x81);write(MCP2515_CNF2, 0xAC);write(MCP2515_CNF3, 0x03);read(MCP2515_CNF1, &tmp);if(tmp != 0x81){return 1; // err!}#endifreturn 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_STATif(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;}#elsemcp2515_read_rxtx_status(&status);if((status&0x01) != 0x01) return FAILURE;#endifmcp2515_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); // 1mswrite(MCP2515_CANCTRL, 0);mcp2515_set_op_mode(mcp2515_op_mode_config);write(MCP2515_TXRTSCTRL, 0); // disable TXnRTSwrite(MCP2515_BFPCTRL, 0); // disable RxnBF#if USE_INT_STATwrite(MCP2515_CANINTE, MCP2515_CANINT_RX0I); // RX0 interrupt enable
#elsewrite(MCP2515_CANINTE, 0);
#endifwrite(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 modemcp2515_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 disavlemcp2515_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 disavlemcp2515_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 writewhile(pREGS->SPISTS.bit.INT_FLAG != 1);// Check against sent datarx = pREGS->SPIRXBUF; // right-justifiedif(prdata != NULL) *prdata = rx;
}
给大家提供一个思路,在遇到相同的问题是可以减少码农的工作负担~~
MCP2515 驱动程序相关推荐
- MCP2515驱动程序
下载链接https://download.csdn.net/download/y1757655788/13197815 STM32芯片内部已有1个或2个CAN控制器,但是在有些情况下两个CAN控制 ...
- SPI转can芯片mcp2515
开发环境 CPU:RK3399 ARCH: aarch64 KERNEL:Linux4.4 OS:ubuntu18.04 mcp2515芯片相关信息 CAN.SPI接口控制电路图 修改设备树文件 文件 ...
- atlas 200移植mcp2515
mcp2515是spi接入的模块 淘宝买的can小板子,直接通过spi飞线到atlas 200的单板 1.首先需要配置spi复用 2.配置内核 3.配置设备树 调试问题: 第一个问题 重新编译dtb文 ...
- Android评分栏示例
在Android中,您可以使用" android.widget.RatingBar "以星号图标显示评分栏组件. 用户可以触摸,拖动或单击星号以轻松设置评级值. 在本教程中,我们向 ...
- Spi cp2515 linux,基于MCP2515的Linux CAN总线驱动程序设计
图3 MCP2515硬件连接图 5.MCP2515 Socket CAN驱动实现 FS2416平台使用Linux2.6.39的内核,内核中为MCP2515提供了Socket CAN驱动程序,我们只需为 ...
- OpenGL在图形管道中调用了什么用户模式图形驱动程序(UMD)?
OpenGL在图形管道中调用了什么用户模式图形驱动程序(UMD)? 图形硬件供应商,需要为显示适配器编,编写用户模式显示驱动程序.用户模式显示驱动程序,是由Microsoft Direct3D运行时加 ...
- 嵌入式Linux设备驱动程序:在运行时读取驱动程序状态
嵌入式Linux设备驱动程序:在运行时读取驱动程序状态 Embedded Linux device drivers: Reading driver state at runtime 在运行时了解驱动程 ...
- 嵌入式Linux设备驱动程序:用户空间中的设备驱动程序
嵌入式Linux设备驱动程序:用户空间中的设备驱动程序 Embedded Linux device drivers: Device drivers in user space Interfacing ...
- 嵌入式Linux设备驱动程序:发现硬件配置
嵌入式Linux设备驱动程序:发现硬件配置 Embedded Linux device drivers: Discovering the hardware configuration Interfac ...
最新文章
- python中execute函数_Python 中的内置函数与模块
- android 命令启动服务,adb 命令
- 用python函数画德国国旗代码_python海龟绘图之画国旗实例代码
- mac笔记本怎么外接显示屏_苹果MAC笔记本怎么外接显示器?
- 专家预测第二波WannaCry勒索病毒攻击即将到来!
- linux 下使用 curl post
- sap相关性不能被编译_经典综述编译丨生物硝化抑制丨NAT PLANTS:现代农业中的氮转化和生物硝化抑制作用...
- 【开源GPS追踪】 之 服务器端opengts安装
- JavaScript数组的某些操作(一)
- 信创只是开始_一切只是开始!谁是下一个“第一创业”?
- SQLServer2008R2密钥
- python职场应用英语作文_春考关于职场应用的英语作文
- WinDbg实践--入门篇
- 前端三剑客 HTML、CSS、JavaScript 入门到上手
- Invalid Java package name: '1' is not a valid Java identifier eclipse创建sevlet时,无法创建
- 常见点击反应(Click Reactions)及其试剂——CuAAC
- java将汉字转成拼音首字母大写字母_Java 将汉字转换为拼音并取首字母大写
- VS2008上安装64位编译器工具
- 反向恢复时间trr的影响
- 分享武汉大学李征航老师的《GPS原理与应用》
热门文章
- 解决66版本后Chrome浏览器无法安装插件的问题
- Vivado中FFT9.1 IP核的使用(1)
- C语言头文件和源文件差异,#include两种引用方式差异
- 详解:IP地址132.119.100.200的子网掩码是255.255.255.240,那么它所在子网的广播地址是(132.119.100.207)
- 计算机电子电路原理图,电子电路图 如何看懂电子电路图 凡亿教你如何看懂电路图...
- 全国计算机等级考试三级数据库技术-知识点汇总
- SRTP RFC 3711
- 不容错过 产品发布ppt模板素材推荐
- 百度百科词条创建技巧及经验之谈,如何顺利创建百科
- 一顿饭的事儿,搞懂了Linux5种IO模型