#define CAN_OPMODE_CONFIG 0x4 #define CAN_OPMODE_LOOPBACK 0x2 #define CAN_OPMODE_NORMAL 0x0 #define NUM_OF_ECAN_BUFFERS 32 __eds__ uint16 m_Can_ECanTXRXMsgBuf[NUM_OF_ECAN_BUFFERS][8] __attribute__((eds,aligned(NUM_OF_ECAN_BUFFERS * 16))); void Can_Init() { PPSUnLock; /* IO Register initialisieren RPINR26 = RPI41 0x29 RPOR5 = RPI54 0x36 */ RPINR26 = 0x29; /* Output RP54 to C1TX (0xE oder 14) setzen */ RPOR5bits.RP54R = 0xE; PPSLock; /* Can Baustein in Konfigurationsmode versetzen */ CAN1SetOperationModeNoWait(CAN_REQ_OPERMODE_CONFIG, CAN_DO_NOT_CMP_DATABYTES); while(C1CTRL1bits.OPMODE != CAN_OPMODE_CONFIG); C1CTRL1bits.CANCKS = 0; C1CTRL1bits.CSIDL = 0; C1CTRL1bits.CANCAP = 0; /* Bit Timings */ /* Berechnungsschritte für Can Bit Timing Konfiguration * * Step1: CALCULATE THE TIME QUANTUM FREQUENCY (FTQ) Ftq = N*Fbaud * 12 TQ Pro Bit, gewählt weil es gerade Ergebnisse gibt * N = 12 -> 250Kbits/s = 4µs Bittime = 12 Quanta/bit = 250ns/Quanta * Ftq = 12*250*10^3 = 3*10^6 * * STEP 2: CALCULATE THE BAUD RATE PRESCALER * BRP = (Fcan/(2 × FTQ))-1 = Fcan = Fcy = 60 * 10^6 Hz * BRP = (60*10^6/(2*3*10^6))-1 = (60/60)-1 = 0 * * STEP 3: SELECT THE INDIVIDUAL BIT TIME SEGMENTS * Phase Segment 2 = 25% -> Gerade TQ Zahl und Sample Point 75% * Bit Time = Sync Segment + (Sync Jump Width) + Propagation Segment + Phase Segment 1 + Phase Segment 2 * 12 = 1 + (2) + 2 + 6 + 3 */ C1CFG1bits.BRP = 0x0; C1CFG1bits.SJW = 0x1; C1CFG2bits.SEG1PH = 0x5; C1CFG2bits.SEG2PHTS = 0x1; C1CFG2bits.SEG2PH = 0x2; C1CFG2bits.PRSEG = 0x1; C1FCTRL = 0xC01F; //C1FCTRLbits.DMABS = 0x0; //C1FCTRLbits.FSA = 0x0; uint32 adMsgBuf; /* DMA Config Channel 0 for TX IRQ = 70*/ DMA0CON = 0x2020; DMA0REQ = 70; DMA0CNT = 7; DMA0PAD = (volatile unsigned int)&C1TXD; adMsgBuf = __builtin_edsoffset(m_Can_ECanTXRXMsgBuf); adMsgBuf = adMsgBuf & 0x7FFF; adMsgBuf += __builtin_edspage(m_Can_ECanTXRXMsgBuf) <<15; DMA0STAL = adMsgBuf & 0xFFFF; DMA0STAH = adMsgBuf >> 16; DMA0CONbits.CHEN = 0x1; /* Assign 32x8word Message Buffers for ECAN1 in device RAM. This example uses DMA1 for RX. Refer to 21.8.1 ?DMA Operation for Transmitting Data? for details on DMA channel configuration for ECAN transmit. */ DMA1CONbits.SIZE = 0x0; DMA1CONbits.DIR = 0x0; DMA1CONbits.AMODE = 0x2; DMA1CONbits.MODE = 0x0; DMA1REQ = 34; DMA1CNT = 7; DMA1PAD = (volatile unsigned int) &C1RXD; adMsgBuf = __builtin_edsoffset(m_Can_ECanTXRXMsgBuf); adMsgBuf = adMsgBuf & 0x7FFF; adMsgBuf += __builtin_edspage(m_Can_ECanTXRXMsgBuf) << 15; DMA1STAL = adMsgBuf & 0xFFFF; DMA1STAH = adMsgBuf >> 16; DMA1CONbits.CHEN = 0x1; //IEC0bits.DMA1IE = 1; /* Set SFR Window to Buffer register in RAM */ C1CTRL1bits.WIN = 1; /* RX Filter */ /* Select Acceptance Filter Mask 0 for Acceptance Filter 0 */ C1FMSKSEL1bits.F0MSK = 0x0; /* Configure Acceptance Filter Mask 0 register to mask SID<2:0> * Mask Bits (11-bits) : 0b111 1111 1000 */ C1RXM0SIDbits.SID = 0x7F8; // C1RXM0SIDbits.SID = 0x000; /* Configure Acceptance Filter 0 to match standard identifier Filter Bits (11-bits): 0b011 1010 xxx with the mask setting, message with SID range 0x1D0-0x1D7 will be accepted by the ECAN module. */ C1RXF0SIDbits.SID = 0x01D0; /* Acceptance Filter 0 to check for Standard Identifier */ C1RXM0SIDbits.MIDE = 0x1; // C1RXM0SIDbits.MIDE = 0x0; C1RXF0SIDbits.EXIDE = 0x0; /* Acceptance Filter 0 to use Message Buffer 10 to store message */ C1BUFPNT1bits.F0BP = 0xA; /* Filter 0 enabled for Identifier match with incoming message */ C1FEN1 = 0x0; C1FEN1bits.FLTEN0 = 0x1; /* Set SFR Window to Control register in RAM */ C1CTRL1bits.WIN = 0; /* Configure Message Buffer 0 for Transmission and assign priority */ C1TR01CONbits.TXEN0 = 0x1; C1TR01CONbits.TXEN1 = 0x0; C1TR01CONbits.TX0PRI = 0x3; C1TR01CONbits.TX1PRI = 0x3; /* start Can */ C1CTRL1bits.REQOP = CAN_OPMODE_NORMAL; while(C1CTRL1bits.OPMODE != CAN_OPMODE_NORMAL); // C1CTRL1bits.REQOP = CAN_OPMODE_LOOPBACK; // while(C1CTRL1bits.OPMODE != CAN_OPMODE_LOOPBACK); m_Can_ECanTXRXMsgBuf[0][0] = 0x01D2 << 2; /* IDE, SRR = 0 SID = 1D2 */ m_Can_ECanTXRXMsgBuf[0][1] = 0x0000; /* EID = 0 */ m_Can_ECanTXRXMsgBuf[0][2] = 0x0008; /* RTR = 0, DLC = Data Length counter = 8 = 8 Wörter sollen übertragen werden */ m_Can_ECanTXRXMsgBuf[0][3] = 0xabcd; m_Can_ECanTXRXMsgBuf[0][4] = 0xabcd; m_Can_ECanTXRXMsgBuf[0][5] = 0xabcd; m_Can_ECanTXRXMsgBuf[0][6] = 0xabcd; /* Empfangspuffer leer setzen */ C1RXFUL1 = 0; /* Request sende Nachricht */ C1TR01CONbits.TXREQ0 = 0x0; /* Warte auf gesendet */ while(C1TR01CONbits.TXREQ0 == 1); /* Message was received. */ while (C1RXFUL1bits.RXFUL10 == 0); C1RXFUL1bits.RXFUL10 = 0; uint16 test = m_Can_ECanTXRXMsgBuf[10][0]; test = test >> 2; }