📄 can-mcp2510.c
字号:
/////////////////////////////////////////////////////////////////////////
//// can-mcp2510.c ////
//// CAN Library routines for Microchip's MCP2510 (and compatable) ////
//// CAN IO expanders. ////
//// ////
//// This library provides the following functions: ////
//// (for more information on these functions see the comment ////
//// header above each function) ////
//// ////
//// can_init - Configures the MCP2510 CAN peripheral ////
//// ////
//// can_set_baud - Sets the baud rate control registers ////
//// ////
//// can_set_mode - Sets the CAN module into a specific mode ////
//// ////
//// can_set_id - Sets the standard and extended ID ////
//// ////
//// can_get_id - Gets the standard and extended ID ////
//// ////
//// can_putd - Sends a message/request with specified ID ////
//// ////
//// can_getd - Returns specifid message/request and ID ////
//// ////
//// can_kbhit - Returns true if there is data in one of the ////
//// receive buffers ////
//// ////
//// can_tbe - Returns true if the transmit buffer is ready to ////
//// send more data ////
//// ////
//// can_abort - Aborts all pending transmissions ////
//// ////
//// You will need a CAN transeiver to connect CANRX and CANTX ////
//// pins to CANH and CANL bus lines. ////
//// ////
//// CCS provides an example, ex_can_ccs_b.c, which shows how to use ////
//// this library with CCS's CAN Prototype board. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// Version History ////
//// ////
//// Feb 24 04 - can_get_id() fixed for EID<18:20> ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
#include <can-mcp2510.h>
//IO pins connected to MCP2510
#ifndef EXT_CAN_CS
#define EXT_CAN_CS PIN_B1
#define EXT_CAN_SI PIN_C1
#define EXT_CAN_SO PIN_C0
#define EXT_CAN_SCK PIN_C3
// #define EXT_CAN_RESET PIN_B5 //CCS library does not use this pin by default
// #define EXT_CAN_TX0RTS PIN_C4 //CCS library does not use this pin by default
// #define EXT_CAN_TX1RTS PIN_B4 //CCS library does not use this pin by default
// #define EXT_CAN_TX2RTS PIN_C2 //CCS library does not use this pin by default
#endif
#if CAN_DO_DEBUG
#define can_debug printf
#else
#define can_debug
#endif
////////////////////////////////////////////////////////////////////////
//
// can_init()
//
// Initializes MCP2510 CAN peripheral. Sets the RX filter and masks so the
// CAN peripheral will receive all incoming IDs. Configures both RX buffers
// to only accept valid valid messages (as opposed to all messages, or all
// extended message, or all standard messages).
//
// The constants (CAN_USE_RX_DOUBLE_BUFFER, CAN_ENABLE_DRIVE_HIGH,
// CAN_ENABLE_CAN_CAPTURE, etc) are given a default define in the can-mcp2510.h file.
// These default values can be overwritten in the main code, but most
// applications will be fine with these defaults.
//
//////////////////////////////////////////////////////////////////////////////
void can_init(void) {
struct struct_RXB0CTRL b_rxb0ctrl;
mcp2510_init();
can_set_mode(CAN_OP_CONFIG); //must be in config mode before params can be set
can_set_baud();
b_rxb0ctrl=0;
b_rxb0ctrl.rxm=CAN_RX_VALID;
b_rxb0ctrl.bukt=CAN_USE_RX_DOUBLE_BUFFER;
mcp2510_write(RXB0CTRL, (int)b_rxb0ctrl);
mcp2510_write(RXB1CTRL, (int)b_rxb0ctrl);
//if you want to configure the TXnRTS pins, do it here. default is off
can_set_id(RX0MASK, CAN_MASK_ACCEPT_ALL, 1); //set mask 0 (RX BUFFER 0)
can_set_id(RX0FILTER0, 0, 1); //set filter 0 of mask 0 (RX BUFFER 0)
can_set_id(RX0FILTER1, 0, 1); //set filter 1 of mask 0 (RX BUFFER 0)
can_set_id(RX1MASK, CAN_MASK_ACCEPT_ALL, 1); //set mask 1 (RX BUFFER 1)
can_set_id(RX1FILTER2, 0, 1); //set filter 0 of mask 1 (RX BUFFER 1)
can_set_id(RX1FILTER3, 0, 1); //set filter 1 of mask 1 (RX BUFFER 1)
can_set_id(RX1FILTER4, 0, 1); //set filter 2 of mask 1 (RX BUFFER 1)
can_set_id(RX1FILTER5, 0, 1); //set filter 3 of mask 1 (RX BUFFER 1)
can_set_mode(CAN_OP_NORMAL);
}
////////////////////////////////////////////////////////////////////////
//
// can_set_baud()
//
// Configures the baud rate control registers. All the defines here
// are defaulted in the can-mcp2510.h file. These defaults can, and
// probably should, be overwritten in the main code.
//
// Current defaults are set to work with CCS's CAN Prototype board and
// Microchip's MCP250xxx CAN Developers Kit if this PIC is running at 20Mhz.
//
////////////////////////////////////////////////////////////////////////
void can_set_baud(void) {
struct struct_CNF1 new_CNF1;
struct struct_CNF2 new_CNF2;
struct struct_CNF3 new_CNF3;
new_CNF1.brp=CAN_BRG_PRESCALAR;
new_CNF1.sjw=CAN_BRG_SYNCH_JUMP_WIDTH;
new_CNF2.prseg=CAN_BRG_PROPAGATION_TIME;
new_CNF2.phseg1=CAN_BRG_PHASE_SEGMENT_1;
new_CNF2.sam=CAN_BRG_SAM;
new_CNF2.btlmode=CAN_BRG_SEG_2_PHASE_TS;
new_CNF3.phseg2=CAN_BRG_PHASE_SEGMENT_2;
new_CNF3.wakfil=CAN_BRG_WAKE_FILTER;
mcp2510_write(CNF1, (int)new_CNF1);
mcp2510_write(CNF2, (int)new_CNF2);
mcp2510_write(CNF3, (int)new_CNF3);
}
void can_set_mode(CAN_OP_MODE mode) {
struct struct_CANCTRL old_CANCTRL;
old_CANCTRL=mcp2510_read(CANCTRL);
old_CANCTRL.reqop=mode;
mcp2510_write(CANCTRL, (int)old_CANCTRL);
do {
old_CANCTRL=mcp2510_read(CANCTRL);
} while (old_CANCTRL.reqop != mode);
}
////////////////////////////////////////////////////////////////////////
//
// can_set_id()
//
// Configures the xxxxEIDL, xxxxEIDH, xxxxSIDL and xxxxSIDH registers to
// configure the defined buffer to use the specified ID
//
// Paramaters:
// addr - pointer to first byte of ID register, starting with xxxxEIDL.
// For example, a pointer to RXM1EIDL
// id - ID to set buffer to
// ext - Set to TRUE if this buffer uses an extended ID, FALSE if not
//
////////////////////////////////////////////////////////////////////////
void can_set_id(int addr, int32 id, int1 ext) {
int converted_id[4];
int *ptr;
ptr=&converted_id[3]; //3=eidl, 2=eidh, 1=sidl, 0=sidh
if (ext) { //extended
//eidl
*ptr=make8(id,0); //0:7
//eidh
ptr--;
*ptr=make8(id,1); //8:15
//sidl
ptr--;
*ptr=make8(id,2) & 0x03; //16:17
*ptr|=(make8(id,2) << 3) & 0xE0; //18:20
*ptr|=0x08;
//sidh
ptr--;
*ptr=((make8(id,2) >> 5) & 0x07 ); //21:23
*ptr|=((make8(id,3) << 3) & 0xF8);//24:28
}
else { //standard
//eidl
*ptr=0;
//eidh
ptr--;
*ptr=0;
//sidl
ptr--;
*ptr=(make8(id,0) << 5) & 0xE0;
//sidh
ptr--;
*ptr=(make8(id,0) >> 3) & 0x1F;
*ptr|=(make8(id,1) << 5) & 0xE0;
}
//0=eidl, 1=eidh, 2=sidl, 3=sidh
mcp2510_write(addr--, converted_id[3]);
mcp2510_write(addr--, converted_id[2]);
mcp2510_write(addr--, converted_id[1]);
mcp2510_write(addr, converted_id[0]);
}
////////////////////////////////////////////////////////////////////////
//
// can_get_id()
//
// Returns the ID of the specified buffer. (The opposite of can_set_id())
// This is used after receiving a message, to see which ID sent the message.
//
// Paramaters:
// addr - pointer to first byte of ID register, starting with xxxxEIDL.
// For example, a pointer to RXM1EIDL
// ext - Set to TRUE if this buffer uses an extended ID, FALSE if not
//
// Returns:
// The ID of the buffer
//
////////////////////////////////////////////////////////////////////////
int32 can_get_id(int addr, int1 ext) {
int32 ret;
int * ptr;
int converted_id[4];
ptr=&converted_id[3]; //3=eidl, 2=eidh, 1=sidl, 0=sidh
converted_id[3]=mcp2510_read(addr--);
converted_id[2]=mcp2510_read(addr--);
converted_id[1]=mcp2510_read(addr--);
converted_id[0]=mcp2510_read(addr);
ret=0;
if (ext) {
ret=*ptr; //eidl
ptr--; //eidh
ret|=((int32)*ptr << 8);
ptr--; //sidl
ret|=((int32)*ptr & 0x03) << 16;
ret|=((int32)*ptr & 0xE0) << 13;
ptr--; //sidh
ret|=((int32)*ptr << 21);
}
else {
ptr-=2; //sidl
ret=((int32)*ptr & 0xE0) >> 5;
ptr--; //sidh
ret|=((int32)*ptr << 3);
}
return(ret);
}
////////////////////////////////////////////////////////////////////////
//
// can_putd()
//
// Puts data on a transmit buffer, at which time the CAN peripheral will
// send when the CAN bus becomes available.
//
// Paramaters:
// id - ID to transmit data as
// data - pointer to data to send
// len - length of data to send
// priority - priority of message. The higher the number, the
// sooner the CAN peripheral will send the message.
// Numbers 0 through 3 are valid.
// ext - TRUE to use an extended ID, FALSE if not
// rtr - TRUE to set the RTR (request) bit in the ID, false if NOT
//
// Returns:
// If successful, it will return TRUE
// If un-successful, will return FALSE
//
////////////////////////////////////////////////////////////////////////
int1 can_putd(int32 id, int * data, int len, int priority, int1 ext, int1 rtr) {
int i;
int port;
int TXRXBaD0;
int TXBaCTRL;
int TXRXBaEIDL;
int TXBaDLC;
struct txbNctrl_struct b_TXBaCTRL;
struct rxbNdlc_struct b_TXBaDLC;
struct txbNctrl_struct b_TXB0CTRL, b_TXB1CTRL, b_TXB2CTRL;
b_TXB0CTRL=mcp2510_read(TXB0CTRL);
b_TXB1CTRL=mcp2510_read(TXB1CTRL);
b_TXB2CTRL=mcp2510_read(TXB2CTRL);
// find emtpy transmitter
//map access bank addresses to empty transmitter
if (!b_TXB0CTRL.txreq) {
TXRXBaD0=TXB0D0;
TXBaCTRL=TXB0CTRL;
TXRXBaEIDL=TXB0EIDL;
TXBaDLC=TXB0DLC;
port=0;
}
else if (!b_TXB1CTRL.txreq) {
TXRXBaD0=TXB1D0;
TXBaCTRL=TXB1CTRL;
TXRXBaEIDL=TXB1EIDL;
TXBaDLC=TXB1DLC;
port=1;
}
else if (!b_TXB2CTRL.txreq) {
TXRXBaD0=TXB2D0;
TXBaCTRL=TXB2CTRL;
TXRXBaEIDL=TXB2EIDL;
TXBaDLC=TXB2DLC;
port=2;
}
else {
#if CAN_DO_DEBUG
can_debug("\r\nCAN_PUTD() FAIL: NO OPEN TX BUFFERS\r\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -