1 | #define CAN_OPMODE_CONFIG 0x4
|
2 | #define CAN_OPMODE_LOOPBACK 0x2
|
3 | #define CAN_OPMODE_NORMAL 0x0
|
4 | #define NUM_OF_ECAN_BUFFERS 32
|
5 |
|
6 |
|
7 | __eds__ uint16 m_Can_ECanTXRXMsgBuf[NUM_OF_ECAN_BUFFERS][8] __attribute__((eds,aligned(NUM_OF_ECAN_BUFFERS * 16)));
|
8 |
|
9 |
|
10 | void Can_Init()
|
11 | {
|
12 | /* IO Register initialisieren RPINR26 = RPI41 0x2A RPOR5 = RPI54 0x36 */
|
13 | RPINR26 = 0x2A;
|
14 | /* Output RP54 to C1TX (0xD oder 14) setzen */
|
15 | RPOR5bits.RP54R = 0xD;
|
16 |
|
17 | /* Can Baustein in Konfigurationsmode versetzen */
|
18 | CAN1SetOperationModeNoWait(CAN_REQ_OPERMODE_CONFIG, CAN_DO_NOT_CMP_DATABYTES);
|
19 | while(C1CTRL1bits.OPMODE != CAN_OPMODE_CONFIG);
|
20 |
|
21 |
|
22 | C1CTRL1bits.CANCKS = 0;
|
23 | C1CTRL1bits.CSIDL = 0;
|
24 | C1CTRL1bits.CANCAP = 0;
|
25 |
|
26 | /* Config */
|
27 | C1CTRL1bits.WIN = 1;
|
28 | /* Bit Timings */
|
29 | /* Berechnungsschritte für Can Bit Timing Konfiguration
|
30 | *
|
31 | * Step1: CALCULATE THE TIME QUANTUM FREQUENCY (FTQ) Ftq = N*Fbaud
|
32 | * 12 TQ Pro Bit, gewählt weil es gerade Ergebnisse gibt
|
33 | * N = 12 -> 250Kbits/s = 4µs Bittime = 12 Quanta/bit = 250ns/Quanta
|
34 | * Ftq = 12*250*10^3 = 3*10^6
|
35 | *
|
36 | * STEP 2: CALCULATE THE BAUD RATE PRESCALER
|
37 | * BRP = (Fcan/(2 × FTQ))-1 = Fcan = Fcy = 60 * 10^6 Hz
|
38 | * BRP = (60*10^6/(2*3*10^6))-1 = (60/60)-1 = 0
|
39 | *
|
40 | * STEP 3: SELECT THE INDIVIDUAL BIT TIME SEGMENTS
|
41 | * Phase Segment 2 = 25% -> Gerade TQ Zahl und Sample Point 75%
|
42 | * Bit Time = Sync Segment + (Sync Jump Width) + Propagation Segment + Phase Segment 1 + Phase Segment 2
|
43 | * 12 = 1 + (2) + 2 + 6 + 3 */
|
44 | C1CFG1bits.BRP = 0x0;
|
45 | C1CFG1bits.SJW = 0x1;
|
46 | C1CFG2bits.SEG1PH = 0x5;
|
47 | C1CFG2bits.SEG2PHTS = 0x1;
|
48 | C1CFG2bits.SEG2PH = 0x2;
|
49 | C1CFG2bits.PRSEG = 0x1;
|
50 |
|
51 | C1FCTRL = 0xC01F;
|
52 |
|
53 | /* Configure Message Buffer 0 for Transmission and assign priority */
|
54 | C1TR01CONbits.TXEN0 = 0x1;
|
55 | C1TR01CONbits.TX0PRI = 0x3;
|
56 |
|
57 |
|
58 | uint32 adMsgBuf;
|
59 |
|
60 | /* DMA Config Channel 0 for TX IRQ = 70*/
|
61 | DMA0CON = 0x2020;
|
62 | DMA0REQ = 70;
|
63 | DMA0CNT = 7;
|
64 | DMA0PAD = (volatile unsigned int)&C1TXD;
|
65 | adMsgBuf = __builtin_edsoffset(m_Can_ECanTXRXMsgBuf);
|
66 | adMsgBuf = adMsgBuf & 0x7FFF;
|
67 | adMsgBuf += __builtin_edspage(m_Can_ECanTXRXMsgBuf) <<15;
|
68 | DMA0STAL = adMsgBuf & 0xFFFF;
|
69 | DMA0STAH = adMsgBuf >> 16;
|
70 | DMA0CONbits.CHEN = 0x1;
|
71 |
|
72 | /* Assign 32x8word Message Buffers for ECAN1 in device RAM. This example uses DMA1 for RX.
|
73 | Refer to 21.8.1 ?DMA Operation for Transmitting Data? for details on DMA channel
|
74 | configuration for ECAN transmit. */
|
75 | DMA1CONbits.SIZE = 0x0;
|
76 | DMA1CONbits.DIR = 0x0;
|
77 | DMA1CONbits.AMODE = 0x2;
|
78 | DMA1CONbits.MODE = 0x0;
|
79 | DMA1REQ = 34;
|
80 | DMA1CNT = 7;
|
81 | DMA1PAD = (volatile unsigned int) &C1RXD;
|
82 | adMsgBuf = __builtin_edsoffset(m_Can_ECanTXRXMsgBuf);
|
83 | adMsgBuf = adMsgBuf & 0x7FFF;
|
84 | adMsgBuf += __builtin_edspage(m_Can_ECanTXRXMsgBuf) << 15;
|
85 | DMA1STAL = adMsgBuf & 0xFFFF;
|
86 | DMA1STAH = adMsgBuf >> 16;
|
87 | DMA1CONbits.CHEN = 0x1;
|
88 |
|
89 | /* RX Filter */
|
90 | /* Select Acceptance Filter Mask 0 for Acceptance Filter 0 */
|
91 | C1FMSKSEL1bits.F0MSK = 0x0;
|
92 | /* Configure Acceptance Filter Mask 0 register to mask SID<2:0>
|
93 | * Mask Bits (11-bits) : 0b111 1111 1000 */
|
94 | C1RXM0SIDbits.SID = 0x7F8;
|
95 | /* Configure Acceptance Filter 0 to match standard identifier
|
96 | Filter Bits (11-bits): 0b011 1010 xxx with the mask setting, message with SID
|
97 | range 0x1D0-0x1D7 will be accepted by the ECAN module. */
|
98 | C1RXF0SIDbits.SID = 0x01D0;
|
99 | /* Acceptance Filter 0 to check for Standard Identifier */
|
100 | C1RXM0SIDbits.MIDE = 0x1;
|
101 | C1RXF0SIDbits.EXIDE = 0x0;
|
102 | /* Acceptance Filter 0 to use Message Buffer 10 to store message */
|
103 | C1BUFPNT1bits.F0BP = 0xA;
|
104 | /* Filter 0 enabled for Identifier match with incoming message */
|
105 | C1FEN1bits.FLTEN0 = 0x1;
|
106 | /* Clear Window Bit to Access ECAN
|
107 | * Control Registers */
|
108 | C1CTRL1bits.WIN = 0x0;
|
109 |
|
110 | /* start Can */
|
111 | // C1CTRL1bits.REQOP = CAN_OPMODE_NORMAL;
|
112 | // while(C1CTRL1bits.OPMODE != CAN_OPMODE_NORMAL);
|
113 |
|
114 | C1CTRL1bits.REQOP = CAN_OPMODE_LOOPBACK;
|
115 | while(C1CTRL1bits.OPMODE != CAN_OPMODE_LOOPBACK);
|
116 |
|
117 | m_Can_ECanTXRXMsgBuf[0][0] = 0x01D2 << 2; /* IDE, SRR = 0 SID = 1D2 */
|
118 | m_Can_ECanTXRXMsgBuf[0][1] = 0x0000; /* EID = 0 */
|
119 | m_Can_ECanTXRXMsgBuf[0][2] = 0x0008; /* RTR = 0, DLC = Data Length counter = 8 = 8 Wörter sollen übertragen werden */
|
120 | m_Can_ECanTXRXMsgBuf[0][3] = 0xabcd;
|
121 | m_Can_ECanTXRXMsgBuf[0][4] = 0xabcd;
|
122 | m_Can_ECanTXRXMsgBuf[0][5] = 0xabcd;
|
123 | m_Can_ECanTXRXMsgBuf[0][6] = 0xabcd;
|
124 |
|
125 | /* Request sende Nachricht */
|
126 | C1TR01CONbits.TXREQ0 = 0x1;
|
127 | /* Warte auf gesendet */
|
128 | //while(C1TR01CONbits.TXREQ0 == 1);
|
129 | while(1)
|
130 | {
|
131 | /* Message was received. */
|
132 | while (C1RXFUL1bits.RXFUL10 == 0);
|
133 | C1RXFUL1bits.RXFUL10 = 0;
|
134 | }
|