PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ecan_example_nofifo.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 #include "pic24_all.h"
30 #include <stdio.h>
31 
32 /** \file
33 Illustrate CAN transmit, receive. Uses only one buffer for RX receive, and
34 uses a standard data frame.
35 */
36 
37 /**
38 Clock config taken from the PIC24H FRM ECAN datasheet (DS70226B, Example 21-9),
39 Produces data rate of 1 Mbps assuming FCY = 40 MHz, quanta = 20, Prescale = 2.
40 **/
41 
42 void configBaudECAN1(void) {
43 //set baud rate
44 #if FCY == 40000000L
45 // FCAN = FCY = 40 MHz. TQ = 20. Prescale = 2, Data Rate = FCAN/(TQ * pre) = 40MHz/40 = 1 MHz.
46  C1CTRL1bits.CANCKS = ECAN_FCAN_IS_FCY; // CANCKS = 1, sets FCAN = FCY = 40 MHz
47 //20 TQ for a bit time. 20 = Sync(1) + Prop seg (5) + Seg1 (8) + Seg2 (6)
48  C1CFG2 = ECAN_NO_WAKEUP |
49  ECAN_SAMPLE_3TIMES | //sample three times at sample point
50  ECAN_SEG1PH_8TQ | //seg1 = 8 TQ
51  ECAN_SEG2_PROGRAMMABLE | //seg2 is programmable
52  ECAN_SEG2PH_6TQ | //seg2 = 6 TQ
53  ECAN_PRSEG_5TQ; //propagation delay segment = 5 TQ
54 
55  C1CFG1 = ECAN_SYNC_JUMP_4 | //use maximum sync jump width
56  ECAN_PRE_2x1; //prescalers to 2x1
57 
58 #else
59 #warning ECAN module not configured! Edit function configECAN1()
60 #endif
61 }
62 
63 //minimum number of buffers, 1 for TX, 1 for RX
64 #define NUM_TX_BUFS 1 //reserve 1 for TX
65 #define NUM_BUFS 2 //make this a power of 2 for the alignment to work or enter alignment manually
66 ECANMSG msgBuf[NUM_BUFS] __attribute__((space(dma),aligned(NUM_BUFS*16)));
67 
68 //base message ID
69 #define MSG_ID 0x7A0 //arbitrary choice for 11-bit messsage ID
70 
71 //configure DMA transmit buffer
72 void configDMA0(void) {
73  DMACS0 = 0;
74  _DMA0IF = 0;
75  DMA0PAD = (unsigned int) &C1TXD;
76  DMA0REQ = DMA_IRQ_ECAN1TX;
77  DMA0STA = __builtin_dmaoffset(msgBuf);
78  DMA0CNT = sizeof(ECANMSG)/2 -1; // == 7
79  DMA0CON = //configure and enable the module Module
80  (DMA_MODULE_ON |
81  DMA_SIZE_WORD |
82  DMA_DIR_WRITE_PERIPHERAL |
83  DMA_INTERRUPT_FULL |
84  DMA_NULLW_OFF |
85  DMA_AMODE_PERIPHERAL_INDIRECT |
86  DMA_MODE_CONTINUOUS);
87 }
88 
89 //configure DMA receive buffer
90 void configDMA1(void) {
91  _DMA1IF = 0;
92  DMA1PAD = (unsigned int) &C1RXD;
93  DMA1REQ = DMA_IRQ_ECAN1RX;
94  DMA1STA = __builtin_dmaoffset(msgBuf);
95  DMA1CNT = sizeof(ECANMSG)/2 -1;
96  DMA1CON = //configure and enable the module Module
97  (DMA_MODULE_ON |
98  DMA_SIZE_WORD |
99  DMA_DIR_READ_PERIPHERAL |
100  DMA_INTERRUPT_FULL |
101  DMA_NULLW_OFF |
102  DMA_AMODE_PERIPHERAL_INDIRECT |
103  DMA_MODE_CONTINUOUS);
104 
105 }
106 
107 #define RX_BUFFER_ID 1
108 
109 void configECAN1() {
110  uint8_t u8_i;
111  CHANGE_MODE_ECAN1(ECAN_MODE_CONFIGURE);
112  configBaudECAN1();
113 
114 //use Filter 0 with Mask 0, write to RX_BUFFER_ID
115  configRxFilterECAN1(0, MSG_ID, ECAN_MATCH_SID, RX_BUFFER_ID, 0);
116  configRxMaskECAN1(0, 0x7FC, 0, 1); //check all but last 2 bits
117  clrRxFullOvfFlagsECAN1(); //clear all RX full, overflow flags.
118 
119 //first 8 buffs must be configured as either TX or TX
120  for (u8_i = 0; u8_i<8; u8_i++) {
121  if (u8_i < NUM_TX_BUFS)
122  configTxRxBufferECAN1(u8_i,ECAN_TX_BUFF,3);
123  else
124  configTxRxBufferECAN1(u8_i,ECAN_RX_BUFF,3);
125  }
126 
127  configDMA0(); //do DMA config after ECAN has been initialized
128  configDMA1();
129  CHANGE_MODE_ECAN1(ECAN_MODE_NORMAL);
130 }
131 
132 uint32_t rrot32(uint32_t u32_x) {
133  if (u32_x & 0x1) {
134  u32_x = u32_x >> 1;
135  u32_x = u32_x | 0x8000;
136  } else u32_x = u32_x >> 1;
137  return u32_x;
138 }
139 
140 int main (void) {
141  uint32_t u32_out0, u32_out1, u32_in0, u32_in1;
142  uint8_t rx_buff_id, u8_cnt;
143 
144  configBasic(HELLO_MSG);
145  configECAN1();
146  CHANGE_MODE_ECAN1(ECAN_MODE_LOOPBACK); //loopback to ourself for a test.
147  u32_out0 = 0xFEDCBA98;
148  u32_out1 = 0x76543210;
149  u8_cnt = 0;
150  while (1) {
151  DELAY_MS(500);
152  msgBuf[0].data.u32[0] = u32_out0; //save in CAN message
153  msgBuf[0].data.u32[1] = u32_out1;
154  //format Buffer 0 for TX with SID=MSG_ID, data length = 8 bytes
155  formatStandardDataFrameECAN(&msgBuf[0], MSG_ID+u8_cnt, 8);
156  startTxECAN1(0); //start transmission of buffer 0
157  while (getTxInProgressECAN1(0)) {
158  doHeartbeat(); //wait for transmission to end.
159  }
160  _DMA0IF = 0;
161  DELAY_MS(10); //delay for reception
162  if (!_DMA1IF) {
163  printf("Message ID 0x%X rejected by acceptance filter.\n",MSG_ID+u8_cnt);
164  } else {
165  _DMA1IF = 0; //RX message accepted
166  rx_buff_id = RX_BUFFER_ID;
167  u32_in0 = msgBuf[rx_buff_id].data.u32[0];
168  u32_in1 = msgBuf[rx_buff_id].data.u32[1];
169  printf("Msg ID: 0x%X, Out: 0x%lx%lx, In: 0x%lx%lx\n",
170  msgBuf[rx_buff_id].w0.SID,u32_out0, u32_out1, u32_in0, u32_in1 );
171  clrRxFullFlagECAN1(rx_buff_id);
172  }
173  u32_out0 = rrot32(u32_out0);
174  u32_out1 = rrot32(u32_out1);
175  u8_cnt++;
176  if (u8_cnt == 8) u8_cnt = 0;
177  } //end while
178 }//end main