1 /**********************************************************************
\r
2 * $Id$ lpc18xx_can.c 2011-06-02
\r
4 * @file lpc18xx_can.c
\r
5 * @brief Contains all functions support for C CAN firmware library
\r
8 * @date 02. June. 2011
\r
9 * @author NXP MCU SW Application Team
\r
11 * Copyright(C) 2011, NXP Semiconductor
\r
12 * All rights reserved.
\r
14 ***********************************************************************
\r
15 * Software that is described herein is for illustrative purposes only
\r
16 * which provides customers with programming information regarding the
\r
17 * products. This software is supplied "AS IS" without any warranties.
\r
18 * NXP Semiconductors assumes no responsibility or liability for the
\r
19 * use of the software, conveys no license or title under any patent,
\r
20 * copyright, or mask work right to the product. NXP Semiconductors
\r
21 * reserves the right to make changes in the software without
\r
22 * notification. NXP Semiconductors also make no representation or
\r
23 * warranty that such application will be suitable for the specified
\r
24 * use without further testing or modification.
\r
25 **********************************************************************/
\r
27 /* Peripheral group ----------------------------------------------------------- */
\r
28 /** @addtogroup C_CAN
\r
32 /* Includes ------------------------------------------------------------------- */
\r
33 #include "LPC18xx.h"
\r
34 #include "lpc18xx_can.h"
\r
35 #include "lpc18xx_cgu.h"
\r
37 /* If this source file built with example, the LPC18xx FW library configuration
\r
38 * file in each example directory ("lpc18xx_libcfg.h") must be included,
\r
39 * otherwise the default FW library configuration file must be included instead
\r
41 #ifdef __BUILD_WITH_EXAMPLE__
\r
42 #include "lpc18xx_libcfg.h"
\r
44 #include "lpc18xx_libcfg_default.h"
\r
45 #endif /* __BUILD_WITH_EXAMPLE__ */
\r
49 /* Private Macros ---------------------------------------------------------- */
\r
51 /* Macro for reading and writing to CCAN IF registers */
\r
52 #define CAN_IF_Read(reg, IFsel) (LPC_C_CAN0->##IFsel##_##reg)
\r
53 #define CAN_IF_Write(reg, IFsel, val) (LPC_C_CAN0->##IFsel##_##reg=val)
\r
55 /* Macro for writing IF to specific RAM message object */
\r
56 #define CAN_IF_readBuf(IFsel,msg) \
\r
57 LPC_C_CAN0->##IFsel##_##CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \
\r
58 LPC_C_CAN0->##IFsel##_##CMDREQ=msg; \
\r
59 while (LPC_C_CAN0->##IFsel##_##CMDREQ & IFCREQ_BUSY );
\r
61 /* Macro for reading specific RAM message object to IF */
\r
62 #define CAN_IF_writeBuf(IFsel,msg) \
\r
63 LPC_C_CAN0->##IFsel##_##CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \
\r
64 LPC_C_CAN0->##IFsel##_##CMDREQ=msg; \
\r
65 while (LPC_C_CAN0->##IFsel##_##CMDREQ & IFCREQ_BUSY );
\r
67 #define CAN_IF_Read(reg, IFsel) (LPC_C_CAN0->IFsel##_##reg)
\r
68 #define CAN_IF_Write(reg, IFsel, val) (LPC_C_CAN0->IFsel ## _ ## reg = val)
\r
70 /* Macro for writing IF to specific RAM message object */
\r
71 #define CAN_IF_readBuf(IFsel,msg) \
\r
72 LPC_C_CAN0->IFsel##_##CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \
\r
73 LPC_C_CAN0->IFsel##_##CMDREQ=msg; \
\r
74 while (LPC_C_CAN0->IFsel##_##CMDREQ & IFCREQ_BUSY );
\r
76 /* Macro for reading specific RAM message object to IF */
\r
77 #define CAN_IF_writeBuf(IFsel,msg) \
\r
78 LPC_C_CAN0->IFsel##_##CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \
\r
79 LPC_C_CAN0->IFsel##_##CMDREQ=msg; \
\r
80 while (LPC_C_CAN0->IFsel##_##CMDREQ & IFCREQ_BUSY );
\r
86 #define CAN_STATUS_INTERRUPT 0x8000 /* 0x0001-0x0020 are the # of the message
\r
88 /* 0x8000 is the status interrupt */
\r
90 /* CAN Message interface register definitions */
\r
91 /* bit field of IF command request n register */
\r
92 #define IFCREQ_BUSY 0x8000 /* 1 is writing is progress, cleared when
\r
94 /* CAN CTRL register */
\r
95 #define CTRL_INIT (1 << 0)
\r
96 #define CTRL_IE (1 << 1)
\r
97 #define CTRL_SIE (1 << 2)
\r
98 #define CTRL_EIE (1 << 3)
\r
99 #define CTRL_DAR (1 << 5)
\r
100 #define CTRL_CCE (1 << 6)
\r
101 #define CTRL_TEST (1 << 7)
\r
103 /* CAN Test register */
\r
104 #define TEST_BASIC (1 << 2)
\r
105 #define TEST_SILENT (1 << 3)
\r
106 #define TEST_LBACK (1 << 4)
\r
108 /* CAN Status register */
\r
109 #define STAT_LEC (0x7 << 0)
\r
110 #define STAT_TXOK (1 << 3)
\r
111 #define STAT_RXOK (1 << 4)
\r
112 #define STAT_EPASS (1 << 5)
\r
113 #define STAT_EWARN (1 << 6)
\r
114 #define STAT_BOFF (1 << 7)
\r
116 #define NO_ERR 0 // No Error
\r
117 #define STUFF_ERR 1 // Stuff Error : More than 5 equal bits in a sequence have occurred in a part
\r
118 // of a received message where this is not allowed.
\r
119 #define FORM_ERR 2 // Form Error : A fixed format part of a received frame has the wrong format.
\r
120 #define ACK_ERR 3 // AckError : The message this CAN Core transmitted was not acknowledged
\r
121 // by another node.
\r
122 #define BIT1_ERR 4 // Bit1Error : During the transmission of a message (with the exception of
\r
123 // the arbitration field), the device wanted to send a recessive level (bit of
\r
124 // logical value �1�), but the monitored bus value was dominant.
\r
125 #define BIT0_ERR 5 // Bit0Error : During the transmission of a message (or acknowledge bit,
\r
126 // or active error flag, or overload flag), the device wanted to send a
\r
127 // LOW/dominant level (data or identifier bit logical value �0�), but the
\r
128 // monitored Bus value was HIGH/recessive. During busoff recovery this
\r
129 // status is set each time a
\r
130 // sequence of 11 HIGH/recessive bits has been monitored. This enables
\r
131 // the CPU to monitor the proceeding of the busoff recovery sequence
\r
132 // (indicating the bus is not stuck at LOW/dominant or continuously
\r
134 #define CRC_ERR 6 // CRCError: The CRC checksum was incorrect in the message received.
\r
137 /* bit field of IF command mask register */
\r
138 #define DATAB (1 << 0) /* 1 is transfer data byte 4-7 to message object, 0 is not */
\r
139 #define DATAA (1 << 1) /* 1 is transfer data byte 0-3 to message object, 0 is not */
\r
140 #define NEWDAT (1 << 2) /* Clear NEWDAT bit in the message object */
\r
141 #define CLRINTPND (1 << 3)
\r
142 #define CTRL (1 << 4) /* 1 is transfer the CTRL bit to the message object, 0 is not */
\r
143 #define ARB (1 << 5) /* 1 is transfer the ARB bits to the message object, 0 is not */
\r
144 #define MASK (1 << 6) /* 1 is transfer the MASK bit to the message object, 0 is not */
\r
145 #define WR (1 << 7) /* 0 is READ, 1 is WRITE */
\r
148 /* bit field of IF mask 2 register */
\r
149 #define MASK_MXTD (1 << 15) /* 1 extended identifier bit is used in the RX filter unit, 0 is not */
\r
150 #define MASK_MDIR (1 << 14) /* 1 direction bit is used in the RX filter unit, 0 is not */
\r
152 /* bit field of IF identifier 2 register */
\r
153 #define ID_MVAL (1 << 15) /* Message valid bit, 1 is valid in the MO handler, 0 is ignored */
\r
154 #define ID_MTD (1 << 14) /* 1 extended identifier bit is used in the RX filter unit, 0 is not */
\r
155 #define ID_DIR (1 << 13) /* 1 direction bit is used in the RX filter unit, 0 is not */
\r
157 /* bit field of IF message control register */
\r
158 #define NEWD (1 << 15) /* 1 indicates new data is in the message buffer. */
\r
159 #define MLST (1 << 14) /* 1 indicates a message loss. */
\r
160 #define INTP (1 << 13) /* 1 indicates message object is an interrupt source */
\r
161 #define UMSK (1 << 12) /* 1 is to use the mask for the receive filter mask. */
\r
162 #define TXIE (1 << 11) /* 1 is TX interrupt enabled */
\r
163 #define RXIE (1 << 10) /* 1 is RX interrupt enabled */
\r
166 #define RMTEN (1 << 9) /* 1 is remote frame enabled */
\r
171 #define TXRQ (1 << 8) /* 1 is TxRqst enabled */
\r
172 #define EOB (1 << 7) /* End of buffer, always write to 1 */
\r
173 #define DLC 0x000F /* bit mask for DLC */
\r
175 #define ID_STD_MASK 0x07FF
\r
176 #define ID_EXT_MASK 0x1FFFFFFF
\r
177 #define DLC_MASK 0x0F
\r
179 /* Private Variables ---------------------------------------------------------- */
\r
180 /* Statistics of all the interrupts */
\r
181 /* Buss off status counter */
\r
182 volatile uint32_t BOffCnt = 0;
\r
183 /* Warning status counter. At least one of the error counters
\r
184 in the EML has reached the error warning limit of 96 */
\r
185 volatile uint32_t EWarnCnt = 0;
\r
186 /* More than 5 equal bits in a sequence in received message */
\r
187 volatile uint32_t StuffErrCnt = 0;
\r
188 /* Wrong format of fixed format part of a received frame */
\r
189 volatile uint32_t FormErrCnt = 0;
\r
190 /* Transmitted message not acknowledged. */
\r
191 volatile uint32_t AckErrCnt = 0;
\r
192 /* Send a HIGH/recessive level, but monitored LOW/dominant */
\r
193 volatile uint32_t Bit1ErrCnt = 0;
\r
194 /* Send a LOW/dominant level, but monitored HIGH/recessive */
\r
195 volatile uint32_t Bit0ErrCnt = 0;
\r
196 /* The CRC checksum was incorrect in the message received */
\r
197 volatile uint32_t CRCErrCnt = 0;
\r
198 /* Message object new data error counter */
\r
199 volatile uint32_t ND1ErrCnt = 0;
\r
201 MSG_CB TX_cb, RX_cb;
\r
203 message_object can_buff[CAN_MSG_OBJ_MAX];
\r
204 message_object recv_buff;
\r
207 uint32_t CANStatusLog[100];
\r
208 uint32_t CANStatusLogCount = 0;
\r
212 //uint32_t CAN_IF_Read(uint32_t reg,uint32_t IFsel){
\r
213 // if(IFsel == IF1){
\r
214 // return (LPC_C_CAN0->IF1_reg);
\r
216 // return (LPC_C_CAN0->IF2_reg);
\r
219 //void CAN_IF_Write(uint32_t reg, uint32_t IFsel,uint32_t val){
\r
220 // if(IFsel == IF1){
\r
221 // (LPC_C_CAN0->IF1_reg=val);
\r
223 // (LPC_C_CAN0->IF2_reg=val);
\r
227 ///* Macro for writing IF to specific RAM message object */
\r
228 //void CAN_IF_readBuf(uint32_t IFsel,uint32_t msg){
\r
229 // if(IFsel == IF1){
\r
230 // LPC_C_CAN0->IF1_CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;
\r
231 // LPC_C_CAN0->IF1_CMDREQ=msg;
\r
232 // while (LPC_C_CAN0->IF1_CMDREQ & IFCREQ_BUSY );
\r
234 // LPC_C_CAN0->IF2_CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;
\r
235 // LPC_C_CAN0->IF2_CMDREQ=msg;
\r
236 // while (LPC_C_CAN0->IF2_CMDREQ & IFCREQ_BUSY );
\r
241 ///* Macro for reading specific RAM message object to IF */
\r
242 //void CAN_IF_writeBuf(uint32_t IFsel,uint32_t msg){
\r
243 // if(IFsel == IF1){
\r
244 // LPC_C_CAN0->IF1_CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;
\r
245 // LPC_C_CAN0->IF1_CMDREQ=msg;
\r
246 // while (LPC_C_CAN0->IF1_CMDREQ & IFCREQ_BUSY );
\r
248 // LPC_C_CAN0->IF2_CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;
\r
249 // LPC_C_CAN0->IF2_CMDREQ=msg;
\r
250 // while (LPC_C_CAN0->IF2_CMDREQ & IFCREQ_BUSY );
\r
255 /*********************************************************************//**
\r
256 * @brief Handle valid received message
\r
257 * @param[in] msg_no Message Object number
\r
259 **********************************************************************/
\r
260 void CAN_RxInt_MessageProcess( uint8_t msg_no )
\r
264 uint32_t reg1, reg2;
\r
266 /* Import message object to IF2 */
\r
267 CAN_IF_readBuf(IF2, msg_no); /* Read the message into the IF registers */
\r
269 p_add = (uint32_t *)&recv_buff;
\r
271 if( CAN_IF_Read(ARB2, IF2) & ID_MTD ) /* bit 28-0 is 29 bit extended frame */
\r
273 /* mask off MsgVal and Dir */
\r
274 reg1 = CAN_IF_Read(ARB1, IF2);
\r
275 reg2 = CAN_IF_Read(ARB2, IF2);
\r
276 msg_id = (reg1|(reg2<<16));
\r
280 /* bit 28-18 is 11-bit standard frame */
\r
281 msg_id = (CAN_IF_Read(ARB2, IF2) &0x1FFF) >> 2;
\r
285 p_add[1] = CAN_IF_Read(MCTRL, IF2) & 0x000F; /* Get Msg Obj Data length */
\r
286 p_add[2] = (CAN_IF_Read(DA2, IF2)<<16) | CAN_IF_Read(DA1, IF2);
\r
287 p_add[3] = (CAN_IF_Read(DB2, IF2)<<16) | CAN_IF_Read(DB1, IF2);
\r
289 /* Clear interrupt pending bit */
\r
290 CAN_IF_Write(MCTRL, IF2, UMSK|RXIE|EOB|CAN_DLC_MAX);
\r
291 /* Save changes to message RAM */
\r
292 CAN_IF_writeBuf(IF2, msg_no);
\r
296 /*********************************************************************//**
\r
297 * @brief Handle valid transmit message
\r
298 * @param[in] msg_no Message Object number
\r
300 **********************************************************************/
\r
301 void CAN_TxInt_MessageProcess( uint8_t msg_no )
\r
303 /* Clear interrupt pending bit */
\r
304 CAN_IF_Write(MCTRL, IF2, UMSK|RXIE|EOB|CAN_DLC_MAX);
\r
305 /* Save changes to message RAM */
\r
306 CAN_IF_writeBuf(IF2,msg_no);
\r
310 /*********************************************************************//**
\r
311 * @brief CAN interrupt handler
\r
314 **********************************************************************/
\r
315 volatile uint32_t nd_tmp;
\r
316 void CAN_IRQHandler(void)
\r
318 uint32_t canstat = 0;
\r
319 uint32_t can_int, msg_no;
\r
321 while ( (can_int = LPC_C_CAN0->INT) != 0 ) /* While interrupt is pending */
\r
323 canstat = LPC_C_CAN0->STAT; /* Read CAN status register */
\r
325 if ( can_int & CAN_STATUS_INTERRUPT )
\r
327 /* Passive state monitored frequently in main. */
\r
329 if ( canstat & STAT_EWARN )
\r
334 if ( canstat & STAT_BOFF )
\r
340 switch (canstat&STAT_LEC) /* LEC Last Error Code (Type of the last error to occur on the CAN bus) */
\r
366 /* Clear all warning/error states except RXOK/TXOK */
\r
367 LPC_C_CAN0->STAT &= STAT_RXOK|STAT_TXOK;
\r
371 if ( (canstat & STAT_LEC) == 0 ) /* NO ERROR */
\r
373 msg_no = can_int & 0x7FFF;
\r
374 if((msg_no >= 1 ) && (msg_no <= 16))
\r
376 LPC_C_CAN0->STAT &= ~STAT_RXOK;
\r
377 /* Check if message number is correct by reading NEWDAT registers.
\r
378 By reading out the NEWDAT bits, the CPU can check for which Message
\r
379 Object the data portion was updated
\r
380 Only first 16 message object used for receive : only use ND1 */
\r
381 if((1<<(msg_no-1)) != LPC_C_CAN0->ND1)
\r
383 /* message object does not contain new data! */
\r
387 CAN_RxInt_MessageProcess(msg_no);
\r
392 LPC_C_CAN0->STAT &= ~STAT_TXOK;
\r
393 CAN_TxInt_MessageProcess(msg_no);
\r
402 /*********************************************************************//**
\r
403 * @brief Initialize CAN peripheral
\r
404 * @param[in] BitClk CAN bit clock setting
\r
405 * @param[in] ClkDiv CAN bit clock setting
\r
406 * @param[in] Tx_cb point to call-back function when transmitted
\r
407 * @param[in] Rx_cb point to call-back function when received
\r
409 **********************************************************************/
\r
410 void CAN_Init( uint32_t BitClk, CCAN_CLKDIV_Type ClkDiv , MSG_CB Tx_cb, MSG_CB Rx_cb)
\r
415 if ( !(LPC_C_CAN0->CNTL & CTRL_INIT) )
\r
417 /* If it's in normal operation already, stop it, reconfigure
\r
418 everything first, then restart. */
\r
419 LPC_C_CAN0->CNTL |= CTRL_INIT; /* Default state */
\r
422 LPC_C_CAN0->CLKDIV = ClkDiv; /* Divider for CAN VPB3 clock */
\r
423 LPC_C_CAN0->CNTL |= CTRL_CCE; /* Start configuring bit timing */
\r
424 LPC_C_CAN0->BT = BitClk;
\r
425 LPC_C_CAN0->BRPE = 0x0000;
\r
426 LPC_C_CAN0->CNTL &= ~CTRL_CCE; /* Stop configuring bit timing */
\r
428 LPC_C_CAN0->CNTL &= ~CTRL_INIT; /* Initialization finished, normal operation now. */
\r
429 while ( LPC_C_CAN0->CNTL & CTRL_INIT );
\r
431 /* By default, auto TX is enabled, enable all related interrupts */
\r
432 LPC_C_CAN0->CNTL |= (CTRL_IE|CTRL_SIE|CTRL_EIE);
\r
436 /*********************************************************************//**
\r
437 * @brief Send a message to the CAN port
\r
438 * @param[in] msg_no message object number
\r
439 * @param[in] msg_ptr msg buffer pointer
\r
441 **********************************************************************/
\r
442 void CAN_Send(uint8_t msg_no, uint32_t *msg_ptr )
\r
444 uint32_t tx_id, Length;
\r
446 if(msg_ptr == NULL) return;
\r
448 /* first is the ID, second is length, the next four are data */
\r
449 tx_id = *msg_ptr++;
\r
450 Length = *msg_ptr++;
\r
452 if(Length>CAN_DLC_MAX)Length = CAN_DLC_MAX;
\r
453 CAN_IF_Write(MCTRL, IF1, UMSK|TXIE|TXRQ|EOB|RMTEN|(Length & DLC_MASK));
\r
454 CAN_IF_Write(DA1, IF1, *msg_ptr); /* Lower two bytes of message pointer */
\r
455 CAN_IF_Write(DA2, IF1, (*msg_ptr++)>>16); /* Upper two bytes of message pointer */
\r
456 CAN_IF_Write(DB1, IF1, *msg_ptr); /* Lower two bytes of message pointer */
\r
457 CAN_IF_Write(DB2, IF1, (*msg_ptr)>>16); /* Upper two bytes of message pointer */
\r
459 /* Configure arbitration */
\r
460 if(!(tx_id & (0x1<<30))) /* bit 30 is 0, standard frame */
\r
462 /* Mxtd: 0, Mdir: 1, Mask is 0x7FF */
\r
463 CAN_IF_Write(MSK2, IF1, MASK_MDIR | (ID_STD_MASK << 2));
\r
464 CAN_IF_Write(MSK1, IF1, 0x0000);
\r
466 /* MsgVal: 1, Mtd: 0, Dir: 1, ID = 0x200 */
\r
467 CAN_IF_Write(ARB1, IF1, 0x0000);
\r
468 CAN_IF_Write(ARB2, IF1, ID_MVAL| ID_DIR | (tx_id << 2));
\r
470 else /* Extended frame */
\r
472 /* Mxtd: 1, Mdir: 1, Mask is 0x7FF */
\r
473 CAN_IF_Write(MSK2, IF1, MASK_MXTD | MASK_MDIR | (ID_EXT_MASK >> 16));
\r
474 CAN_IF_Write(MSK1, IF1, ID_EXT_MASK & 0x0000FFFF);
\r
476 /* MsgVal: 1, Mtd: 1, Dir: 1, ID = 0x200000 */
\r
477 CAN_IF_Write(ARB1, IF1, tx_id & 0x0000FFFF);
\r
478 CAN_IF_Write(ARB2, IF1, ID_MVAL|ID_MTD | ID_DIR | (tx_id >> 16));
\r
481 /* Write changes to message RAM */
\r
482 CAN_IF_writeBuf(IF1, msg_no);
\r
487 /*********************************************************************//**
\r
488 * @brief Listen for a message on CAN bus
\r
489 * @param[in] msg_no message object number
\r
490 * @param[in] msg_ptr msg buffer pointer
\r
491 * @param[in] RemoteEnable Enable/disable remote frame support, should be:
\r
495 **********************************************************************/
\r
496 void CAN_Recv(uint8_t msg_no, uint32_t *msg_ptr, Bool RemoteEnable)
\r
498 uint32_t rx_id = *msg_ptr;
\r
499 uint32_t rmten = 0;
\r
503 if(!(rx_id & (0x1<<30))){ /* standard frame */
\r
505 /* Mxtd: 0, Mdir: 0, Mask is 0x7FF */
\r
506 CAN_IF_Write(MSK1, IF1, 0x0000);
\r
507 CAN_IF_Write(MSK2, IF1, ID_STD_MASK << 2);
\r
508 /* MsgVal: 1, Mtd: 0, Dir: 0 */
\r
509 CAN_IF_Write(ARB1, IF1, 0x0000);
\r
510 CAN_IF_Write(MCTRL, IF1, rmten|UMSK|RXIE|EOB|CAN_DLC_MAX);
\r
511 CAN_IF_Write(DA1, IF1, 0x0000);
\r
512 CAN_IF_Write(DA2, IF1, 0x0000);
\r
513 CAN_IF_Write(DB1, IF1, 0x0000);
\r
514 CAN_IF_Write(DB2, IF1, 0x0000);
\r
515 CAN_IF_Write(ARB2, IF1, ID_MVAL | ((rx_id) << 2));
\r
516 /* Transfer data to message RAM */
\r
517 CAN_IF_writeBuf(IF1, msg_no);
\r
521 rx_id &= (0x1<<30)-1 ; /* Mask ID bit */
\r
522 /* Mxtd: 1, Mdir: 0, Mask is 0x1FFFFFFF */
\r
523 CAN_IF_Write(MSK1, IF1, ID_EXT_MASK & 0xFFFF);
\r
524 CAN_IF_Write(MSK2, IF1, MASK_MXTD | (ID_EXT_MASK >> 16));
\r
525 /* MsgVal: 1, Mtd: 1, Dir: 0 */
\r
526 CAN_IF_Write(ARB1, IF1, (rx_id) & 0xFFFF);
\r
527 CAN_IF_Write(MCTRL, IF1, rmten|UMSK|RXIE|EOB|CAN_DLC_MAX);
\r
528 CAN_IF_Write(DA1, IF1, 0x0000);
\r
529 CAN_IF_Write(DA2, IF1, 0x0000);
\r
530 CAN_IF_Write(DB1, IF1, 0x0000);
\r
531 CAN_IF_Write(DB2, IF1, 0x0000);
\r
532 CAN_IF_Write(ARB2, IF1, ID_MVAL | ID_MTD | ((rx_id) >> 16));
\r
533 /* Transfer data to message RAM */
\r
534 CAN_IF_writeBuf(IF1, msg_no);
\r
539 /*********************************************************************//**
\r
540 * @brief Read a message from Message RAM to buffer
\r
541 * @param[in] msg_no message object number
\r
542 * @param[in] buff msg buffer pointer
\r
544 **********************************************************************/
\r
545 void CAN_ReadMsg(uint32_t msg_no, message_object* buff){
\r
547 buff->id = recv_buff.id;
\r
548 buff->dlc = recv_buff.dlc;
\r
549 if(recv_buff.dlc>CAN_DLC_MAX) recv_buff.dlc = CAN_DLC_MAX;
\r
550 for(i=0;i<recv_buff.dlc;i++)
\r
551 buff->data[i] = recv_buff.data[i];
\r
559 /* --------------------------------- End Of File ------------------------------ */
\r