#if defined(__dsPIC33F__)
#include <p33Fxxxx.h>
#elif defined(__PIC24H__)
#include <p24hxxxx.h>
#endif
#include "ecan.h"
#include "delay.h"
#include <stdio.h>
#include <ctype.h>
#include "serialio.h"
#include "timer.h"
#include "uart2.h"
mID canTxMessage;
mID canRxMessage;
/* Define ECAN Message Buffers */
ECAN1MSGBUF ecan1msgBuf __attribute__((space(dma),aligned(ECAN1_MSG_BUF_LENGTH*16)));
void CANBUSinitialise(void)
{
printf("\n\nECAN test \n");
/* initialise other modules */
_C1RXR = 24;
_RP23R = 0x10;
initECAN();
initDMAECAN();
/* Enable ECAN1 Interrupt */
IEC2bits.C1IE=1;
/* enable Transmit interrupt */
C1INTEbits.TBIE=1;
/* Enable Receive interrupt */
C1INTEbits.RBIE=1;
}
void putstring(char *string, int length)
{
int i;
for(i=0;i<length;i++)
{
UART2PutChar(string[i]);
}
}
/******************************************************************************
*
* Function: puts_ecanTx
* Description: puts the sent message on the LCD module
*
* Arguments: *message: a pointer to the message structure
* containing all the information about the message
* Author: Jatinder Gharoo
*
*
******************************************************************************/
void puts_ecanTx(mID *message)
{
if(m->frame_type==CAN_FRAME_EXT)
printf("TX XTD %lx\n", m->id);
else
printf("TX STD %lx\n", m->id);
}
/******************************************************************************
*
* Function: puts_ecanRx
* Description: puts the received message on the LCD module
*
* Arguments: *message: a pointer to the message structure
* containing all the information about the message
* Author: Jatinder Gharoo
*
*
******************************************************************************/
void puts_ecanRx(mID *message)
{
if(m->frame_type==CAN_FRAME_EXT)
printf("RX XTD %lx\n", m->id);
else
printf("RX STD %lx\n", m->id);
}
int CANBUSreceived(void)
{
/* check to see when a message is received and move the message
into RAM and parse the message */
if(canRxMessage.buffer_status==CAN_BUF_FULL)
{
printf("recived CAN message\n");
rxECAN(&canRxMessage);
/* display the message on LCD */
puts_ecanRx(&canRxMessage);
/* reset the flag when done */
canRxMessage.buffer_status=CAN_BUF_EMPTY;
}
return 1;
}
extern unsigned long int CANBUSfilter, CANBUSmask;
void testCanbus(void)
{
while(1)
{
printf("CANBUS tests\n"
" S: send a message \n"
" F: set receive filter\n"
" M: set receive filtermask\n"
" enter command ?");
fflush(stdout);
UART2flush();
while(1)
{
CANBUSreceived();
if(UART2IsPressed())break;
}
switch (toupper(UART2GetChar()))
{
case 'S': printf("\nenter ID ?");
/* configure and send a message */
canTxMessage.message_type=CAN_MSG_DATA;
//canTxMessage.message_type=CAN_MSG_RTR;
canTxMessage.frame_type=CAN_FRAME_EXT;
//canTxMessage.frame_type=CAN_FRAME_STD;
canTxMessage.buffer=0;
canTxMessage.id=readLongIntHex();
printf("\nenter data (max 16 hex numbers) ? ");
readHexChars(canTxMessage.data, 16);
/*canTxMessage.data[0]=0x55;
canTxMessage.data[1]=0x55;
canTxMessage.data[2]=0x55;
canTxMessage.data[3]=0x55;
canTxMessage.data[4]=0x55;
canTxMessage.data[5]=0x55;
canTxMessage.data[6]=0x55;
canTxMessage.data[7]=0x55;*/
canTxMessage.data_length=8;
/* Delay for a second */
// Delay(Delay_1S_Cnt);
printf("\nsend CAN message\n");
/* send a CAN message */
sendECAN(&canTxMessage);
break;
case 'F': printf("\nenter FILTER ?");
CANBUSfilter=readLongIntHex();
initECAN();
break;
case 'M': printf("\nenter MASK ?");
CANBUSmask=readLongIntHex();
initECAN();
break; }
printf("\n");
}
}
/* Interrupt Service Routine 1 */
/* No fast context save, and no variables stacked */
void __attribute__((interrupt,no_auto_psv))_C1Interrupt(void)
{
/* check to see if the interrupt is caused by receive */
if(C1INTFbits.RBIF)
{
/* check to see if buffer 1 is full */
if(C1RXFUL1bits.RXFUL1)
{
/* set the buffer full flag and the buffer received flag */
canRxMessage.buffer_status=CAN_BUF_FULL;
canRxMessage.buffer=1;
}
/* check to see if buffer 2 is full */
else if(C1RXFUL1bits.RXFUL2)
{
/* set the buffer full flag and the buffer received flag */
canRxMessage.buffer_status=CAN_BUF_FULL;
canRxMessage.buffer=2;
}
/* check to see if buffer 3 is full */
else if(C1RXFUL1bits.RXFUL3)
{
/* set the buffer full flag and the buffer received flag */
canRxMessage.buffer_status=CAN_BUF_FULL;
canRxMessage.buffer=3;
}
else;
/* clear flag */
C1INTFbits.RBIF = 0;
}
else if(C1INTFbits.TBIF)
{
puts_ecanTx(&canTxMessage);
/* clear flag */
C1INTFbits.TBIF = 0;
}
else;
/* clear interrupt flag */
IFS2bits.C1IF=0;
}
ecan1WriteTxMsgBufId(0,0x1FFEFFFF,1,0);
ecan1WriteTxMsgBufData(0,8,0x1111,0x2222,0x3333,0x4444);
ecan2WriteTxMsgBufId(0,0x1FFEFFFF,1,0);
ecan2WriteTxMsgBufData(0,8,0xaaaa,0xbbbb,0xcccc,0xdddd);
/**********************************************************************
* © 2005 Microchip Technology Inc.
*
* FileName: main.c
* Dependencies: Header (.h) files if applicable, see below
* Processor: dsPIC33Fxxxx
* Compiler: MPLAB® C30 v3.00 or higher
*
* SOFTWARE LICENSE AGREEMENT:
* Microchip Technology Incorporated ("Microchip") retains all ownership and
* intellectual property rights in the code accompanying this message and in all
* derivatives hereto. You may use this code, and any derivatives created by
* any person or entity by or on your behalf, exclusively with Microchip's
* proprietary products. Your acceptance and/or use of this code constitutes
* agreement to the terms and conditions of this notice.
*
* CODE ACCOMPANYING THIS MESSAGE IS SUPPLIED BY MICROCHIP "AS IS". NO
* WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS CODE, ITS INTERACTION WITH MICROCHIP'S
* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
*
* YOU ACKNOWLEDGE AND AGREE THAT, IN NO EVENT, SHALL MICROCHIP BE LIABLE, WHETHER
* IN CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE OR BREACH OF STATUTORY DUTY),
* STRICT LIABILITY, INDEMNITY, CONTRIBUTION, OR OTHERWISE, FOR ANY INDIRECT, SPECIAL,
* PUNITIVE, EXEMPLARY, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR EXPENSE OF
* ANY KIND WHATSOEVER RELATED TO THE CODE, HOWSOEVER CAUSED, EVEN IF MICROCHIP HAS BEEN
* ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWABLE BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO
* THIS CODE, SHALL NOT EXCEED THE PRICE YOU PAID DIRECTLY TO MICROCHIP SPECIFICALLY TO
* HAVE THIS CODE DEVELOPED.
*
* You agree that you are solely responsible for testing the code and
* determining its suitability. Microchip has no obligation to modify, test,
* certify, or support the code.
*
* REVISION HISTORY:
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Author Date Comments on this revision
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Vinaya Skanda 10/18/06 First release of source file
* Vinaya Skanda 07/25/07 Updates from Joe Supinsky and Jatinder Gharoo incorporated
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ADDITIONAL NOTES:
* This code is tested on Explorer-16 board with ECAN PICTail Card.
* The device used is dsPIC33FJ256GP710 controller
*
* The Processor starts with the External Crystal without PLL enabled and then the Clock is switched to PLL Mode.
*************************************************************************************************/
#if defined(__dsPIC33F__)
#include "p33fxxxx.h"
#elif defined(__PIC24H__)
#include "p24hxxxx.h"
#endif
#include <ECAN1Config.h>
#include <ECAN2Config.h>
#include <common.h>
// Macros for Configuration Fuse Registers
_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT);
// Clock Switching is enabled and Fail Safe Clock Monitor is disabled
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystanl
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software
// (LPRC can be disabled by clearing SWDTEN bit in RCON register
// Define ECAN Message Buffers
ECAN1MSGBUF ecan1msgBuf __attribute__((space(dma),aligned(ECAN1_MSG_BUF_LENGTH*16)));
ECAN2MSGBUF ecan2msgBuf __attribute__((space(dma),aligned(ECAN2_MSG_BUF_LENGTH*16)));
// CAN Messages in RAM
mID rx_ecan1message[10];
mID rx_ecan2message[10];
int ecan1_in=0, ecan1_out=0, ecan2_in=0, ecan2_out=0; // array indexes
// Prototype Declaration
void oscConfig(void);
void clearIntrflags(void);
void ecan1WriteMessage(void);
void ecan2WriteMessage(void);
void rxECAN1(mID *message);
void rxECAN2(mID *message);
int main(void)
{
/* Configure Oscillator Clock Source */
oscConfig();
UART2Init(); // Setup the UART
printf("\n\ndsPIC33 test program\n");
// printf("Fosc %ld\n", Fosc);
/* Clear Interrupt Flags */
clearIntrflags();
/* ECAN1 Initialisation
Configure DMA Channel 0 for ECAN1 Transmit
Configure DMA Channel 2 for ECAN1 Receive */
ecan1Init();
dma0init();
dma2init();
/* Enable ECAN1 Interrupt */
IEC2bits.C1IE = 1;
C1INTEbits.TBIE = 1;
C1INTEbits.RBIE = 1;
/* ECAN2 Initialisation
Configure DMA Channel 1 for ECAN2 Transmit
Configure DMA Channel 3 for ECAN2 Receive */
ecan2Init();
dma1init();
dma3init();
/* Enable ECAN2 Interrupt */
IEC3bits.C2IE = 1;
C2INTEbits.TBIE = 1;
C2INTEbits.RBIE = 1;
C2TR01CONbits.TXREQ0=1;
/* Write a Message in ECAN1 Transmit Buffer
Request Message Transmission */
// ecan1WriteMessage();
// C1TR01CONbits.TXREQ0=1;
/* Write a Message in ECAN2 Transmit Buffer
Request Message Transmission */
ecan2WriteMessage();
C2TR01CONbits.TXREQ0=1;
/* Write a Message in ECAN1 Transmit Buffer
Request Message Transmission */
ecan1WriteMessage();
C1TR01CONbits.TXREQ0=1;
/* Loop infinitely */
while (1)
{
if(ecan1_out < ecan1_in)
{
int i;
printf("\nECAN1 received message ecan1_out %d ecan1_in %d - \n ID %lx data ",
ecan1_out, ecan1_in, rx_ecan1message[ecan1_out].id);
for(i=0;i<8;i++)printf("%x", rx_ecan1message[ecan1_out].data[i]);
ecan1_out++;
}
if(ecan2_out < ecan2_in)
{
int i;
printf("\nECAN2 received message ecan2_out %d ecan2_in %d - - \n ID %lx data ",
ecan2_out, ecan2_in, rx_ecan1message[ecan2_out].id);
for(i=0;i<8;i++)printf("%x", rx_ecan2message[ecan2_out].data[i]);
ecan2_out++;
}
}
}
/* ECAN1 buffer loaded with Identifiers and Data */
void ecan1WriteMessage(void){
/* Writing the message for Transmission
ecan1WriteTxMsgBufId(unsigned int buf, long txIdentifier, unsigned int ide, unsigned int remoteTransmit);
ecan1WriteTxMsgBufData(unsigned int buf, unsigned int dataLength, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4);
buf -> Transmit Buffer number
txIdentifier -> SID<10:0> : EID<17:0>
ide = 0 -> Message will transmit standard identifier
ide = 1 -> Message will transmit extended identifier
remoteTransmit = 0 -> Normal message
remoteTransmit = 1 -> Message will request remote transmission
dataLength -> Data length can be from 0 to 8 bytes
data1, data2, data3, data4 -> Data words (2 bytes) each
*/
ecan1WriteTxMsgBufId(0,0x1FFEFFFF,1,0);
ecan1WriteTxMsgBufData(0,8,0x1111,0x2222,0x3333,0x4444);
}
/* ECAN2 buffer loaded with Identifiers and Data */
void ecan2WriteMessage(void){
/* Writing the message for Transmission
ecan2WriteTxMsgBufId(unsigned int buf, long txIdentifier, unsigned int ide, unsigned int remoteTransmit);
ecan2WriteTxMsgBufData(unsigned int buf, unsigned int dataLength, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4);
buf -> Transmit Buffer Number
txIdentifier -> SID<10:0> : EID<17:0>
ide = 0 -> Message will transmit standard identifier
ide = 1 -> Message will transmit extended identifier
remoteTransmit = 0 -> Normal message
remoteTransmit = 1 -> Message will request remote transmission
dataLength -> Data length can be from 0 to 8 bytes
data1, data2, data3, data4 -> Data words (2 bytes) each
*/
ecan2WriteTxMsgBufId(0,0x1FFEFFFF,1,0);
ecan2WriteTxMsgBufData(0,8,0xaaaa,0xbbbb,0xcccc,0xdddd);
}
/******************************************************************************
*
* Function: rxECAN1
* Description: moves the message from the DMA memory to RAM
*
* Arguments: *message: a pointer to the message structure in RAM
* that will store the message.
* Author: Jatinder Gharoo
*
*
******************************************************************************/
void rxECAN1(mID *message)
{
unsigned int ide=0;
unsigned int srr=0;
unsigned long id=0,d;
/*
Standard Message Format:
Word0 : 0bUUUx xxxx xxxx xxxx
|____________|||
SID10:0 SRR IDE(bit 0)
Word1 : 0bUUUU xxxx xxxx xxxx
|____________|
EID17:6
Word2 : 0bxxxx xxx0 UUU0 xxxx
|_____|| |__|
EID5:0 RTR DLC
word3-word6: data bytes
word7: filter hit code bits
Substitute Remote Request Bit
SRR-> "0" Normal Message
"1" Message will request remote transmission
Extended Identifier Bit
IDE-> "0" Message will transmit standard identifier
"1" Message will transmit extended identifier
Remote Transmission Request Bit
RTR-> "0" Message transmitted is a normal message
"1" Message transmitted is a remote message
*/
/* read word 0 to see the message type */
ide=ecan1msgBuf[m->buffer][0] & 0x0001;
srr=ecan1msgBuf[m->buffer][0] & 0x0002;
/* check to see what type of message it is */
/* message is standard identifier */
if(ide==0)
{
m->id=(ecan1msgBuf[m->buffer][0] & 0x1FFC) >> 2;
m->frame_type=CAN_FRAME_STD;
}
/* mesage is extended identifier */
else
{
id=ecan1msgBuf[m->buffer][0] & 0x1FFC;
m->id=id << 16;
id=ecan1msgBuf[m->buffer][1] & 0x0FFF;
m->id=m->id+(id << 6);
id=(ecan1msgBuf[m->buffer][2] & 0xFC00) >> 10;
m->id=m->id+id;
m->frame_type=CAN_FRAME_EXT;
}
/* check to see what type of message it is */
/* RTR message */
if(srr==1)
{
m->message_type=CAN_MSG_RTR;
}
/* normal message */
else
{
m->message_type=CAN_MSG_DATA;
m->data[0]=(unsigned char)ecan1msgBuf[m->buffer][3];
m->data[1]=(unsigned char)((ecan1msgBuf[m->buffer][3] & 0xFF00) >> 8);
m->data[2]=(unsigned char)ecan1msgBuf[m->buffer][4];
m->data[3]=(unsigned char)((ecan1msgBuf[m->buffer][4] & 0xFF00) >> 8);
m->data[4]=(unsigned char)ecan1msgBuf[m->buffer][5];
m->data[5]=(unsigned char)((ecan1msgBuf[m->buffer][5] & 0xFF00) >> 8);
m->data[6]=(unsigned char)ecan1msgBuf[m->buffer][6];
m->data[7]=(unsigned char)((ecan1msgBuf[m->buffer][6] & 0xFF00) >> 8);
m->data_length=(unsigned char)(ecan1msgBuf[m->buffer][2] & 0x000F);
}
}
/******************************************************************************
*
* Function: rxECAN2
* Description: moves the message from the DMA memory to RAM
*
* Arguments: *message: a pointer to the message structure in RAM
* that will store the message.
* Author: Jatinder Gharoo
*
*
******************************************************************************/
void rxECAN2(mID *message)
{
unsigned int ide=0;
unsigned int srr=0;
unsigned long id=0,a1;
/*
Standard Message Format:
Word0 : 0bUUUx xxxx xxxx xxxx
|____________|||
SID10:0 SRR IDE(bit 0)
Word1 : 0bUUUU xxxx xxxx xxxx
|____________|
EID17:6
Word2 : 0bxxxx xxx0 UUU0 xxxx
|_____|| |__|
EID5:0 RTR DLC
word3-word6: data bytes
word7: filter hit code bits
Substitute Remote Request Bit
SRR-> "0" Normal Message
"1" Message will request remote transmission
Extended Identifier Bit
IDE-> "0" Message will transmit standard identifier
"1" Message will transmit extended identifier
Remote Transmission Request Bit
RTR-> "0" Message transmitted is a normal message
"1" Message transmitted is a remote message
*/
/* read word 0 to see the message type */
ide=ecan2msgBuf[m->buffer][0] & 0x0001;
srr=ecan2msgBuf[m->buffer][0] & 0x0002;
/* check to see what type of message it is */
/* message is standard identifier */
if(ide==0)
{
m->id=(ecan2msgBuf[m->buffer][0] & 0x1FFC) >> 2;
m->frame_type=CAN_FRAME_STD;
}
/* mesage is extended identifier */
else
{
id=ecan2msgBuf[m->buffer][0] & 0x1FFC;
m->id=id << 16;
id=ecan2msgBuf[m->buffer][1] & 0x0FFF;
m->id=m->id+(id << 6);
id=(ecan2msgBuf[m->buffer][2] & 0xFC00) >> 10;
m->id=m->id+id;
m->frame_type=CAN_FRAME_EXT;
}
/* check to see what type of message it is */
/* RTR message */
if(srr==1)
{
m->message_type=CAN_MSG_RTR;
}
/* normal message */
else
{
m->message_type=CAN_MSG_DATA;
m->data[0]=(unsigned char)ecan2msgBuf[m->buffer][3];
m->data[1]=(unsigned char)((ecan2msgBuf[m->buffer][3] & 0xFF00) >> 8);
m->data[2]=(unsigned char)ecan2msgBuf[m->buffer][4];
m->data[3]=(unsigned char)((ecan2msgBuf[m->buffer][4] & 0xFF00) >> 8);
m->data[4]=(unsigned char)ecan2msgBuf[m->buffer][5];
m->data[5]=(unsigned char)((ecan2msgBuf[m->buffer][5] & 0xFF00) >> 8);
m->data[6]=(unsigned char)ecan2msgBuf[m->buffer][6];
m->data[7]=(unsigned char)((ecan2msgBuf[m->buffer][6] & 0xFF00) >> 8);
m->data_length=(unsigned char)(ecan2msgBuf[m->buffer][2] & 0x000F);
}
}
void clearIntrflags(void){
/* Clear Interrupt Flags */
IFS0=0;
IFS1=0;
IFS2=0;
IFS3=0;
IFS4=0;
}
void oscConfig(void){
/* Configure Oscillator to operate the device at 40Mhz
Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
Fosc= 8M*40/(2*2)=80Mhz for 8M input clock */
PLLFBD=38; /* M=40 */
CLKDIVbits.PLLPOST=0; /* N1=2 */
CLKDIVbits.PLLPRE=0; /* N2=2 */
OSCTUN=0; /* Tune FRC oscillator, if FRC is used */
/* Disable Watch Dog Timer */
RCONbits.SWDTEN=0;
/* Clock switch to incorporate PLL*/
__builtin_write_OSCCONH(0x03); // Initiate Clock Switch to Primary
// Oscillator with PLL (NOSC=0b011)
__builtin_write_OSCCONL(0x01); // Start clock switching
while (OSCCONbits.COSC != 0b011); // Wait for Clock switch to occur
/* Wait for PLL to lock */
while(OSCCONbits.LOCK!=1) {};
}
void __attribute__((interrupt))_C1Interrupt(void)
//void __attribute__((interrupt, no_auto_psv))_C1Interrupt(void)
{
IFS2bits.C1IF = 0; // clear interrupt flag
if(C1INTFbits.TBIF)
{
C1INTFbits.TBIF = 0;
}
if(C1INTFbits.RBIF)
{
// read the message
if(C1RXFUL1bits.RXFUL1==1)
{
rx_ecan1message[ecan1_in].buffer=1;
C1RXFUL1bits.RXFUL1=0;
}
rxECAN1(&rx_ecan1message[ecan1_in]);
ecan1_in++;
C1INTFbits.RBIF = 0;
}
}
//void __attribute__((interrupt, no_auto_psv))_C2Interrupt(void)
void __attribute__((interrupt))_C2Interrupt(void)
{
IFS3bits.C2IF = 0; // clear interrupt flag
if(C2INTFbits.TBIF)
{
C2INTFbits.TBIF = 0;
}
if(C2INTFbits.RBIF)
{
// read the message
if(C2RXFUL1bits.RXFUL1==1)
{
rx_ecan2message[ecan2_in].buffer=1;
C2RXFUL1bits.RXFUL1=0;
}
rxECAN2(&rx_ecan2message[ecan2_in]);
ecan2_in++;
C2INTFbits.RBIF = 0;
}
}
//------------------------------------------------------------------------------
// DMA interrupt handlers
//------------------------------------------------------------------------------
void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void)
{
IFS0bits.DMA0IF = 0; // Clear the DMA0 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA1Interrupt(void)
{
IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA2Interrupt(void)
{
IFS1bits.DMA2IF = 0; // Clear the DMA2 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA3Interrupt(void)
{
IFS2bits.DMA3IF = 0; // Clear the DMA3 Interrupt Flag;
}
#if defined(__dsPIC33F__)
#include "p33fxxxx.h"
#elif defined(__PIC24H__)
#include "p24hxxxx.h"
#endif
#include <ECAN1Config.h>
#include <ECAN2Config.h>
#include <common.h>
// Macros for Configuration Fuse Registers
_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT);
// Clock Switching is enabled and Fail Safe Clock Monitor is disabled
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystanl
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software
// (LPRC can be disabled by clearing SWDTEN bit in RCON register
// Define ECAN Message Buffers
ECAN1MSGBUF ecan1msgBuf __attribute__((space(dma),aligned(ECAN1_MSG_BUF_LENGTH*16)));
ECAN2MSGBUF ecan2msgBuf __attribute__((space(dma),aligned(ECAN2_MSG_BUF_LENGTH*16)));
// CAN Messages in RAM
mID rx_ecan1message[10];
mID rx_ecan2message[10];
volatile int ecan1_in=0, ecan1_out=0, ecan2_in=0, ecan2_out=0; // array indexes
volatile int ecan1Transmited=1, ecan2Transmited=1;
// Prototype Declaration
void oscConfig(void);
void clearIntrflags(void);
void ecan1WriteMessage(unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4);
void ecan2WriteMessage(unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4);
void rxECAN1(mID *message);
void rxECAN2(mID *message);
int main(void)
{
/* Configure Oscillator Clock Source */
oscConfig();
UART2Init(); // Setup the UART
printf("\n\ndsPIC33 test program\n");
// printf("Fosc %ld\n", Fosc);
/* Clear Interrupt Flags */
clearIntrflags();
/* ECAN1 Initialisation
Configure DMA Channel 0 for ECAN1 Transmit
Configure DMA Channel 2 for ECAN1 Receive */
ecan1Init();
dma0init();
dma2init();
/* Enable ECAN1 Interrupt */
IEC2bits.C1IE = 1;
C1INTEbits.TBIE = 1;
C1INTEbits.RBIE = 1;
/* ECAN2 Initialisation
Configure DMA Channel 1 for ECAN2 Transmit
Configure DMA Channel 3 for ECAN2 Receive */
ecan2Init();
dma1init();
dma3init();
/* Enable ECAN2 Interrupt */
IEC3bits.C2IE = 1;
C2INTEbits.TBIE = 1;
C2INTEbits.RBIE = 1;
C2TR01CONbits.TXREQ0=1;
/* Write a Message in ECAN1 Transmit Buffer
Request Message Transmission */
// ecan1WriteMessage();
// C1TR01CONbits.TXREQ0=1;
/* Write a Message in ECAN2 Transmit Buffer
Request Message Transmission */
ecan2WriteMessage(0xaaaa,0xbbbb,0xcccc,0xdddd);
// C2TR01CONbits.TXREQ0=1;
/* Write a Message in ECAN1 Transmit Buffer
Request Message Transmission */
ecan1WriteMessage(0x1111,0x2222,0x3333,0x4444);
ecan1WriteMessage(0x5555,0x6666,0x7777,0x8888);
ecan2WriteMessage(0xaaff,0xbbff,0xccff,0xddff);
ecan1WriteMessage(0x1234,0x5678,0x9abc,0xdeff);
/* Loop infinitely */
while (1)
{
if(ecan1_out < ecan1_in)
{
int i;
printf("\nECAN1 received message ecan1_out %d ecan1_in %d - \n ID %lx data ",
ecan1_out, ecan1_in, rx_ecan1message[ecan1_out].id);
for(i=0;i<8;i++)printf("%x", rx_ecan1message[ecan1_out].data[i]);
ecan1_out++;
}
if(ecan2_out < ecan2_in)
{
int i;
printf("\nECAN2 received message ecan2_out %d ecan2_in %d - - \n ID %lx data ",
ecan2_out, ecan2_in, rx_ecan1message[ecan2_out].id);
for(i=0;i<8;i++)printf("%x", rx_ecan2message[ecan2_out].data[i]);
ecan2_out++;
}
}
}
/* ECAN1 buffer loaded with Identifiers and Data */
void ecan1WriteMessage(unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4){
/* Writing the message for Transmission
ecan1WriteTxMsgBufId(unsigned int buf, long txIdentifier, unsigned int ide, unsigned int remoteTransmit);
ecan1WriteTxMsgBufData(unsigned int buf, unsigned int dataLength, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4);
buf -> Transmit Buffer number
txIdentifier -> SID<10:0> : EID<17:0>
ide = 0 -> Message will transmit standard identifier
ide = 1 -> Message will transmit extended identifier
remoteTransmit = 0 -> Normal message
remoteTransmit = 1 -> Message will request remote transmission
dataLength -> Data length can be from 0 to 8 bytes
data1, data2, data3, data4 -> Data words (2 bytes) each
*/
while( !ecan1Transmited) Nop();
ecan1Transmited=0;
ecan1WriteTxMsgBufId(0,0x1FFEFFFF,1,0);
ecan1WriteTxMsgBufData(0,8,data1, data2, data3, data4);
C1TR01CONbits.TXREQ0=1;
}
/* ECAN2 buffer loaded with Identifiers and Data */
void ecan2WriteMessage(unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4){
/* Writing the message for Transmission
ecan2WriteTxMsgBufId(unsigned int buf, long txIdentifier, unsigned int ide, unsigned int remoteTransmit);
ecan2WriteTxMsgBufData(unsigned int buf, unsigned int dataLength, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4);
buf -> Transmit Buffer Number
txIdentifier -> SID<10:0> : EID<17:0>
ide = 0 -> Message will transmit standard identifier
ide = 1 -> Message will transmit extended identifier
remoteTransmit = 0 -> Normal message
remoteTransmit = 1 -> Message will request remote transmission
dataLength -> Data length can be from 0 to 8 bytes
data1, data2, data3, data4 -> Data words (2 bytes) each
*/
while( !ecan2Transmited) Nop();
ecan2Transmited=0;
ecan2WriteTxMsgBufId(0,0x1FFEFFFF,1,0);
ecan2WriteTxMsgBufData(0,8,data1, data2, data3, data4);
C2TR01CONbits.TXREQ0=1;
}
/******************************************************************************
*
* Function: rxECAN1
* Description: moves the message from the DMA memory to RAM
*
* Arguments: *message: a pointer to the message structure in RAM
* that will store the message.
* Author: Jatinder Gharoo
*
*
******************************************************************************/
void rxECAN1(mID *message)
{
unsigned int ide=0;
unsigned int srr=0;
unsigned long id=0,d;
/*
Standard Message Format:
Word0 : 0bUUUx xxxx xxxx xxxx
|____________|||
SID10:0 SRR IDE(bit 0)
Word1 : 0bUUUU xxxx xxxx xxxx
|____________|
EID17:6
Word2 : 0bxxxx xxx0 UUU0 xxxx
|_____|| |__|
EID5:0 RTR DLC
word3-word6: data bytes
word7: filter hit code bits
Substitute Remote Request Bit
SRR-> "0" Normal Message
"1" Message will request remote transmission
Extended Identifier Bit
IDE-> "0" Message will transmit standard identifier
"1" Message will transmit extended identifier
Remote Transmission Request Bit
RTR-> "0" Message transmitted is a normal message
"1" Message transmitted is a remote message
*/
/* read word 0 to see the message type */
ide=ecan1msgBuf[m->buffer][0] & 0x0001;
srr=ecan1msgBuf[m->buffer][0] & 0x0002;
/* check to see what type of message it is */
/* message is standard identifier */
if(ide==0)
{
m->id=(ecan1msgBuf[m->buffer][0] & 0x1FFC) >> 2;
m->frame_type=CAN_FRAME_STD;
}
/* mesage is extended identifier */
else
{
id=ecan1msgBuf[m->buffer][0] & 0x1FFC;
m->id=id << 16;
id=ecan1msgBuf[m->buffer][1] & 0x0FFF;
m->id=m->id+(id << 6);
id=(ecan1msgBuf[m->buffer][2] & 0xFC00) >> 10;
m->id=m->id+id;
m->frame_type=CAN_FRAME_EXT;
}
/* check to see what type of message it is */
/* RTR message */
if(srr==1)
{
m->message_type=CAN_MSG_RTR;
}
/* normal message */
else
{
m->message_type=CAN_MSG_DATA;
m->data[0]=(unsigned char)ecan1msgBuf[m->buffer][3];
m->data[1]=(unsigned char)((ecan1msgBuf[m->buffer][3] & 0xFF00) >> 8);
m->data[2]=(unsigned char)ecan1msgBuf[m->buffer][4];
m->data[3]=(unsigned char)((ecan1msgBuf[m->buffer][4] & 0xFF00) >> 8);
m->data[4]=(unsigned char)ecan1msgBuf[m->buffer][5];
m->data[5]=(unsigned char)((ecan1msgBuf[m->buffer][5] & 0xFF00) >> 8);
m->data[6]=(unsigned char)ecan1msgBuf[m->buffer][6];
m->data[7]=(unsigned char)((ecan1msgBuf[m->buffer][6] & 0xFF00) >> 8);
m->data_length=(unsigned char)(ecan1msgBuf[m->buffer][2] & 0x000F);
}
}
/******************************************************************************
*
* Function: rxECAN2
* Description: moves the message from the DMA memory to RAM
*
* Arguments: *message: a pointer to the message structure in RAM
* that will store the message.
* Author: Jatinder Gharoo
*
*
******************************************************************************/
void rxECAN2(mID *message)
{
unsigned int ide=0;
unsigned int srr=0;
unsigned long id=0,a1;
/*
Standard Message Format:
Word0 : 0bUUUx xxxx xxxx xxxx
|____________|||
SID10:0 SRR IDE(bit 0)
Word1 : 0bUUUU xxxx xxxx xxxx
|____________|
EID17:6
Word2 : 0bxxxx xxx0 UUU0 xxxx
|_____|| |__|
EID5:0 RTR DLC
word3-word6: data bytes
word7: filter hit code bits
Substitute Remote Request Bit
SRR-> "0" Normal Message
"1" Message will request remote transmission
Extended Identifier Bit
IDE-> "0" Message will transmit standard identifier
"1" Message will transmit extended identifier
Remote Transmission Request Bit
RTR-> "0" Message transmitted is a normal message
"1" Message transmitted is a remote message
*/
/* read word 0 to see the message type */
ide=ecan2msgBuf[m->buffer][0] & 0x0001;
srr=ecan2msgBuf[m->buffer][0] & 0x0002;
/* check to see what type of message it is */
/* message is standard identifier */
if(ide==0)
{
m->id=(ecan2msgBuf[m->buffer][0] & 0x1FFC) >> 2;
m->frame_type=CAN_FRAME_STD;
}
/* mesage is extended identifier */
else
{
id=ecan2msgBuf[m->buffer][0] & 0x1FFC;
m->id=id << 16;
id=ecan2msgBuf[m->buffer][1] & 0x0FFF;
m->id=m->id+(id << 6);
id=(ecan2msgBuf[m->buffer][2] & 0xFC00) >> 10;
m->id=m->id+id;
m->frame_type=CAN_FRAME_EXT;
}
/* check to see what type of message it is */
/* RTR message */
if(srr==1)
{
m->message_type=CAN_MSG_RTR;
}
/* normal message */
else
{
m->message_type=CAN_MSG_DATA;
m->data[0]=(unsigned char)ecan2msgBuf[m->buffer][3];
m->data[1]=(unsigned char)((ecan2msgBuf[m->buffer][3] & 0xFF00) >> 8);
m->data[2]=(unsigned char)ecan2msgBuf[m->buffer][4];
m->data[3]=(unsigned char)((ecan2msgBuf[m->buffer][4] & 0xFF00) >> 8);
m->data[4]=(unsigned char)ecan2msgBuf[m->buffer][5];
m->data[5]=(unsigned char)((ecan2msgBuf[m->buffer][5] & 0xFF00) >> 8);
m->data[6]=(unsigned char)ecan2msgBuf[m->buffer][6];
m->data[7]=(unsigned char)((ecan2msgBuf[m->buffer][6] & 0xFF00) >> 8);
m->data_length=(unsigned char)(ecan2msgBuf[m->buffer][2] & 0x000F);
}
}
void clearIntrflags(void){
/* Clear Interrupt Flags */
IFS0=0;
IFS1=0;
IFS2=0;
IFS3=0;
IFS4=0;
}
void oscConfig(void){
/* Configure Oscillator to operate the device at 40Mhz
Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
Fosc= 8M*40/(2*2)=80Mhz for 8M input clock */
PLLFBD=38; /* M=40 */
CLKDIVbits.PLLPOST=0; /* N1=2 */
CLKDIVbits.PLLPRE=0; /* N2=2 */
OSCTUN=0; /* Tune FRC oscillator, if FRC is used */
/* Disable Watch Dog Timer */
RCONbits.SWDTEN=0;
/* Clock switch to incorporate PLL*/
__builtin_write_OSCCONH(0x03); // Initiate Clock Switch to Primary
// Oscillator with PLL (NOSC=0b011)
__builtin_write_OSCCONL(0x01); // Start clock switching
while (OSCCONbits.COSC != 0b011); // Wait for Clock switch to occur
/* Wait for PLL to lock */
while(OSCCONbits.LOCK!=1) {};
}
void __attribute__((interrupt))_C1Interrupt(void)
//void __attribute__((interrupt, no_auto_psv))_C1Interrupt(void)
{
IFS2bits.C1IF = 0; // clear interrupt flag
if(C1INTFbits.TBIF)
{
C1INTFbits.TBIF = 0;
ecan1Transmited=1;
}
if(C1INTFbits.RBIF)
{
// read the message
if(C1RXFUL1bits.RXFUL1==1)
{
// if array indexes are the same reset then add new data to array
if(ecan1_out == ecan1_in)ecan1_out = ecan1_in=0;
rx_ecan1message[ecan1_in].buffer=1;
C1RXFUL1bits.RXFUL1=0;
}
rxECAN1(&rx_ecan1message[ecan1_in]);
ecan1_in++;
C1INTFbits.RBIF = 0;
}
}
//void __attribute__((interrupt, no_auto_psv))_C2Interrupt(void)
void __attribute__((interrupt))_C2Interrupt(void)
{
IFS3bits.C2IF = 0; // clear interrupt flag
if(C2INTFbits.TBIF)
{
C2INTFbits.TBIF = 0;
ecan2Transmited=1;
}
if(C2INTFbits.RBIF)
{
// read the message
if(C2RXFUL1bits.RXFUL1==1)
{
// if array indexes are the same reset then add new data to array
if(ecan2_out == ecan2_in)ecan2_out = ecan2_in=0;
rx_ecan2message[ecan2_in].buffer=1;
C2RXFUL1bits.RXFUL1=0;
}
rxECAN2(&rx_ecan2message[ecan2_in]);
ecan2_in++;
C2INTFbits.RBIF = 0;
}
}
//------------------------------------------------------------------------------
// DMA interrupt handlers
//------------------------------------------------------------------------------
void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void)
{
IFS0bits.DMA0IF = 0; // Clear the DMA0 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA1Interrupt(void)
{
IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA2Interrupt(void)
{
IFS1bits.DMA2IF = 0; // Clear the DMA2 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA3Interrupt(void)
{
IFS2bits.DMA3IF = 0; // Clear the DMA3 Interrupt Flag;
}
ecan1WriteMessage(0x1234,0x5678,0x9abc,0xdeff);
ID 0 data 34127856bc9affde
there are various ways to fix thisthe problem with data being transmited in the wrong order is no doubt due to the dsPIC being little endian when multiple byte data is stored in memory least significant byte first - we are passing the ecan1WriteMessage() function unsigned int parameters where a value such as 0x1234 is stored as two bytes 0x34 then 0x12
// fix so bytes are transmitted in correct order
#define swopBytes(x) ((x << 8)| ((x >> 8) & 0xFF))
void ecan1WriteTxMsgBufData(unsigned int buf, unsigned int dataLength, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4){
ecan1msgBuf[buf][2] = ((ecan1msgBuf[buf][2] & 0xFFF0) + dataLength) ;
ecan1msgBuf[buf][3] = swopBytes(data1);
ecan1msgBuf[buf][4] = swopBytes(data2);
ecan1msgBuf[buf][5] = swopBytes(data3);
ecan1msgBuf[buf][6] = swopBytes(data4);
}
ecan1WriteMessage(0x1111,0x2222,0x3333,0x4444);
ecan1WriteMessage(0x1234,0x5678,0x9abc,0xdeff);
ID 0 data 34127856bc9affde
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?