ECAN Library
mikroPascal 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.mpas
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 |
function ECANxDmaChannelInit(DmaChannel : word; ChannelDir : word; DmaRamBuffAdd : word) : word; |
---|---|
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 |
procedure ECANxSetOperationMode(mode : word; WAIT : word) ; |
---|---|
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 |
function ECANxGetOperationMode() : word; |
---|---|
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) then begin ... end |
Notes |
|
ECANxInitialize
Prototype |
procedure ECANxInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, ECAN_CONFIG_FLAGS : word); |
---|---|
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 var ecan_config_flags : word; ... ecan_config_flags := _ECAN_CONFIG_SAMPLE_THRICE and // Form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON and // with ECANInitialize _ECAN_CONFIG_XTD_MSG and _ECAN_CONFIG_MATCH_MSG_TYPE and _ECAN_CONFIG_LINE_FILTER_OFF; ECAN1Initialize(1, 3, 3, 3, 1, ecan_config_flags); // initialize the ECAN1 module |
Notes |
|
ECANxSelectTxBuffers
Prototype |
function ECANxSelectTxBuffers(txselect : word) : word; |
---|---|
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 |
procedure ECANxFilterDisable(fltdis : word) ; |
---|---|
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 |
procedure ECANxFilterEnable(flten : word); |
---|---|
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 |
function ECANxSetBufferSize(Ecan1BuffSize : word) : word; |
---|---|
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.mpas header file located in the ECAN project folder. |
ECANxSetBaudRate
Prototype |
procedure ECANxSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, ECAN_CONFIG_FLAGS : word); |
---|---|
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 var ecan_config_flags : word; ... 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 and // Form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON and // with ECAN1SetBaudRate _ECAN_CONFIG_XTD_MSG and _ECAN_CONFIG_MATCH_MSG_TYPE and _ECAN_CONFIG_LINE_FILTER_OFF; ECAN1SetBaudRate(1, 3, 3, 3, 1, ecan_config_flags); // set ECAN1 module baud rate |
Notes |
|
ECANxSetMask
Prototype |
procedure ECANxSetMask(ECAN_MASK : word; val : longint; ECAN_CONFIG_FLAGS : word); |
---|---|
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 |
procedure ECANxSetFilter(ECAN_FILTER : word; val : longint; ECAN_FILTER_MASK : word; ECAN_FILTER_RXBUFF : word; ECAN_CONFIG_FLAGS : word) ; |
---|---|
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 |
function ECANxRead(var id : longint; var data: array[8] of byte; var dataLen : word; var ECAN_RX_MSG_FLAGS : word) : word; |
---|---|
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. var msg_rcvd, rx_flags, data_len : word; data : array[8] of byte; msg_id : longint; ... 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)) then begin ... end; |
Notes |
|
ECANxWrite
Prototype |
function ECANxWrite(id : longint; var Data : array[8] of byte; DataLen, ECAN_TX_MSG_FLAGS : word) : word; |
---|---|
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 var tx_flags : word; data : array[8] of byte; msg_id : longint; ... 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 and _ECAN_TX_XTD_FRAME and _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 _ECAN_MODE_BITS : word = 0x00E0; // Use this to access opmode bits _ECAN_MODE_NORMAL : word = 0x00; _ECAN_MODE_DISABLE : word = 0x01; _ECAN_MODE_LOOP : word = 0x02; _ECAN_MODE_LISTEN : word = 0x03; _ECAN_MODE_CONFIG : word = 0x04; _ECAN_MODE_LISTEN_ALL : word = 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 _ECAN_CONFIG_DEFAULT : word = 0xFF; // 11111111 _ECAN_CONFIG_PHSEG2_PRG_BIT : word = 0x01; _ECAN_CONFIG_PHSEG2_PRG_ON : word = 0xFF; // XXXXXXX1 _ECAN_CONFIG_PHSEG2_PRG_OFF : word = 0xFE; // XXXXXXX0 _ECAN_CONFIG_LINE_FILTER_BIT : word = 0x02; _ECAN_CONFIG_LINE_FILTER_ON : word = 0xFF; // XXXXXX1X _ECAN_CONFIG_LINE_FILTER_OFF : word = 0xFD; // XXXXXX0X _ECAN_CONFIG_SAMPLE_BIT : word = 0x04; _ECAN_CONFIG_SAMPLE_ONCE : word = 0xFF; // XXXXX1XX _ECAN_CONFIG_SAMPLE_THRICE : word = 0xFB; // XXXXX0XX _ECAN_CONFIG_MSG_TYPE_BIT : word = 0x08; _ECAN_CONFIG_STD_MSG : word = 0xFF; // XXXX1XXX _ECAN_CONFIG_XTD_MSG : word = 0xF7; // XXXX0XXX _ECAN_CONFIG_MATCH_TYPE_BIT : word = 0x20; _ECAN_CONFIG_ALL_VALID_MSG : word = 0xDF; // XX0XXXXX _ECAN_CONFIG_MATCH_MSG_TYPE : word = 0xFF; // XX1XXXXX
You may use bitwise and
to form config word out of these values. For example:
init := _ECAN_CONFIG_SAMPLE_THRICE and _ECAN_CONFIG_PHSEG2_PRG_ON and _ECAN_CONFIG_STD_MSG and _ECAN_CONFIG_MATCH_MSG_TYPE and _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 _ECAN_TX_PRIORITY_BITS : word = 0x03; _ECAN_TX_PRIORITY_0 : word = 0xFC; // XXXXXX00 _ECAN_TX_PRIORITY_1 : word = 0xFD; // XXXXXX01 _ECAN_TX_PRIORITY_2 : word = 0xFE; // XXXXXX10 _ECAN_TX_PRIORITY_3 : word = 0xFF; // XXXXXX11 _ECAN_TX_FRAME_BIT : word = 0x08; _ECAN_TX_STD_FRAME : word = 0xFF; // XXXXX1XX _ECAN_TX_XTD_FRAME : word = 0xF7; // XXXXX0XX _ECAN_TX_RTR_BIT : word = 0x40; _ECAN_TX_NO_RTR_FRAME : word = 0xFF; // X1XXXXXX _ECAN_TX_RTR_FRAME : word = 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 and _ECAN_TX_XTD_FRAME and _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 _ECAN_RX_FILTER_BITS : word = 0x000F; // Use this to access filter bits _ECAN_RX_FILTER_0 : word = 0x00; // filter0 match _ECAN_RX_FILTER_1 : word = 0x01; // filter1 match _ECAN_RX_FILTER_2 : word = 0x02; // ... _ECAN_RX_FILTER_3 : word = 0x03; _ECAN_RX_FILTER_4 : word = 0x04; _ECAN_RX_FILTER_5 : word = 0x05; _ECAN_RX_FILTER_6 : word = 0x06; _ECAN_RX_FILTER_7 : word = 0x07; _ECAN_RX_FILTER_8 : word = 0x08; _ECAN_RX_FILTER_9 : word = 0x09; _ECAN_RX_FILTER_10 : word = 0x0A; _ECAN_RX_FILTER_11 : word = 0x0B; _ECAN_RX_FILTER_12 : word = 0x0C; _ECAN_RX_FILTER_13 : word = 0x0D; _ECAN_RX_FILTER_14 : word = 0x0E; // ... _ECAN_RX_FILTER_15 : word = 0x0F; // filter15 match _ECAN_RX_OVERFLOW : word = 0x10; // Set if Overflowed else cleared _ECAN_RX_INVALID_MSG : word = 0x20; // Set if invalid else cleared _ECAN_RX_XTD_FRAME : word = 0x40; // Set if XTD message else cleared _ECAN_RX_RTR_FRAME : word = 0x80; // Set if RTR message else cleared
You may use bitwise and
to extract received message status. For example:
if (MsgFlag and _ECAN_RX_OVERFLOW <> 0) then begin ... // Receiver overflow has occurred. // We have lost our previous message. end
ECAN_MASK Constants
The ECAN_MASK
constants define mask codes. The routine ECANxSetMask expect one of these as their argument:
const _ECAN_MASK_0 : word = 0; _ECAN_MASK_1 : word = 1; _ECAN_MASK_2 : word = 2;
ECAN_FILTER Constants
The ECAN_FILTER
constants define filter codes. The routine ECANxSetFilter expect one of these as their argument:
const _ECAN_FILTER_0 : word = 0; _ECAN_FILTER_1 : word = 1; _ECAN_FILTER_2 : word = 2; _ECAN_FILTER_3 : word = 3; _ECAN_FILTER_4 : word = 4; _ECAN_FILTER_5 : word = 5; _ECAN_FILTER_6 : word = 6; _ECAN_FILTER_7 : word = 7; _ECAN_FILTER_8 : word = 8; _ECAN_FILTER_9 : word = 9; _ECAN_FILTER_10 : word = 10; _ECAN_FILTER_11 : word = 11; _ECAN_FILTER_12 : word = 12; _ECAN_FILTER_13 : word = 13; _ECAN_FILTER_14 : word = 14; _ECAN_FILTER_15 : word = 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 _ECAN_RX_BUFFER_0 : word = 0, _ECAN_RX_BUFFER_1 : word = 1, _ECAN_RX_BUFFER_2 : word = 2, _ECAN_RX_BUFFER_3 : word = 3, _ECAN_RX_BUFFER_4 : word = 4, _ECAN_RX_BUFFER_5 : word = 5, _ECAN_RX_BUFFER_6 : word = 6, _ECAN_RX_BUFFER_7 : word = 7, _ECAN_RX_BUFFER_8 : word = 8, _ECAN_RX_BUFFER_9 : word = 9, _ECAN_RX_BUFFER_10 : word = 10, _ECAN_RX_BUFFER_11 : word = 11, _ECAN_RX_BUFFER_12 : word = 12, _ECAN_RX_BUFFER_13 : word = 13, _ECAN_RX_BUFFER_14 : word = 14, _ECAN_RX_BUFFER_15 : word = 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:
program ECan_1st; uses ECAN_Defs; var Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags : word; // can flags Rx_Data_Len : word; // received data length in bytes RxTx_Data : array[8] of byte; // can rx/tx data buffer Msg_Rcvd : word; // reception flag Rx_ID : longint; const ID_1st : longint = 12111; const ID_2nd : longint = 3; // node IDs procedure C1Interrupt(); org 0x005A; // ECAN event iterrupt begin IFS2.C1IF := 0; // clear ECAN interrupt flag if(C1INTF.TBIF <> 0) then // was it tx interrupt? C1INTF.TBIF := 0; // if yes clear tx interrupt flag if(C1INTF.RBIF <> 0) then // was it rx interrupt? C1INTF.RBIF := 0; // if yes clear rx interrupt flag end; begin // Set PLL : Fosc = ((Fin/PLLPRE)*PLLDIV)/PLLPOST ; (((10MHz/2)*32)/4) = 20MHz // refer the family datasheet for more details CLKDIV := CLKDIV and 0xFFE0; //CLKDIVbits.PLLPRE = 0; PLLFBD := 0x1E; //PLLFBDbits.PLLDIV = 0x1E; CLKDIV := CLKDIV and 0xFF3F; //CLKDIVbits.PLLPOST = 1; CLKDIV := CLKDIV or 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 *} IEC2.C1IE := 1; // enable ECAN1 interrupts C1INTE.TBIE := 1; // enable ECAN1 tx interrupt C1INTE.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 and // form value to be used _ECAN_TX_XTD_FRAME and // with CANSendMessage _ECAN_TX_NO_RTR_FRAME; Can_Init_Flags := _ECAN_CONFIG_SAMPLE_THRICE and // form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON and // with CANInitialize _ECAN_CONFIG_XTD_MSG and _ECAN_CONFIG_MATCH_MSG_TYPE and _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 and _ECAN_CONFIG_XTD_MSG); // set all mask1 bits to ones ECAN1SetMask(_ECAN_MASK_1, -1, _ECAN_CONFIG_MATCH_MSG_TYPE and _ECAN_CONFIG_XTD_MSG); // set all mask2 bits to ones ECAN1SetMask(_ECAN_MASK_2, -1, _ECAN_CONFIG_MATCH_MSG_TYPE and _ECAN_CONFIG_XTD_MSG); // set all mask3 bits to ones ECAN1SetFilter(_ECAN_FILTER_10, ID_2nd, _ECAN_MASK_2, _ECAN_RX_BUFFER_7, _ECAN_CONFIG_XTD_MSG); // set id of filter10 to 2nd node ID // assign mask2 to filter10 // assign buffer7 to filter10 ECAN1SetOperationMode(_ECAN_MODE_NORMAL, 0xFF); // set NORMAL mode ECAN1Write(ID_1st, RxTx_Data, 1, Can_Send_Flags); // send initial message while TRUE do // endless loop begin Msg_Rcvd := ECAN1Read(Rx_ID , RxTx_Data , Rx_Data_Len, Can_Rcv_Flags); // receive message if ((Rx_ID = ID_2nd) and (Msg_Rcvd <> 0)) <> 0 then // if message received check id begin PORTB := RxTx_Data[0]; // id correct, output data at PORTB Inc(RxTx_Data[0]); Delay_ms(10); ECAN1Write(ID_1st, RxTx_Data, 1, Can_Send_Flags); // send incremented data back end; end; end.
Code for the second ECAN node:
program ECAN_2nd; uses ECan_Defs; var Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags : word; // can flags Rx_Data_Len : word; // received data length in bytes RxTx_Data : array[8] of byte; // can rx/tx data buffer Msg_Rcvd : word; // reception flag Rx_ID : longint; // can rx and tx ID const ID_1st : longint = 12111; const ID_2nd : longint = 3; // node IDs procedure C1Interrupt(); org 0x005A; // ECAN event iterrupt begin IFS2.C1IF := 0; // clear ECAN interrupt flag if(C1INTF.TBIF <> 0) then // was it tx interrupt? C1INTF.TBIF := 0; // if yes clear tx interrupt flag if(C1INTF.RBIF <> 0) then // was it rx interrupt? C1INTF.RBIF := 0; // if yes clear rx interrupt flag end; begin // Set PLL : Fosc = ((Fin/PLLPRE)*PLLDIV)/PLLPOST ; (((10MHz/2)*32)/4) = 20MHz // refer the family datasheet for more details CLKDIV := CLKDIV and 0xFFE0; //CLKDIVbits.PLLPRE = 0; PLLFBD := 0x1E; //PLLFBDbits.PLLDIV = 0x1E; CLKDIV := CLKDIV and 0xFF3F; //CLKDIVbits.PLLPOST = 1; CLKDIV := CLKDIV or 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 *} IEC2.C1IE := 1; // enable ECAN1 interrupts C1INTE.TBIE := 1; // enable ECAN1 tx interrupt C1INTE.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 and // Form value to be used _ECAN_TX_XTD_FRAME and // with CANSendMessage _ECAN_TX_NO_RTR_FRAME; Can_Init_Flags := _ECAN_CONFIG_SAMPLE_THRICE and // Form value to be used _ECAN_CONFIG_PHSEG2_PRG_ON and // with CANInitialize _ECAN_CONFIG_XTD_MSG and _ECAN_CONFIG_MATCH_MSG_TYPE and _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 and _ECAN_CONFIG_XTD_MSG); // set all mask1 bits to ones ECAN1SetMask(_ECAN_MASK_1, -1, _ECAN_CONFIG_MATCH_MSG_TYPE and _ECAN_CONFIG_XTD_MSG); // set all mask2 bits to ones ECAN1SetMask(_ECAN_MASK_2, -1, _ECAN_CONFIG_MATCH_MSG_TYPE and _ECAN_CONFIG_XTD_MSG); // set all mask3 bits to ones ECAN1SetFilter(_ECAN_FILTER_10, ID_1st, _ECAN_MASK_2, _ECAN_RX_BUFFER_7, _ECAN_CONFIG_XTD_MSG); // set id of filter10 to 1st node ID // assign buffer7 to filter10 ECAN1SetOperationMode(_ECAN_MODE_NORMAL,0xFF); // set NORMAL mode while TRUE do begin Msg_Rcvd := ECAN1Read(Rx_ID, RxTx_Data, Rx_Data_Len, Can_Rcv_Flags); // receive message if ((Rx_ID = ID_1st) and (Msg_Rcvd <> 0) <> 0) then // if message received check id begin PORTB := RxTx_Data[0]; // id correct, output data at PORTB Inc(RxTx_Data[0]); // increment received data ECAN1Write(ID_2nd, RxTx_Data, 1, Can_Send_Flags); // send incremented data back end; end; end.
HW Connection
Example of interfacing ECAN transceiver with MCU and bus
What do you think about this topic ? Send us feedback!