The mikroC PRO for PIC provides a library (driver) for working with the
CAN module.
The CAN is a very robust
protocol that has error detection and signalization, self–checking and fault
confinement. Faulty CAN data
and remote frames are re-transmitted automatically, similar to the Ethernet.
Data transfer rates depends on the distance. For example, 1 Mbit/s can be
achieved at network lengths below 40m while 250 Kbit/s can be achieved at
network lengths below 250m. The greater distance the lower maximum bitrate that
can be achieved. The lowest bitrate defined by the standard is 200Kbit/s. Cables
used are shielded twisted pairs.
CAN supports two message
formats:
- Standard format, with 11 identifier bits, and
- Extended format, with 29 identifier bits
Important :
- Consult the CAN standard about CAN bus termination resistance.
Library Routines
- CANSetOperationMode
- CANGetOperationMode
- CANInitialize
- CANSetBaudRate
- CANSetMask
- CANSetFilter
- CANRead
- CANWrite
- CANSetTxIdleLevel
CANSetOperationMode
Prototype | void CANSetOperationMode(unsigned short mode, unsigned short wait_flag); |
---|---|
Returns | Nothing. |
Description |
Sets CAN to requested
mode, i.e. copies mode to CANSTAT. Parameter mode
needs to be one of CAN_OP_MODE constants .Parameter wait_flag needs to be either 0 or 0xFF:
|
Requires | Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | CANSetOperationMode(_CAN_MODE_CONFIG, 0xFF); |
CANGetOperationMode
Prototype | unsigned short CANGetOperationMode(); |
---|---|
Returns | Current opmode. |
Description | Function returns current operational mode of CAN module. |
Requires | Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | if (CANGetOperationMode() == _CAN_MODE_NORMAL) { ... }; |
CANInitialize
Prototype | void CANInitialize(char SJW, char BRP, char PHSEG1, char PHSEG2, char PROPSEG, char CAN_CONFIG_FLAGS); |
---|---|
Returns | Nothing. |
Description |
Initializes CAN. All
pending transmissions are aborted. Sets all mask registers to 0 to allow all
messages. Filter registers are set according to flag value: if (CAN_CONFIG_FLAGS & _CAN_CONFIG_VALID_XTD_MSG != 0) // Set all filters to XTD_MSG else if (config & _CAN_CONFIG_VALID_STD_MSG != 0) // Set all filters to STD_MSG else // Set half of the filters to STD, and the rest to XTD_MSG.Parameters:
|
Requires |
CAN must be in Config
mode; otherwise the function will be ignored. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | init = _CAN_CONFIG_SAMPLE_THRICE &
_CAN_CONFIG_PHSEG2_PRG_ON &
_CAN_CONFIG_STD_MSG &
_CAN_CONFIG_DBL_BUFFER_ON &
_CAN_CONFIG_VALID_XTD_MSG &
_CAN_CONFIG_LINE_FILTER_OFF;
...
CANInitialize(1, 1, 3, 3, 1, init); // initialize CAN
|
CANSetBaudRate
Prototype | void CANSetBaudRate(char SJW, char BRP, char PHSEG1, char PHSEG2, char PROPSEG, char CAN_CONFIG_FLAGS); |
---|---|
Returns | Nothing. |
Description |
Sets CAN baud rate. Due to
complexity of CAN protocol,
you cannot simply force a bps value. Instead, use this function when CAN is in Config mode. Refer to
datasheet for details. Parameters:
|
Requires |
CAN must be in Config
mode; otherwise the function will be ignored. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | init = _CAN_CONFIG_SAMPLE_THRICE &
_CAN_CONFIG_PHSEG2_PRG_ON &
_CAN_CONFIG_STD_MSG &
_CAN_CONFIG_DBL_BUFFER_ON &
_CAN_CONFIG_VALID_XTD_MSG &
_CAN_CONFIG_LINE_FILTER_OFF;
...
CANSetBaudRate(1, 1, 3, 3, 1, init);
|
CANSetMask
Prototype | void CANSetMask(char CAN_MASK, long value, char CAN_CONFIG_FLAGS); |
---|---|
Returns | Nothing. |
Description |
Function sets mask for advanced filtering of messages. Given
value is bit adjusted to appropriate buffer mask registers.Parameters:
|
Requires |
CAN must be in Config
mode; otherwise the function will be ignored. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | // Set all mask bits to 1, i.e. all filtered bits are relevant: CANSetMask(_CAN_MASK_B1, -1, _CAN_CONFIG_XTD_MSG); // Note that -1 is just a cheaper way to write 0xFFFFFFFF. Complement will do the trick and fill it up with ones. |
CANSetFilter
Prototype | void CANSetFilter(char CAN_FILTER, long value, char CAN_CONFIG_FLAGS); |
---|---|
Returns | Nothing. |
Description |
Function sets message filter. Given value is bit adjusted to
appropriate buffer mask registers.Parameters:
|
Requires |
CAN must be in Config
mode; otherwise the function will be ignored. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | // Set id of filter B1_F1 to 3: CANSetFilter(_CAN_FILTER_B1_F1, 3, _CAN_CONFIG_XTD_MSG); |
CANRead
Prototype | char CANRead(long *id, char *data, char *datalen, char *CAN_RX_MSG_FLAGS); |
---|---|
Returns | Message from receive buffer or zero if no message found. |
Description |
Function reads message from receive buffer. If at least one full receive
buffer is found, it is extracted and returned. If none found, function returns
zero. Parameters:
|
Requires |
CAN must be in mode in
which receiving is possible. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | char rcv, rx, len, data[8];
long id;
// ...
rx = 0;
// ...
rcv = CANRead(id, data, len, rx);
|
CANWrite
Prototype | unsigned short CANWrite(long id, char *data, char datalen, char CAN_TX_MSG_FLAGS); |
---|---|
Returns | Returns zero if message cannot be queued (buffer full). |
Description |
If at least one empty transmit buffer is found, function sends message on
queue for transmission. If buffer is full, function returns 0. Parameters:
|
Requires |
CAN must be in Normal
mode. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. |
Example | char tx, data;
long id;
// ...
tx = _CAN_TX_PRIORITY_0 &
_CAN_TX_XTD_FRAME;
// ...
CANWrite(id, data, 2, tx);
|
CANSetTxIdleLevel
Prototype | void CANSetTxIdleLevel(char driveHighState); | ||||||
---|---|---|---|---|---|---|---|
Returns | Nothing. | ||||||
Description |
This function sets the state of CANTX pin when recessive. Parameters:
| ||||||
Requires | Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus. | ||||||
Example | CANSetTxIdleLevel(_CAN_DRIVE_HIGH_STATE_ENABLE); |
CAN Constants
There is a number of constants predefined in CAN library. To be able to use the
library effectively, you need to be familiar with these. You might want to check
the example at the end of the chapter.
CAN_OP_MODE
CAN_OP_MODE
constants define CAN operation mode. Function
CANSetOperationMode
expects one of these as its argument:const char_CAN_MODE_BITS = 0xE0, // Use this to access opmode bits_CAN_MODE_NORMAL = 0x00,_CAN_MODE_SLEEP = 0x20,_CAN_MODE_LISTEN = 0x60,_CAN_MODE_LOOP = 0x40,_CAN_MODE_CONFIG = 0x80;
CAN_CONFIG_FLAGS
CAN_CONFIG_FLAGS
constants define flags related to CAN module configuration. Functions
CANInitialize
and CANSetBaudRate
expect one of these
(or a bitwise combination) as their argument:const char_CAN_CONFIG_DEFAULT = 0xFF, // 11111111_CAN_CONFIG_PHSEG2_PRG_BIT = 0x01,_CAN_CONFIG_PHSEG2_PRG_ON = 0xFF, // XXXXXXX1_CAN_CONFIG_PHSEG2_PRG_OFF = 0xFE, // XXXXXXX0_CAN_CONFIG_LINE_FILTER_BIT = 0x02,_CAN_CONFIG_LINE_FILTER_ON = 0xFF, // XXXXXX1X_CAN_CONFIG_LINE_FILTER_OFF = 0xFD, // XXXXXX0X_CAN_CONFIG_SAMPLE_BIT = 0x04,_CAN_CONFIG_SAMPLE_ONCE = 0xFF, // XXXXX1XX_CAN_CONFIG_SAMPLE_THRICE = 0xFB, // XXXXX0XX_CAN_CONFIG_MSG_TYPE_BIT = 0x08,_CAN_CONFIG_STD_MSG = 0xFF, // XXXX1XXX_CAN_CONFIG_XTD_MSG = 0xF7, // XXXX0XXX_CAN_CONFIG_DBL_BUFFER_BIT = 0x10,_CAN_CONFIG_DBL_BUFFER_ON = 0xFF, // XXX1XXXX_CAN_CONFIG_DBL_BUFFER_OFF = 0xEF, // XXX0XXXX_CAN_CONFIG_MSG_BITS = 0x60,_CAN_CONFIG_ALL_MSG = 0xFF, // X11XXXXX_CAN_CONFIG_VALID_XTD_MSG = 0xDF, // X10XXXXX_CAN_CONFIG_VALID_STD_MSG = 0xBF, // X01XXXXX_CAN_CONFIG_ALL_VALID_MSG = 0x9F; // X00XXXXX
You may use bitwise AND (
&
) to form config byte out of these
values. For example:init = _CAN_CONFIG_SAMPLE_THRICE &_CAN_CONFIG_PHSEG2_PRG_ON &_CAN_CONFIG_DBL_BUFFER_ON &_CAN_CONFIG_STD_MSG & _CAN_CONFIG_VALID_XTD_MSG &CANInitialize(1, 1, 3, 3, 1, init); // initialize CAN_CAN_CONFIG_LINE_FILTER_OFF;...
CAN_TX_MSG_FLAGS
CAN_TX_MSG_FLAGS
are flags related to transmission of a CAN message:const char_CAN_TX_PRIORITY_BITS = 0x03,_CAN_TX_PRIORITY_0 = 0xFC, // XXXXXX00_CAN_TX_PRIORITY_1 = 0xFD, // XXXXXX01_CAN_TX_PRIORITY_2 = 0xFE, // XXXXXX10_CAN_TX_PRIORITY_3 = 0xFF, // XXXXXX11_CAN_TX_FRAME_BIT = 0x08,_CAN_TX_STD_FRAME = 0xFF, // XXXXX1XX_CAN_TX_XTD_FRAME = 0xF7, // XXXXX0XX_CAN_TX_RTR_BIT = 0x40,_CAN_TX_NO_RTR_FRAME = 0xFF, // X1XXXXXX_CAN_TX_RTR_FRAME = 0xBF; // X0XXXXXX
You may use bitwise AND (
&
) to adjust the appropriate flags.
For example:// form value to be used with CANSendMessage:send_config = _CAN_TX_PRIORITY_0 &_CAN_TX_XTD_FRAME &_CAN_TX_NO_RTR_FRAME;...CANSendMessage(id, data, 1, send_config);
CAN_RX_MSG_FLAGS
CAN_RX_MSG_FLAGS
are flags related to reception of CAN message. If a particular bit is
set; corresponding meaning is TRUE or else it will be FALSE.const char_CAN_RX_FILTER_BITS = 0x07, // Use this to access filter bits_CAN_RX_FILTER_1 = 0x00,_CAN_RX_FILTER_2 = 0x01,_CAN_RX_FILTER_4 = 0x03,_CAN_RX_FILTER_3 = 0x02, _CAN_RX_FILTER_5 = 0x04,_CAN_RX_OVERFLOW = 0x08, // Set if Overflowed else cleared_CAN_RX_FILTER_6 = 0x05,_CAN_RX_INVALID_MSG = 0x10, // Set if invalid else cleared_CAN_RX_XTD_FRAME = 0x20, // Set if XTD message else cleared_CAN_RX_RTR_FRAME = 0x40, // Set if RTR message else cleared_CAN_RX_DBL_BUFFERED = 0x80; // Set if this message was hardware double-buffered
You may use bitwise AND (
&
) to adjust the appropriate flags.
For example:if (MsgFlag & _CAN_RX_OVERFLOW != 0) {...// Receiver overflow has occurred.// We have lost our previous message.}
CAN_MASK
CAN_MASK
constants define mask codes. Function
CANSetMask
expects one of these as its argument:#const char_CAN_MASK_B1 = 0,_CAN_MASK_B2 = 1;
CAN_FILTER
CAN_FILTER
constants define filter codes. Function
CANSetFilter
expects one of these as its argument:const char_CAN_FILTER_B1_F1 = 0,_CAN_FILTER_B1_F2 = 1,_CAN_FILTER_B2_F2 = 3,_CAN_FILTER_B2_F1 = 2, _CAN_FILTER_B2_F3 = 4,_CAN_FILTER_B2_F4 = 5;
Library Example
This is a simple demonstration of CAN Library routines usage. First node
initiates the communication with the second node by sending some data to its
address. The second node responds by sending back the data incremented by 1.
First node then does the same and sends incremented data back to second node,
etc.
Code for the first CAN node:
unsigned char Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags; // can flagsunsigned char Rx_Data_Len; // received data length in byteschar RxTx_Data[8]; // can rx/tx data bufferchar Msg_Rcvd; // reception flagconst long ID_1st = 12111, ID_2nd = 3; // node IDslong Rx_ID;void main() {PORTC = 0; // clear PORTCTRISC = 0; // set PORTC as outputCan_Init_Flags = 0; //Can_Send_Flags = 0; // clear flagsCan_Rcv_Flags = 0; //Can_Send_Flags = _CAN_TX_PRIORITY_0 & // form value to be used_CAN_TX_XTD_FRAME & // with CANWrite_CAN_TX_NO_RTR_FRAME;Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE & // form value to be used_CAN_CONFIG_PHSEG2_PRG_ON & // with CANInit_CAN_CONFIG_XTD_MSG &_CAN_CONFIG_DBL_BUFFER_ON &_CAN_CONFIG_VALID_XTD_MSG;CANInitialize(1,3,3,3,1,Can_Init_Flags); // Initialize CAN moduleCANSetOperationMode(_CAN_MODE_CONFIG,0xFF); // set CONFIGURATION modeCANSetMask(_CAN_MASK_B1,-1,_CAN_CONFIG_XTD_MSG); // set all mask1 bits to onesCANSetMask(_CAN_MASK_B2,-1,_CAN_CONFIG_XTD_MSG); // set all mask2 bits to onesCANSetFilter(_CAN_FILTER_B2_F4,ID_2nd,_CAN_CONFIG_XTD_MSG);// set id of filter B2_F4 to 2nd node IDCANSetOperationMode(_CAN_MODE_NORMAL,0xFF); // set NORMAL modeRxTx_Data[0] = 9; // set initial data to be sentCANWrite(ID_1st, RxTx_Data, 1, Can_Send_Flags); // send initial messagewhile(1) { // endless loopMsg_Rcvd = CANRead(&Rx_ID , RxTx_Data , &Rx_Data_Len, &Can_Rcv_Flags); // receive messageif ((Rx_ID == ID_2nd) && Msg_Rcvd) { // if message received check idPORTC = RxTx_Data[0]; // id correct, output data at PORTCRxTx_Data[0]++ ; // increment received dataDelay_ms(10);CANWrite(ID_1st, RxTx_Data, 1, Can_Send_Flags); // send incremented data back}}}
Code for the second CAN node:
unsigned char Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags; // can flagsunsigned char Rx_Data_Len; // received data length in byteschar RxTx_Data[8]; // can rx/tx data bufferchar Msg_Rcvd; // reception flagconst long ID_1st = 12111, ID_2nd = 3; // node IDslong Rx_ID;void main() {PORTC = 0; // clear PORTCTRISC = 0; // set PORTC as outputCan_Init_Flags = 0; //Can_Send_Flags = 0; // clear flagsCan_Rcv_Flags = 0; //Can_Send_Flags = _CAN_TX_PRIORITY_0 & // form value to be used_CAN_TX_XTD_FRAME & // with CANWrite_CAN_TX_NO_RTR_FRAME;Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE & // form value to be used_CAN_CONFIG_PHSEG2_PRG_ON & // with CANInit_CAN_CONFIG_XTD_MSG &_CAN_CONFIG_DBL_BUFFER_ON &_CAN_CONFIG_VALID_XTD_MSG &_CAN_CONFIG_LINE_FILTER_OFF;CANInitialize(1,3,3,3,1,Can_Init_Flags); // initialize external CAN moduleCANSetOperationMode(_CAN_MODE_CONFIG,0xFF); // set CONFIGURATION modeCANSetMask(_CAN_MASK_B1,-1,_CAN_CONFIG_XTD_MSG); // set all mask1 bits to onesCANSetMask(_CAN_MASK_B2,-1,_CAN_CONFIG_XTD_MSG); // set all mask2 bits to onesCANSetFilter(_CAN_FILTER_B2_F3,ID_1st,_CAN_CONFIG_XTD_MSG);// set id of filter B2_F3 to 1st node IDCANSetOperationMode(_CAN_MODE_NORMAL,0xFF); // set NORMAL modewhile (1) { // endless loopMsg_Rcvd = CANRead(&Rx_ID , RxTx_Data , &Rx_Data_Len, &Can_Rcv_Flags); // receive messageif ((Rx_ID == ID_1st) && Msg_Rcvd) { // if message received check idPORTC = RxTx_Data[0]; // id correct, output data at PORTCRxTx_Data[0]++ ; // increment received dataCANWrite(ID_2nd, RxTx_Data, 1, Can_Send_Flags); // send incremented data back}}}
No comments:
Post a Comment