can.c
上传用户:yyyd609
上传日期:2022-07-18
资源大小:183k
文件大小:20k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /******************** (C) COPYRIGHT 2003 STMicroelectronics ********************
  2. * File Name          : can.c
  3. * Author             : MCD Application Team
  4. * Date First Issued  : 10/27/2003
  5. * Description        : This file contains all the functions prototypes for the
  6. *                      CAN bus software library.
  7. ********************************************************************************
  8. * History:
  9. *  01/01/2004 : V1.2
  10. *  14/07/2004 : V1.3
  11. *******************************************************************************/
  12. #include "can.h"
  13. #include "xti.h"
  14. #include "pcu.h"
  15. // macro to format the timing register value from the timing parameters
  16. #define CAN_TIMING(tseg1, tseg2, sjw, brp) (((tseg2-1) & 0x07) << 12) | (((tseg1-1) & 0x0F) << 8) | (((sjw-1) & 0x03) << 6) | ((brp-1) & 0x3F)
  17. // array of pre-defined timing parameters for standard bitrates
  18. u16 CanTimings[] = {             // value   bitrate     NTQ  TSEG1  TSEG2  SJW  BRP
  19. CAN_TIMING(11, 4, 4, 5), // 0x3AC4  100 kbit/s  16   11     4      4    5
  20. CAN_TIMING(11, 4, 4, 4), // 0x3AC3  125 kbit/s  16   11     4      4    4
  21. CAN_TIMING( 4, 3, 3, 4), // 0x2383  250 kbit/s   8    4     3      3    4
  22. CAN_TIMING(13, 2, 1, 1), // 0x1C00  500 kbit/s  16   13     2      1    1
  23. CAN_TIMING( 4, 3, 1, 1), // 0x2300  1 Mbit/s     8    4     3      1    1
  24. };
  25. /*******************************************************************************
  26. * Function Name  : CAN_SetBitrate
  27. * Description    : Setup a standard CAN bitrate
  28. * Input 1        : one of the CAN_BITRATE_xxx defines
  29. * Output         : None
  30. * Return         : None
  31. * Note           : CAN must be in initialization mode
  32. *******************************************************************************/
  33. void CAN_SetBitrate(u32 bitrate)
  34. {
  35. CAN->BTR = CanTimings[bitrate]; // write the predefined timing value
  36. CAN->BRPR = 0;  // clear the Extended Baud Rate Prescaler
  37. }
  38. /*******************************************************************************
  39. * Function Name  : CAN_SetTiming
  40. * Description    : Setup the CAN timing with specific parameters
  41. * Input 1        : Time Segment before the sample point position, from 1 to 16
  42. * Input 2        : Time Segment after the sample point position, from 1 to 8
  43. * Input 3        : Synchronisation Jump Width, from 1 to 4
  44. * Input 4        : Baud Rate Prescaler, from 1 to 1024
  45. * Output         : None
  46. * Return         : None
  47. * Note           : CAN must be in initialization mode
  48. *******************************************************************************/
  49. void CAN_SetTiming(u32 tseg1, u32 tseg2, u32 sjw, u32 brp)
  50. {
  51. CAN->BTR = CAN_TIMING(tseg1, tseg2, sjw, brp);
  52. CAN->BRPR = ((brp-1) >> 6) & 0x0F;
  53. }
  54. /*******************************************************************************
  55. * Function Name  : CAN_SleepRequest
  56. * Description    : Request the CAN cell to enter sleep mode
  57. * Input 1        : CAN_WAKEUP_ON_EXT or CAN_WAKEUP_ON_CAN
  58. * Output         : None
  59. * Return         : None
  60. *******************************************************************************/
  61. void CAN_SleepRequest(u32 WakeupMode)
  62. {
  63. // Wakeup Line 6 is linked to CAN RX pin (port 1.11)
  64. // Wakeup Line 2 is linked to external pin (port 2.8)
  65. u32 WakeupLine = (WakeupMode == CAN_WAKEUP_ON_CAN ? XTI_Line6 : XTI_Line2);
  66. CAN_WaitEndOfTx();
  67. XTI_Init();
  68. // Configure the Wakeup Line mode, select Falling edge (transition to dominant state)
  69. XTI_LineModeConfig(WakeupLine, XTI_FallingEdge);
  70. // Enable Wake-Up interrupt
  71. XTI_LineConfig(WakeupLine, ENABLE);
  72. // Enable Wake-Up mode with interrupt
  73. XTI_ModeConfig(XTI_WakeUpInterrupt, ENABLE);
  74. XTI_PendingBitClear(XTI_InterruptLineValue());
  75. // Enter STOP mode (resume execution from here)
  76. PCU_LPMEnter(PCU_STOP);
  77. }
  78. /*******************************************************************************
  79. * Function Name  : CAN_GetFreeIF
  80. * Description    : Search the first free message interface, starting from 0
  81. * Input          : None
  82. * Output         : None
  83. * Return         : A free message interface number (0 or 1) if found, else 2
  84. *******************************************************************************/
  85. static u32 CAN_GetFreeIF(void)
  86. {
  87. if ((CAN->sMsgObj[0].CRR & CAN_CRR_BUSY) == 0)
  88. return 0;
  89. else if ((CAN->sMsgObj[1].CRR & CAN_CRR_BUSY) == 0)
  90. return 1;
  91. else return 2;
  92. }
  93. /*******************************************************************************
  94. * Macro Name     : xxx_ID_MSK, xxx_ID_ARB
  95. * Description    : Form the Mask and Arbitration registers value to filter a range
  96. *                  of identifiers or a fixed identifier, for standard and extended IDs
  97. *******************************************************************************/
  98. #define RANGE_ID_MSK(range_start, range_end) (~((range_end) - (range_start)))
  99. #define RANGE_ID_ARB(range_start, range_end) ((range_start) & (range_end))
  100. #define FIXED_ID_MSK(id) RANGE_ID_MSK((id), (id))
  101. #define FIXED_ID_ARB(id) RANGE_ID_ARB((id), (id))
  102. #define STD_RANGE_ID_MSK(range_start, range_end) ((u16)((RANGE_ID_MSK((range_start), (range_end)) & 0x7FF) << 2))
  103. #define STD_RANGE_ID_ARB(range_start, range_end) ((u16)(RANGE_ID_ARB((range_start), (range_end)) << 2))
  104. #define STD_FIXED_ID_MSK(id) ((u16)((FIXED_ID_MSK(id) & 0x7FF) << 2))
  105. #define STD_FIXED_ID_ARB(id) ((u16)(FIXED_ID_ARB(id) << 2))
  106. #define EXT_RANGE_ID_MSK_L(range_start, range_end) ((u16)(RANGE_ID_MSK((range_start), (range_end)) >> 11))
  107. #define EXT_RANGE_ID_MSK_H(range_start, range_end) ((u16)(STD_RANGE_ID_MSK((range_start), (range_end)) | ((RANGE_ID_MSK((range_start), (range_end)) >> 27) & 0x03)))
  108. #define EXT_RANGE_ID_ARB_L(range_start, range_end) ((u16)(RANGE_ID_ARB((range_start), (range_end)) >> 11))
  109. #define EXT_RANGE_ID_ARB_H(range_start, range_end) ((u16)(STD_RANGE_ID_ARB((range_start), (range_end)) | ((RANGE_ID_ARB((range_start), (range_end)) >> 27) & 0x03)))
  110. #define EXT_FIXED_ID_MSK_L(id) ((u16)(FIXED_ID_MSK(id) >> 11))
  111. #define EXT_FIXED_ID_MSK_H(id) ((u16)(STD_FIXED_ID_MSK(id) | ((FIXED_ID_MSK(id) >> 27) & 0x03)))
  112. #define EXT_FIXED_ID_ARB_L(id) ((u16)(FIXED_ID_ARB(id) >> 11))
  113. #define EXT_FIXED_ID_ARB_H(id) ((u16)(STD_FIXED_ID_ARB(id) | ((FIXED_ID_ARB(id) >> 27) & 0x03)))
  114. /*******************************************************************************
  115. * Function Name  : CAN_SetUnusedMsgObj
  116. * Description    : Configure the message object as unused
  117. * Input 1        : message object number, from 0 to 31
  118. * Output         : None
  119. * Return         : None
  120. *******************************************************************************/
  121. void CAN_SetUnusedMsgObj(u32 msgobj)
  122. {
  123. u32 msg_if;
  124.     while ((msg_if = CAN_GetFreeIF()) == 2);
  125.    CAN->sMsgObj[msg_if].CMR =  CAN_CMR_WRRD
  126.                              | CAN_CMR_MASK
  127.                              | CAN_CMR_ARB
  128.                              | CAN_CMR_CONTROL
  129.                              | CAN_CMR_DATAA
  130.                              | CAN_CMR_DATAB;
  131.    CAN->sMsgObj[msg_if].M1R = 0;
  132.    CAN->sMsgObj[msg_if].M2R = 0;
  133.    CAN->sMsgObj[msg_if].A1R = 0;
  134.    CAN->sMsgObj[msg_if].A2R = 0;
  135.    CAN->sMsgObj[msg_if].MCR = 0;
  136.    CAN->sMsgObj[msg_if].DA1R = 0;
  137.    CAN->sMsgObj[msg_if].DA2R = 0;
  138.    CAN->sMsgObj[msg_if].DB1R = 0;
  139.    CAN->sMsgObj[msg_if].DB2R = 0;
  140.    CAN->sMsgObj[msg_if].CRR = 1 + msgobj;
  141. }
  142. /*******************************************************************************
  143. * Function Name  : CAN_SetTxMsgObj
  144. * Description    : Configure the message object as TX
  145. * Input 1        : message object number, from 0 to 31
  146. * Input 2        : CAN_STD_ID or CAN_EXT_ID
  147. * Output         : None
  148. * Return         : None
  149. *******************************************************************************/
  150. void CAN_SetTxMsgObj(u32 msgobj, u32 idType)
  151. {
  152. u32 msg_if;
  153.     while ((msg_if = CAN_GetFreeIF()) == 2);
  154.    CAN->sMsgObj[msg_if].CMR =  CAN_CMR_WRRD
  155.                              | CAN_CMR_MASK
  156.                              | CAN_CMR_ARB
  157.                              | CAN_CMR_CONTROL
  158.                              | CAN_CMR_DATAA
  159.                              | CAN_CMR_DATAB;
  160. CAN->sMsgObj[msg_if].M1R = 0;
  161. CAN->sMsgObj[msg_if].A1R = 0;
  162. if (idType == CAN_STD_ID)
  163. {
  164.    CAN->sMsgObj[msg_if].M2R = CAN_M2R_MDIR;
  165.    CAN->sMsgObj[msg_if].A2R = CAN_A2R_MSGVAL | CAN_A2R_DIR;
  166.    }
  167.    else
  168.    {
  169.    CAN->sMsgObj[msg_if].M2R = CAN_M2R_MDIR | CAN_M2R_MXTD;
  170.    CAN->sMsgObj[msg_if].A2R = CAN_A2R_MSGVAL | CAN_A2R_DIR | CAN_A2R_XTD;
  171.    }
  172.    CAN->sMsgObj[msg_if].MCR = CAN_MCR_TXIE | CAN_MCR_EOB;
  173.    CAN->sMsgObj[msg_if].DA1R = 0;
  174.    CAN->sMsgObj[msg_if].DA2R = 0;
  175.    CAN->sMsgObj[msg_if].DB1R = 0;
  176.    CAN->sMsgObj[msg_if].DB2R = 0;
  177.    CAN->sMsgObj[msg_if].CRR = 1 + msgobj;
  178. }
  179. /*******************************************************************************
  180. * Function Name  : CAN_SetRxMsgObj
  181. * Description    : Configure the message object as RX
  182. * Input 1        : message object number, from 0 to 31
  183. * Input 2        : CAN_STD_ID or CAN_EXT_ID
  184. * Input 3        : low part of the identifier range used for acceptance filtering
  185. * Input 4        : high part of the identifier range used for acceptance filtering
  186. * Input 5        : TRUE for a single receive object or a FIFO receive object that
  187. *                  is the last one of the FIFO
  188. *                  FALSE for a FIFO receive object that is not the last one
  189. * Output         : None
  190. * Return         : None
  191. *******************************************************************************/
  192. void CAN_SetRxMsgObj(u32 msgobj, u32 idType, u32 idLow, u32 idHigh, bool singleOrFifoLast)
  193. {
  194. u32 msg_if;
  195.     while ((msg_if = CAN_GetFreeIF()) == 2);
  196.    CAN->sMsgObj[msg_if].CMR =  CAN_CMR_WRRD
  197.                              | CAN_CMR_MASK
  198.                              | CAN_CMR_ARB
  199.                              | CAN_CMR_CONTROL
  200.                              | CAN_CMR_DATAA
  201.                              | CAN_CMR_DATAB;
  202. if (idType == CAN_STD_ID)
  203. {
  204.    CAN->sMsgObj[msg_if].M1R = 0;
  205.    CAN->sMsgObj[msg_if].M2R = STD_RANGE_ID_MSK(idLow, idHigh);
  206.    CAN->sMsgObj[msg_if].A1R = 0;
  207.    CAN->sMsgObj[msg_if].A2R = CAN_A2R_MSGVAL | STD_RANGE_ID_ARB(idLow, idHigh);
  208.    }
  209.    else
  210.    {
  211.    CAN->sMsgObj[msg_if].M1R = EXT_RANGE_ID_MSK_L(idLow, idHigh);
  212.    CAN->sMsgObj[msg_if].M2R = CAN_M2R_MXTD | EXT_RANGE_ID_MSK_H(idLow, idHigh);
  213.    CAN->sMsgObj[msg_if].A1R = EXT_RANGE_ID_ARB_L(idLow, idHigh);
  214.    CAN->sMsgObj[msg_if].A2R = CAN_A2R_MSGVAL | CAN_A2R_XTD | EXT_RANGE_ID_ARB_H(idLow, idHigh);
  215.    }
  216.    CAN->sMsgObj[msg_if].MCR = CAN_MCR_RXIE | CAN_MCR_UMASK | (singleOrFifoLast ? CAN_MCR_EOB : 0);
  217.    CAN->sMsgObj[msg_if].DA1R = 0;
  218.    CAN->sMsgObj[msg_if].DA2R = 0;
  219.    CAN->sMsgObj[msg_if].DB1R = 0;
  220.    CAN->sMsgObj[msg_if].DB2R = 0;
  221.    CAN->sMsgObj[msg_if].CRR = 1 + msgobj;
  222. }
  223. /*******************************************************************************
  224. * Function Name  : CAN_InvalidateAllMsgObj
  225. * Description    : Configure all the message objects as unused
  226. * Input          : None
  227. * Output         : None
  228. * Return         : None
  229. *******************************************************************************/
  230. void CAN_InvalidateAllMsgObj(void)
  231. {
  232. u32 i;
  233. for (i = 0; i < 32; i++)
  234. CAN_SetUnusedMsgObj(i);
  235. }
  236. /*******************************************************************************
  237. * Function Name  : CAN_Init
  238. * Description    : Initialize the CAN cell and set the bitrate
  239. * Input 1        : any binary value formed from the CAN_CTL_xxx defines
  240. * Input 2        : one of the CAN_BITRATE_xxx defines
  241. * Output         : None
  242. * Return         : None
  243. *******************************************************************************/
  244. void CAN_Init(u8 mask, u32 bitrate)
  245. {
  246.   CAN_EnterInitMode(CAN_CR_CCE | mask);
  247.   CAN_SetBitrate(bitrate);
  248.   CAN_LeaveInitMode();
  249.   CAN_LeaveTestMode();
  250. }
  251. /*******************************************************************************
  252. * Function Name  : CAN_ReleaseMessage
  253. * Description    : Release the message object
  254. * Input 1        : message object number, from 0 to 31
  255. * Output         : None
  256. * Return         : None
  257. *******************************************************************************/
  258. void CAN_ReleaseMessage(u32 msgobj)
  259. {
  260. u32 i;
  261.     while ((i = CAN_GetFreeIF()) == 2);
  262. CAN->sMsgObj[i].CMR = CAN_CMR_CLRINTPND | CAN_CMR_TXRQST;
  263. CAN->sMsgObj[i].CRR = 1 + msgobj;
  264. }
  265. /*******************************************************************************
  266. * Function Name  : CAN_SendMessage
  267. * Description    : Start transmission of a message
  268. * Input 1        : message object number, from 0 to 31
  269. * Input 2        : pointer to the message structure containing data to transmit
  270. * Output         : None
  271. * Return         : 1 if transmission was OK, else 0
  272. *******************************************************************************/
  273. u32 CAN_SendMessage(u32 msgobj, canmsg* pCanMsg)
  274. {
  275.   while (CAN->sMsgObj[0].CRR & CAN_CRR_BUSY);
  276. //  if (CAN->sMsgObj[0].COMR & CAN_CRQ_BUSY)
  277. // return 0; // message interface 0 not free
  278.   CAN->SR &= ~CAN_SR_TXOK;
  279.   // read the Arbitration and Message Control
  280.   CAN->sMsgObj[0].CMR = CAN_CMR_ARB | CAN_CMR_CONTROL;
  281.   CAN->sMsgObj[0].CRR = 1 + msgobj;
  282.   while (CAN->sMsgObj[0].CRR & CAN_CRR_BUSY);
  283.   // update the contents needed for transmission
  284.   CAN->sMsgObj[0].CMR =   CAN_CMR_WRRD
  285.                    | CAN_CMR_ARB
  286.                    | CAN_CMR_CONTROL
  287.                    | CAN_CMR_DATAA
  288.                    | CAN_CMR_DATAB;
  289.   if ((CAN->sMsgObj[0].A2R & CAN_A2R_XTD) == 0)
  290.   {
  291.    // standard ID
  292. CAN->sMsgObj[0].A1R = 0;
  293. CAN->sMsgObj[0].A2R = (CAN->sMsgObj[0].A2R & 0xE000) | STD_FIXED_ID_ARB(pCanMsg->Id);
  294.   }
  295.   else
  296.   {
  297.    // extended ID
  298. CAN->sMsgObj[0].A1R = EXT_FIXED_ID_ARB_L(pCanMsg->Id);
  299. CAN->sMsgObj[0].A2R = (CAN->sMsgObj[0].A2R & 0xE000) | EXT_FIXED_ID_ARB_H(pCanMsg->Id);
  300.   }
  301.   CAN->sMsgObj[0].MCR = (CAN->sMsgObj[0].MCR & 0xFEF0) | CAN_MCR_NEWDAT | CAN_MCR_TXRQST | pCanMsg->Dlc;
  302.   CAN->sMsgObj[0].DA1R = ((u16)pCanMsg->Data[1]<<8) | pCanMsg->Data[0];
  303.   CAN->sMsgObj[0].DA2R = ((u16)pCanMsg->Data[3]<<8) | pCanMsg->Data[2];
  304.   CAN->sMsgObj[0].DB1R = ((u16)pCanMsg->Data[5]<<8) | pCanMsg->Data[4];
  305.   CAN->sMsgObj[0].DB2R = ((u16)pCanMsg->Data[7]<<8) | pCanMsg->Data[6];
  306.   CAN->sMsgObj[0].CRR = 1 + msgobj;
  307.   return 1;
  308. }
  309. /*******************************************************************************
  310. * Function Name  : CAN_ReceiveMessage
  311. * Description    : Get the message, if received
  312. * Input 1        : message object number, from 0 to 31
  313. * Input 2        : if TRUE, the message object is released when getting the data
  314. *                  if FALSE, the message object is not released
  315. * Input 3        : pointer to the message structure where received data is stored
  316. * Output         : None
  317. * Return         : 1 if reception was OK, else 0 (no message pending)
  318. *******************************************************************************/
  319. u32 CAN_ReceiveMessage(u32 msgobj, bool release, canmsg* pCanMsg)
  320. {
  321.     if (!CAN_IsMessageWaiting(msgobj))
  322.      return 0;
  323. CAN->SR &= ~CAN_SR_RXOK;
  324.     // read the message contents
  325.     CAN->sMsgObj[1].CMR =   CAN_CMR_MASK
  326.                   | CAN_CMR_ARB
  327.                   | CAN_CMR_CONTROL
  328.                   | CAN_CMR_CLRINTPND
  329.                   | (release ? CAN_CMR_TXRQST : 0)
  330.                   | CAN_CMR_DATAA
  331.                   | CAN_CMR_DATAB;
  332. CAN->sMsgObj[1].CRR = 1 + msgobj;
  333. while (CAN->sMsgObj[1].CRR & CAN_CRR_BUSY);
  334.     if ((CAN->sMsgObj[1].A2R & CAN_A2R_XTD) == 0)
  335.     {
  336.      // standard ID
  337.      pCanMsg->IdType = CAN_STD_ID;
  338.       pCanMsg->Id = (CAN->sMsgObj[1].A2R >> 2) & 0x07FF;
  339.     }
  340.     else
  341.     {
  342.       // extended ID
  343.      pCanMsg->IdType = CAN_EXT_ID;
  344.       pCanMsg->Id = ((CAN->sMsgObj[1].A2R >> 2) & 0x07FF) | ((u32)CAN->sMsgObj[1].A1R << 11) | (((u32)CAN->sMsgObj[1].A2R & 0x0003) << 27);
  345.     }
  346.     pCanMsg->Dlc = CAN->sMsgObj[1].MCR & 0x0F;
  347.     pCanMsg->Data[0] = (u8) CAN->sMsgObj[1].DA1R;
  348.     pCanMsg->Data[1] = (u8)(CAN->sMsgObj[1].DA1R >> 8);
  349.     pCanMsg->Data[2] = (u8) CAN->sMsgObj[1].DA2R;
  350.     pCanMsg->Data[3] = (u8)(CAN->sMsgObj[1].DA2R >> 8);
  351.     pCanMsg->Data[4] = (u8) CAN->sMsgObj[1].DB1R;
  352.     pCanMsg->Data[5] = (u8)(CAN->sMsgObj[1].DB1R >> 8);
  353.     pCanMsg->Data[6] = (u8) CAN->sMsgObj[1].DB2R;
  354.     pCanMsg->Data[7] = (u8)(CAN->sMsgObj[1].DB2R >> 8);
  355.     return 1;
  356. }
  357. /*******************************************************************************
  358. * Function Name  : CAN_WaitEndOfTx
  359. * Description    : Wait until current transmission is finished
  360. * Input          : None
  361. * Output         : None
  362. * Return         : None
  363. *******************************************************************************/
  364. void CAN_WaitEndOfTx(void)
  365. {
  366. while ((CAN->SR & CAN_SR_TXOK) == 0);
  367. CAN->SR &= ~CAN_SR_TXOK;
  368. }
  369. /*******************************************************************************
  370. * Function Name  : CAN_BasicSendMessage
  371. * Description    : Start transmission of a message in BASIC mode
  372. * Input 1        : pointer to the message structure containing data to transmit
  373. * Output         : None
  374. * Return         : 1 if transmission was OK, else 0
  375. * Note           : CAN must be in BASIC mode
  376. *******************************************************************************/
  377. u32 CAN_BasicSendMessage(canmsg* pCanMsg)
  378. {
  379. // clear NewDat bit in IF2 to detect next reception
  380. CAN->sMsgObj[1].MCR &= ~CAN_MCR_NEWDAT;
  381. CAN->SR &= ~CAN_SR_TXOK;
  382. CAN->sMsgObj[0].CMR = CAN_CMR_WRRD
  383.                        | CAN_CMR_ARB
  384.                        | CAN_CMR_CONTROL
  385.                        | CAN_CMR_DATAA
  386.                        | CAN_CMR_DATAB;
  387. if (pCanMsg->IdType == CAN_STD_ID)
  388. {
  389.    // standard ID
  390. CAN->sMsgObj[0].A1R = 0;
  391. CAN->sMsgObj[0].A2R = (CAN->sMsgObj[0].A2R & 0xE000) | STD_FIXED_ID_ARB(pCanMsg->Id);
  392. }
  393. else
  394. {
  395.    // extended ID
  396. CAN->sMsgObj[0].A1R = EXT_FIXED_ID_ARB_L(pCanMsg->Id);
  397. CAN->sMsgObj[0].A2R = (CAN->sMsgObj[0].A2R & 0xE000) | EXT_FIXED_ID_ARB_H(pCanMsg->Id);
  398. }
  399. CAN->sMsgObj[0].MCR = (CAN->sMsgObj[0].MCR & 0xFCF0) | pCanMsg->Dlc;
  400. CAN->sMsgObj[0].DA1R = ((u16)pCanMsg->Data[1]<<8) | pCanMsg->Data[0];
  401. CAN->sMsgObj[0].DA2R = ((u16)pCanMsg->Data[3]<<8) | pCanMsg->Data[2];
  402. CAN->sMsgObj[0].DB1R = ((u16)pCanMsg->Data[5]<<8) | pCanMsg->Data[4];
  403. CAN->sMsgObj[0].DB2R = ((u16)pCanMsg->Data[7]<<8) | pCanMsg->Data[6];
  404. // request transmission
  405. CAN->sMsgObj[0].CRR = CAN_CRR_BUSY | (1 + 0);
  406. return 1;
  407. }
  408. /*******************************************************************************
  409. * Function Name  : CAN_BasicReceiveMessage
  410. * Description    : Get the message in BASIC mode, if received
  411. * Input 1        : pointer to the message structure where received data is stored
  412. * Output         : None
  413. * Return         : 1 if reception was OK, else 0 (no message pending)
  414. * Note           : CAN must be in BASIC mode
  415. *******************************************************************************/
  416. u32 CAN_BasicReceiveMessage(canmsg* pCanMsg)
  417. {
  418. if ((CAN->sMsgObj[1].MCR & CAN_MCR_NEWDAT) == 0)
  419. return 0;
  420. CAN->SR &= ~CAN_SR_RXOK;
  421. CAN->sMsgObj[1].CMR =  CAN_CMR_ARB
  422.                         | CAN_CMR_CONTROL
  423.                         | CAN_CMR_DATAA
  424.                         | CAN_CMR_DATAB;
  425.     if ((CAN->sMsgObj[1].A2R & CAN_A2R_XTD) == 0)
  426.     {
  427.      // standard ID
  428.      pCanMsg->IdType = CAN_STD_ID;
  429.       pCanMsg->Id = (CAN->sMsgObj[1].A2R >> 2) & 0x07FF;
  430.     }
  431.     else
  432.     {
  433.       // extended ID
  434.      pCanMsg->IdType = CAN_EXT_ID;
  435.       pCanMsg->Id = ((CAN->sMsgObj[1].A2R >> 2) & 0x07FF) | ((u32)CAN->sMsgObj[1].A1R << 11) | (((u32)CAN->sMsgObj[1].A2R & 0x0003) << 27);
  436.     }
  437.     pCanMsg->Dlc = CAN->sMsgObj[1].MCR & 0x0F;
  438.     pCanMsg->Data[0] = (u8) CAN->sMsgObj[1].DA1R;
  439.     pCanMsg->Data[1] = (u8)(CAN->sMsgObj[1].DA1R >> 8);
  440.     pCanMsg->Data[2] = (u8) CAN->sMsgObj[1].DA2R;
  441.     pCanMsg->Data[3] = (u8)(CAN->sMsgObj[1].DA2R >> 8);
  442.     pCanMsg->Data[4] = (u8) CAN->sMsgObj[1].DB1R;
  443.     pCanMsg->Data[5] = (u8)(CAN->sMsgObj[1].DB1R >> 8);
  444.     pCanMsg->Data[6] = (u8) CAN->sMsgObj[1].DB2R;
  445.     pCanMsg->Data[7] = (u8)(CAN->sMsgObj[1].DB2R >> 8);
  446.     return 1;
  447. }
  448. /******************* (C) COPYRIGHT 2003 STMicroelectronics *****END OF FILE****/