ECAN Library
The mikroC PRO for dsPIC30/33 and PIC24 provides a library (driver) for working with the dsPIC33FJ and pic24HJ ECAN module.
ECAN is a very robust protocol that has error detection and signalling, self–checking and fault confinement. Faulty ECAN data and remote frames are re-transmitted automatically, similar to the Ethernet.
Data transfer rates depend on 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.
ECAN supports two message formats:
- Standard format, with 11 identifier bits, and
- Extended format, with 29 identifier bits
ECAN message format and DMA RAM buffer definiton can be found in the ECan_Defs.h
header file located in the ECAN project folder. Read this file carefully and make appropriate adjustments for mcu in use. Also, if a new project is to be created this file has to be copied, adjusted and included into the project via include pragma directive with corresponding Search Path updating.

- ECAN buffers are located in DMA RAM, so two DMA channels are used for message transfer, one for each direction (ECAN->DMA RAM, DMA RAM->ECAN). See the ECANxDmaChannelInit routine.
- Consult CAN standard about CAN bus termination resistance.
- CAN library routines require you to specify the module you want to use. To select the desired CAN module, simply change the letter x in the routine prototype for a number from 1 to 2.
- Number of CAN modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.
Library Routines
- ECANxDmaChannelInit
- ECANxSetOperationMode
- ECANxGetOperationMode
- ECANxInitialize
- ECANxSelectTxBuffers
- ECANxFilterDisable
- ECANxFilterEnable
- ECANxSetBufferSize
- ECANxSetBaudRate
- ECANxSetMask
- ECANxSetFilter
- ECANxRead
- ECANxWrite
ECANxDmaChannelInit
Prototype |
unsigned ECANxDmaChannelInit(unsigned DmaChannel, unsigned ChannelDir, void *DmaRamBuffAdd); |
---|---|
Description |
The function preforms initialization of the DMA module for ECAN. |
Parameters |
|
Returns |
|
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. |
Example |
// channel 0 will transfer 8 words from DMA RAM at 0x4000 to ECAN1 ECAN1DmaChannelInit(0, 1, 0x4000); |
Notes |
|
ECANxSetOperationMode
Prototype |
void ECANxSetOperationMode(unsigned int mode, unsigned int WAIT); |
---|---|
Description |
Sets the ECAN module to requested mode. |
Parameters |
|
Returns |
Nothing. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. |
Example |
// set the ECAN1 module into configuration mode (wait inside ECAN1SetOperationMode until this mode is set) ECAN1SetOperationMode(_ECAN_MODE_CONFIG, 0xFF); |
Notes |
|
ECANxGetOperationMode
Prototype |
unsigned int ECANxGetOperationMode(); |
---|---|
Description |
The function returns current operation mode of the ECAN module. See ECAN_OP_MODE constants or device datasheet for operation mode codes. |
Parameters |
None. |
Returns |
Current operation mode. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. |
Example |
// check whether the ECAN1 module is in Normal mode and if it is do something. if (ECAN1GetOperationMode() == _ECAN_MODE_NORMAL) { ... } |
Notes |
|
ECANxInitialize
Prototype |
void ECANxInitialize(unsigned int SJW, unsigned int BRP, unsigned int PHSEG1, unsigned int PHSEG2, unsigned int PROPSEG, unsigned int ECAN_CONFIG_FLAGS); |
---|---|
Description |
Initializes the ECAN module. The internal ECAN module is set to:
|
Parameters |
|
Returns |
Nothing. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. |
Example |
// initialize the ECAN1 module with appropriate baud rate and message acceptance flags along with the sampling rules unsigned int ecan_config_flags; ... ecan_config_flags = _ECAN_CONFIG_SAMPLE_THRICE & // Form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON & // with ECANInitialize _ECAN_CONFIG_XTD_MSG & _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_LINE_FILTER_OFF; ECAN1Initialize(1, 3, 3, 3, 1, ecan_config_flags); // initialize the ECAN1 module |
Notes |
|
ECANxSelectTxBuffers
Prototype |
unsigned ECANxSelectTxBuffers(unsigned txselect); |
---|---|
Description |
The function designates the ECAN module's transmit buffers. |
Parameters |
|
Returns |
|
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be initialized. See the ECANxInitialize routine. |
Example |
// Buffers 0 and 2 are enabled for transmition: ECAN1SelectTxBuffers(0x0005); |
Notes |
|
ECANxFilterDisable
Prototype |
void ECANxFilterDisable(unsigned fltdis); |
---|---|
Description |
The function disables receive filters. |
Parameters |
|
Returns |
Nothing. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be initialized. See the ECANxInitialize routine. |
Example |
// Filters 0, 4, 8, 12 are to be disabled: ECAN1FilterDisable(0x1111); |
Notes |
|
ECANxFilterEnable
Prototype |
void ECANxFilterEnable(unsigned flten); |
---|---|
Description |
The function enables receive filters. |
Parameters |
|
Returns |
Nothing. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be initialized. See the ECANxInitialize routine. |
Example |
// Filters 0, 4, 8, 12 are to be enabled: ECAN1FilterEnable(0x1111); |
Notes |
|
ECANxSetBufferSize
Prototype |
unsigned ECANxSetBufferSize(unsigned Ecan1BuffSize); |
---|---|
Description |
The function configures the total number of receive and transmit buffers in DMA RAM. |
Parameters |
|
Returns |
|
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be initialized. See the ECANxInitialize routine. |
Example |
// DMA RAM will have 16 rx+tx buffers ECAN1SetBufferSize(16); |
Notes |
ECan_Defs.h header file located in the ECAN project folder. |
ECANxSetBaudRate
Prototype |
void ECANxSetBaudRate(unsigned int SJW, unsigned int BRP, unsigned int PHSEG1, unsigned int PHSEG2, unsigned int PROPSEG, unsigned int ECAN_CONFIG_FLAGS); |
---|---|
Description |
Sets ECAN module baud rate. Due to complexity of the ECAN protocol, you can not simply force the bps value. Instead, use this function when ECAN is in Config mode. Refer to datasheet for details.
|
Parameters |
|
Returns |
Nothing. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be in Config mode, otherwise the function will be ignored. See ECANxSetOperationMode. |
Example |
// set required baud rate and sampling rules unsigned int ecan_config_flags; ... ECAN1SetOperationMode(_ECAN_MODE_CONFIG,0xFF); // set CONFIGURATION mode (ECAN1 module mast be in config mode for baud rate settings) ecan_config_flags = _ECAN_CONFIG_SAMPLE_THRICE & // Form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON & // with ECAN1SetBaudRate _ECAN_CONFIG_XTD_MSG & _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_LINE_FILTER_OFF; ECAN1SetBaudRate(1, 3, 3, 3, 1, ecan_config_flags); // set ECAN1 module baud rate |
Notes |
|
ECANxSetMask
Prototype |
void ECANxSetMask(unsigned int ECAN_MASK, long val, unsigned int ECAN_CONFIG_FLAGS); |
---|---|
Description |
The function configures appropriate mask for advanced message filtering. |
Parameters |
|
Returns |
Nothing. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be in Config mode, otherwise the function will be ignored. See ECANxSetOperationMode. |
Example |
// set appropriate filter mask and message type value ECAN1SetOperationMode(_ECAN_MODE_CONFIG,0xFF); // set CONFIGURATION mode (ECAN1 module must be in config mode for mask settings) // Set all mask0 bits to 1 (all filtered bits are relevant): // Note that -1 is just a cheaper way to write 0xFFFFFFFF. // Complement will do the trick and fill it up with ones. ECAN1SetMask(_ECAN_MASK_0, -1, _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_XTD_MSG); |
Notes |
|
ECANxSetFilter
Prototype |
void ECANxSetFilter(unsigned int ECAN_FILTER, long val, unsigned int ECAN_FILTER_MASK, unsigned int ECAN_FILTER_RXBUFF, unsigned int ECAN_CONFIG_FLAGS); |
---|---|
Description |
The function configures and enables appropriate message filter. |
Parameters |
|
Returns |
Nothing. |
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be in Config mode, otherwise the function will be ignored. See ECANxSetOperationMode. |
Example |
// set appropriate filter value and message type ECAN1SetOperationMode(_ECAN_MODE_CONFIG,0xFF); // set CONFIGURATION mode (ECAN1 module must be in config mode for filter settings) // Set id of filter 10 to 3, mask2, receive buffer 7, extended messages: ECAN1SetFilter(_ECAN_FILTER_10, 3, _ECAN_MASK_2, _ECAN_RX_BUFFER_7, _ECAN_CONFIG_XTD_MSG); |
Notes |
|
ECANxRead
Prototype |
unsigned int ECANxRead(unsigned long *id, char *data, unsigned int *dataLen, unsigned int *ECAN_RX_MSG_FLAGS); |
---|---|
Description |
If at least one full Receive Buffer is found, it will be processed in the following way:
|
Parameters |
|
Returns |
|
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be in a mode in which receiving is possible. See ECANxSetOperationMode. |
Example |
// check the ECAN1 module for received messages. If any was received do something. unsigned int msg_rcvd, rx_flags, data_len; char data[8]; unsigned long msg_id; ... ECAN1SetOperationMode(_ECAN_MODE_NORMAL,0xFF); // set NORMAL mode (ECAN1 module must be in a mode in which receiving is possible) ... rx_flags = 0; // clear message flags if (msg_rcvd = ECAN1Read(&msg_id, data, &data_len, &rx_flags)) { ... } |
Notes |
|
ECANxWrite
Prototype |
unsigned int ECANxWrite(long id, char *Data, unsigned int DataLen, unsigned int ECAN_TX_MSG_FLAGS); |
---|---|
Description |
If at least one empty Transmit Buffer is found, the function sends message in the queue for transmission. |
Parameters |
|
Returns |
|
Requires |
The ECAN routines are supported only by MCUs with the ECAN module. Microcontroller must be connected to ECAN transceiver which is connected to the ECAN bus. The ECAN module must be in a mode in which transmission is possible. See ECANxSetOperationMode. |
Example |
// send message extended ECAN message with appropriate ID and data unsigned int tx_flags; char data[8]; unsigned long msg_id; ... ECAN1SetOperationMode(_ECAN_MODE_NORMAL,0xFF); // set NORMAL mode (ECAN1 must be in a mode in which transmission is possible) tx_flags = _ECAN_TX_PRIORITY_0 & _ECAN_TX_XTD_FRAME & _ECAN_TX_NO_RTR_FRAME; // set message flags ECAN1Write(msg_id, data, 1, tx_flags); |
Notes |
|
ECAN Constants
There is a number of constants predefined in the ECAN library. You need to be familiar with them in order to be able to use the library effectively. Check the example at the end of the chapter.
ECAN_OP_MODE Constants
The ECAN_OP_MODE
constants define ECAN operation mode. The routine ECANxSetOperationMode expect one of these as their argument:
const unsigned int _ECAN_MODE_BITS = 0x00E0, // Use this to access opmode bits _ECAN_MODE_NORMAL = 0x00, _ECAN_MODE_DISABLE = 0x01, _ECAN_MODE_LOOP = 0x02, _ECAN_MODE_LISTEN = 0x03, _ECAN_MODE_CONFIG = 0x04, _ECAN_MODE_LISTEN_ALL = 0x07;
ECAN_CONFIG_FLAGS Constants
The ECAN_CONFIG_FLAGS
constants define flags related to the ECAN module configuration. The routines ECANxInitialize and ECANxSetBaudRate expect one of these (or a bitwise combination) as their argument:
const unsigned int _ECAN_CONFIG_DEFAULT = 0xFF, // 11111111 _ECAN_CONFIG_PHSEG2_PRG_BIT = 0x01, _ECAN_CONFIG_PHSEG2_PRG_ON = 0xFF, // XXXXXXX1 _ECAN_CONFIG_PHSEG2_PRG_OFF = 0xFE, // XXXXXXX0 _ECAN_CONFIG_LINE_FILTER_BIT = 0x02, _ECAN_CONFIG_LINE_FILTER_ON = 0xFF, // XXXXXX1X _ECAN_CONFIG_LINE_FILTER_OFF = 0xFD, // XXXXXX0X _ECAN_CONFIG_SAMPLE_BIT = 0x04, _ECAN_CONFIG_SAMPLE_ONCE = 0xFF, // XXXXX1XX _ECAN_CONFIG_SAMPLE_THRICE = 0xFB, // XXXXX0XX _ECAN_CONFIG_MSG_TYPE_BIT = 0x08, _ECAN_CONFIG_STD_MSG = 0xFF, // XXXX1XXX _ECAN_CONFIG_XTD_MSG = 0xF7, // XXXX0XXX _ECAN_CONFIG_MATCH_TYPE_BIT = 0x20, _ECAN_CONFIG_ALL_VALID_MSG = 0xDF, // XX0XXXXX _ECAN_CONFIG_MATCH_MSG_TYPE = 0xFF; // XX1XXXXX
You may use bitwise AND (&
) to form config word out of these values. For example:
init = _ECAN_CONFIG_SAMPLE_THRICE & _ECAN_CONFIG_PHSEG2_PRG_ON & _ECAN_CONFIG_STD_MSG & _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_LINE_FILTER_OFF; ... ECAN1Initialize(1, 1, 3, 3, 1, init); // initialize ECAN1
ECAN_TX_MSG_FLAGS Constants
ECAN_TX_MSG_FLAGS
are flags related to transmission of ECAN message. The routine ECANxWrite expect one of these (or a bitwise combination) as their argument:
const unsigned int _ECAN_TX_PRIORITY_BITS = 0x03, _ECAN_TX_PRIORITY_0 = 0xFC, // XXXXXX00 _ECAN_TX_PRIORITY_1 = 0xFD, // XXXXXX01 _ECAN_TX_PRIORITY_2 = 0xFE, // XXXXXX10 _ECAN_TX_PRIORITY_3 = 0xFF, // XXXXXX11 _ECAN_TX_FRAME_BIT = 0x08, _ECAN_TX_STD_FRAME = 0xFF, // XXXXX1XX _ECAN_TX_XTD_FRAME = 0xF7, // XXXXX0XX _ECAN_TX_RTR_BIT = 0x40, _ECAN_TX_NO_RTR_FRAME = 0xFF, // X1XXXXXX _ECAN_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 = _ECAN_TX_PRIORITY_0 & _ECAN_TX_XTD_FRAME & _ECAN_TX_NO_RTR_FRAME; ... ECAN1SendMessage(id, data, 1, send_config);
ECAN_RX_MSG_FLAGS Constants
ECAN_RX_MSG_FLAGS
are flags related to reception of ECAN message. If a particular bit is set then corresponding meaning is TRUE or else it will be FALSE.
const unsigned int _ECAN_RX_FILTER_BITS = 0x000F, // Use this to access filter bits _ECAN_RX_FILTER_0 = 0x00, // filter0 match _ECAN_RX_FILTER_1 = 0x01, // filter1 match _ECAN_RX_FILTER_2 = 0x02, // ... _ECAN_RX_FILTER_3 = 0x03, _ECAN_RX_FILTER_4 = 0x04, _ECAN_RX_FILTER_5 = 0x05, _ECAN_RX_FILTER_6 = 0x06, _ECAN_RX_FILTER_7 = 0x07, _ECAN_RX_FILTER_8 = 0x08, _ECAN_RX_FILTER_9 = 0x09, _ECAN_RX_FILTER_10 = 0x0A, _ECAN_RX_FILTER_11 = 0x0B, _ECAN_RX_FILTER_12 = 0x0C, _ECAN_RX_FILTER_13 = 0x0D, _ECAN_RX_FILTER_14 = 0x0E, // ... _ECAN_RX_FILTER_15 = 0x0F, // filter15 match _ECAN_RX_OVERFLOW = 0x10, // Set if Overflowed else cleared _ECAN_RX_INVALID_MSG = 0x20, // Set if invalid else cleared _ECAN_RX_XTD_FRAME = 0x40, // Set if XTD message else cleared _ECAN_RX_RTR_FRAME = 0x80; // Set if RTR message else cleared
You may use bitwise AND (&
) to extract received message status. For example:
if (MsgFlag & _ECAN_RX_OVERFLOW != 0) { ... // Receiver overflow has occurred. // We have lost our previous message. }
ECAN_MASK Constants
The ECAN_MASK
constants define mask codes. The routine ECANxSetMask expect one of these as their argument:
const unsigned int _ECAN_MASK_0 = 0, _ECAN_MASK_1 = 1, _ECAN_MASK_2 = 2;
ECAN_FILTER Constants
The ECAN_FILTER
constants define filter codes. The routine ECANxSetFilter expect one of these as their argument:
const unsigned int _ECAN_FILTER_0 = 0, _ECAN_FILTER_1 = 1, _ECAN_FILTER_2 = 2, _ECAN_FILTER_3 = 3, _ECAN_FILTER_4 = 4, _ECAN_FILTER_5 = 5, _ECAN_FILTER_6 = 6, _ECAN_FILTER_7 = 7, _ECAN_FILTER_8 = 8, _ECAN_FILTER_9 = 9, _ECAN_FILTER_10 = 10, _ECAN_FILTER_11 = 11, _ECAN_FILTER_12 = 12, _ECAN_FILTER_13 = 13, _ECAN_FILTER_14 = 14, _ECAN_FILTER_15 = 15;
ECAN_RX_BUFFER Constants
The ECAN_RX_BUFFER
constants define RX bufer codes codes. The routine ECANxSetFilter expect one of these as their argument:
const unsigned int _ECAN_RX_BUFFER_0 = 0, _ECAN_RX_BUFFER_1 = 1, _ECAN_RX_BUFFER_2 = 2, _ECAN_RX_BUFFER_3 = 3, _ECAN_RX_BUFFER_4 = 4, _ECAN_RX_BUFFER_5 = 5, _ECAN_RX_BUFFER_6 = 6, _ECAN_RX_BUFFER_7 = 7, _ECAN_RX_BUFFER_8 = 8, _ECAN_RX_BUFFER_9 = 9, _ECAN_RX_BUFFER_10 = 10, _ECAN_RX_BUFFER_11 = 11, _ECAN_RX_BUFFER_12 = 12, _ECAN_RX_BUFFER_13 = 13, _ECAN_RX_BUFFER_14 = 14, _ECAN_RX_BUFFER_15 = 15;
Library Example
The example demonstrates ECAN protocol. The 1st node initiates the communication with the 2nd node by sending some data to its address. The 2nd node responds by sending back the data incremented by 1. The 1st node then does the same and sends incremented data back to the 2nd node, etc.
Code for the first ECAN node:
#include "ECAN_Defs.h" unsigned int Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags; // can flags unsigned int Rx_Data_Len; // received data length in bytes char RxTx_Data[8]; // can rx/tx data buffer char Msg_Rcvd; // reception flag unsigned long Tx_ID, Rx_ID; // can rx and tx ID void C1Interrupt(void) org 0x005A { // ECAN event iterrupt IFS2bits.C1IF = 0; // clear ECAN interrupt flag if(C1INTFbits.TBIF) { // was it tx interrupt? C1INTFbits.TBIF = 0; // if yes clear tx interrupt flag } if(C1INTFbits.RBIF) { // was it rx interrupt? C1INTFbits.RBIF = 0; // if yes clear rx interrupt flag } } void main() { // Set PLL : Fosc = ((Fin/PLLPRE)*PLLDIV)/PLLPOST ; (((10MHz/2)*32)/4) = 20MHz // refer the pic24 family datasheet for more details CLKDIV &= 0xFFE0; //CLKDIVbits.PLLPRE = 0; PLLFBD = 0x1E; //PLLFBDbits.PLLDIV = 0x1E; CLKDIV &= 0xFF3F; //CLKDIVbits.PLLPOST = 1; CLKDIV |= 0x00C0; AD1PCFGH = 0xFFFF; // AD1PCFGL = 0xFFFF; // all ports digital I/O AD2PCFGL = 0xFFFF; // /* Clear Interrupt Flags */ IFS0=0; IFS1=0; IFS2=0; IFS3=0; IFS4=0; /* Enable ECAN1 Interrupt */ IEC2bits.C1IE = 1; // enable ECAN1 interrupts C1INTEbits.TBIE = 1; // enable ECAN1 tx interrupt C1INTEbits.RBIE = 1; // enable ECAN1 rx interrupt PORTB = 0; // clear PORTB TRISB = 0; // set PORTB as output, // for received message data displaying Can_Init_Flags = 0; // Can_Send_Flags = 0; // clear flags Can_Rcv_Flags = 0; // Can_Send_Flags = _ECAN_TX_PRIORITY_0 & // Form value to be used _ECAN_TX_XTD_FRAME & // with CANSendMessage _ECAN_TX_NO_RTR_FRAME; Can_Init_Flags = _ECAN_CONFIG_SAMPLE_THRICE & // Form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON & // with CANInitialize _ECAN_CONFIG_XTD_MSG & _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_LINE_FILTER_OFF; RxTx_Data[0] = 9; // set initial data to be sent ECAN1DmaChannelInit(0, 1, &ECAN1RxTxRAMBuffer); // init dma channel 0 for // dma to ECAN peripheral transfer ECAN1DmaChannelInit(2, 0, &ECAN1RxTxRAMBuffer); // init dma channel 2 for // ECAN peripheral to dma transfer ECAN1Initialize(1, 3, 3, 3, 1, Can_Init_Flags); // initialize ECAN ECAN1SetBufferSize(ECAN1RAMBUFFERSIZE); // set number of rx+tx buffers in DMA RAM ECAN1SelectTxBuffers(0x000F); // select transmit buffers // 0x000F = buffers 0:3 are transmit buffers ECAN1SetOperationMode(_ECAN_MODE_CONFIG,0xFF); // set CONFIGURATION mode ECAN1SetMask(_ECAN_MASK_0, -1, _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_XTD_MSG); // set all mask1 bits to ones ECAN1SetMask(_ECAN_MASK_1, -1, _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_XTD_MSG); // set all mask2 bits to ones ECAN1SetMask(_ECAN_MASK_2, -1, _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_XTD_MSG); // set all mask3 bits to ones ECAN1SetFilter(_ECAN_FILTER_10, 3, _ECAN_MASK_2, _ECAN_RX_BUFFER_7, _ECAN_CONFIG_XTD_MSG); // set id of filter10 to 3, // assign mask2 to filter10 // assign buffer7 to filter10 ECAN1SetOperationMode(_ECAN_MODE_NORMAL, 0xFF); // set NORMAL mode Tx_ID = 12111; // set transmit ID ECAN1Write(Tx_ID, RxTx_Data, 1, Can_Send_Flags); // send initial message while (1) { // endless loop Msg_Rcvd = ECAN1Read(&Rx_ID , RxTx_Data , &Rx_Data_Len, &Can_Rcv_Flags); // receive message if ((Rx_ID == 3u) && Msg_Rcvd) { // if message received check id PORTB = RxTx_Data[0]; // id correct, output data at PORTB RxTx_Data[0]++ ; // increment received data Delay_ms(10); ECAN1Write(Tx_ID, RxTx_Data, 1, Can_Send_Flags); // send incremented data back } } }
Code for the second ECAN node:
#include "__Lib_ECAN1_Defs.h" unsigned int Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags; // can flags unsigned int Rx_Data_Len; // received data length in bytes char RxTx_Data[8]; // can rx/tx data buffer char Msg_Rcvd; // reception flag unsigned long Tx_ID, Rx_ID; // can rx and tx ID void C1Interrupt(void) org 0x005A { // ECAN event iterrupt IFS2bits.C1IF = 0; // clear ECAN interrupt flag if(C1INTFbits.TBIF) { // was it tx interrupt? C1INTFbits.TBIF = 0; // if yes clear tx interrupt flag } if(C1INTFbits.RBIF) { // was it rx interrupt? C1INTFbits.RBIF = 0; // if yes clear rx interrupt flag } } void main() { // Set PLL : Fosc = ((Fin/PLLPRE)*PLLDIV)/PLLPOST ; (((10MHz/2)*32)/4) = 20MHz // refer the pic24 family datasheet for more details CLKDIV &= 0xFFE0; //CLKDIVbits.PLLPRE = 0; PLLFBD = 0x1E; //PLLFBDbits.PLLDIV = 0x1E; CLKDIV &= 0xFF3F; //CLKDIVbits.PLLPOST = 1; CLKDIV |= 0x00C0; AD1PCFGH = 0xFFFF; // AD1PCFGL = 0xFFFF; // all ports digital I/O AD2PCFGL = 0xFFFF; // /* Clear Interrupt Flags */ IFS0 = 0; IFS1 = 0; IFS2 = 0; IFS3 = 0; IFS4 = 0; /* Enable ECAN1 Interrupt */ IEC2bits.C1IE = 1; // enable ECAN1 interrupt C1INTEbits.TBIE = 1; // enable ECAN1 tx interrupt C1INTEbits.RBIE = 1; // enable ECAN1 rx interrupt PORTB = 0; // clear PORTB TRISB = 0; // set PORTB as output, // for received message data displaying Can_Init_Flags = 0; // Can_Send_Flags = 0; // clear flags Can_Rcv_Flags = 0; // Can_Send_Flags = _ECAN_TX_PRIORITY_0 & // Form value to be used _ECAN_TX_XTD_FRAME & // with CANSendMessage _ECAN_TX_NO_RTR_FRAME; Can_Init_Flags = _ECAN_CONFIG_SAMPLE_THRICE & // Form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON & // with CANInitialize _ECAN_CONFIG_XTD_MSG & _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_LINE_FILTER_OFF; ECAN1DmaChannelInit(0, 1, &ECAN1RxTxRAMBuffer); // init dma channel 0 for // dma to ECAN peripheral transfer ECAN1DmaChannelInit(2, 0, &ECAN1RxTxRAMBuffer); // init dma channel 2 for // ECAN peripheral to dma transfer ECAN1Initialize(1, 3, 3, 3, 1, Can_Init_Flags); // initialize ECAN ECAN1SetBufferSize(ECAN1RAMBUFFERSIZE); // set number of rx+tx buffers in DMA RAM ECAN1SelectTxBuffers(0x000F); // select transmit buffers // 0x000F = buffers 0:3 are transmit buffers ECAN1SetOperationMode(_ECAN_MODE_CONFIG,0xFF); // set CONFIGURATION mode ECAN1SetMask(_ECAN_MASK_0, -1, _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_XTD_MSG); // set all mask1 bits to ones ECAN1SetMask(_ECAN_MASK_1, -1, _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_XTD_MSG); // set all mask2 bits to ones ECAN1SetMask(_ECAN_MASK_2, -1, _ECAN_CONFIG_MATCH_MSG_TYPE & _ECAN_CONFIG_XTD_MSG); // set all mask3 bits to ones ECAN1SetFilter(_ECAN_FILTER_10, 12111, _ECAN_MASK_2, _ECAN_RX_BUFFER_7, _ECAN_CONFIG_XTD_MSG); // set id of filter10 to 12111, // assign mask2 to filter10 // assign buffer7 to filter10 ECAN1SetOperationMode(_ECAN_MODE_NORMAL,0xFF); // set NORMAL mode Tx_ID = 3; // set tx ID while (1) { Msg_Rcvd = ECAN1Read(&Rx_ID , RxTx_Data , &Rx_Data_Len, &Can_Rcv_Flags); // receive message if ((Rx_ID == 12111u) && Msg_Rcvd) { // if message received check id PORTB = RxTx_Data[0]; // id correct, output data at PORTB RxTx_Data[0]++ ; // increment received data ECAN1Write(Tx_ID, RxTx_Data, 1, Can_Send_Flags); // send incremented data back } } }
HW Connection
Example of interfacing ECAN transceiver with MCU and bus
What do you think about this topic ? Send us feedback!