cmem7_can.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /**
  2. *****************************************************************************
  3. * @file cmem7_can.c
  4. *
  5. * @brief CMEM7 CAN source file
  6. *
  7. *
  8. * @version V1.0
  9. * @date 3. September 2013
  10. *
  11. * @note
  12. *
  13. *****************************************************************************
  14. * @attention
  15. *
  16. * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  17. * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  18. * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
  19. * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  20. * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  21. * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  22. *
  23. * <h2><center>&copy; COPYRIGHT 2013 Capital-micro </center></h2>
  24. *****************************************************************************
  25. */
  26. #include "cmem7_can.h"
  27. typedef struct {
  28. union {
  29. __IO uint8_t FI; /*!< Transmit Frame Information if writting or Receive Frame Information
  30. if reading, ACR[0] if reset mode */
  31. struct {
  32. __IO uint8_t DLC : 4; /*!< byte number in the data */
  33. uint8_t : 2;
  34. __IO uint8_t RTR : 1; /*!< 1 indicates a remote frame; 0 indicates a data frame */
  35. __IO uint8_t FF : 1; /*!< 1 selects Extended Frame Format (EFF); 0 selects Standard Frame
  36. Format (SFF) */
  37. } FI_b; /*!< BitSize */
  38. } U;
  39. } CAN_FRAME_INFO;
  40. typedef struct {
  41. union {
  42. uint16_t ID; /*!< ID */
  43. struct {
  44. uint16_t ID28_21 : 8; /*!< ID28 to ID21 */
  45. uint16_t : 4;
  46. uint16_t RTR : 1; /*!< if remote frame */
  47. uint16_t ID20_18 : 3; /*!< ID20 to ID18 */
  48. } ID_b; /*!< BitSize */
  49. } U;
  50. } CAN_STANDARD_ID;
  51. typedef struct {
  52. union {
  53. uint32_t ID; /*!< ID */
  54. struct {
  55. uint32_t ID28_21 : 8; /*!< ID28 to ID21 */
  56. uint32_t ID20_13 : 8; /*!< ID20 to ID13 */
  57. uint32_t ID12_5 : 8; /*!< ID12 to ID5 */
  58. uint32_t : 2;
  59. uint32_t RTR : 1; /*!< if remote frame */
  60. uint32_t ID4_0 : 5; /*!< ID4 to ID0 */
  61. } ID_b; /*!< BitSize */
  62. } U;
  63. } CAN_EXTENDED_ID;
  64. #define CAN_MODE_NORMAL 0x00000000
  65. #define CAN_MODE_RESET 0x00000001
  66. #define CAN_MODE_LISTEN_ONLY 0x00000002
  67. #define CAN_MODE_SELF_TEST 0x00000004
  68. #define CAN_MODE_SINGLE_FILTER 0x00000008
  69. #define CAN_MODE_SLEEP 0x00000010
  70. #define CAN_OCR_NORMAL 0x02
  71. #define CAN_OCR_CLOCK 0x03
  72. static BOOL can_SetFilter(CAN0_Type* CANx, CAN_FILTER *f1, CAN_FILTER *f2) {
  73. if (!f1) {
  74. return FALSE;
  75. }
  76. if (!IS_CAN_FLT_TYPE(f1->type)) {
  77. return FALSE;
  78. }
  79. if(IS_CAN_FLT_DUAL(f1->type)) {
  80. if (!f2 || IS_CAN_FLT_SINGLE(f2->type)) {
  81. return FALSE;
  82. }
  83. }
  84. if (f1->type == CAN_FLT_STANDARD_SINGLE) {
  85. CANx->FI_OR_ACR0 = f1->ACCEPT.sf.ID28_18 >> 3;
  86. CANx->DI0_OR_ACR1 = (f1->ACCEPT.sf.ID28_18 & 0x07) << 5;
  87. CANx->DI0_OR_ACR1 |= f1->ACCEPT.sf.RTR << 4;
  88. CANx->DI1_OR_ACR2 = f1->ACCEPT.sf.data1;
  89. CANx->DI2_OR_ACR3 = f1->ACCEPT.sf.data2;
  90. CANx->DI3_OR_AMR0 = f1->MASK.sf.ID28_18 >> 3;
  91. CANx->DI4_OR_AMR1 = (f1->MASK.sf.ID28_18 & 0x07) << 5;
  92. CANx->DI4_OR_AMR1 |= f1->MASK.sf.RTR << 4;
  93. CANx->DI5_OR_AMR2 = f1->MASK.sf.data1;
  94. CANx->DI6_OR_AMR3 = f1->MASK.sf.data2;
  95. } else if (f1->type == CAN_FLT_STANDARD_DUAL) {
  96. CANx->FI_OR_ACR0 = f1->ACCEPT.sf.ID28_18 >> 3;
  97. CANx->DI0_OR_ACR1 = (f1->ACCEPT.sf.ID28_18 & 0x07) << 5;
  98. CANx->DI0_OR_ACR1 |= f1->ACCEPT.sf.RTR << 4;
  99. CANx->DI0_OR_ACR1 |= f1->ACCEPT.sf.data1 >> 4;
  100. CANx->DI2_OR_ACR3 = f1->ACCEPT.sf.data1 & 0x0F;
  101. CANx->DI3_OR_AMR0 = f1->MASK.sf.ID28_18 >> 3;
  102. CANx->DI4_OR_AMR1 = (f1->MASK.sf.ID28_18 & 0x07) << 5;
  103. CANx->DI4_OR_AMR1 |= f1->MASK.sf.RTR << 4;
  104. CANx->DI4_OR_AMR1 = f1->MASK.sf.data1 >> 4;
  105. CANx->DI6_OR_AMR3 = f1->MASK.sf.data1 & 0x0F;
  106. } else if (f1->type == CAN_FLT_EXTENDED_SINGLE) {
  107. CANx->FI_OR_ACR0 = f1->ACCEPT.ef.ID28_13 >> 8;
  108. CANx->DI0_OR_ACR1 = f1->ACCEPT.ef.ID28_13 & 0xFF;
  109. CANx->DI1_OR_ACR2 = f1->ACCEPT.ef.ID12_0 >> 5;
  110. CANx->DI2_OR_ACR3 = (f1->ACCEPT.ef.ID12_0 & 0x1F) << 3;
  111. CANx->DI2_OR_ACR3 |= f1->ACCEPT.ef.RTR << 2;
  112. CANx->DI3_OR_AMR0 = f1->MASK.ef.ID28_13 >> 8;
  113. CANx->DI4_OR_AMR1 = f1->MASK.ef.ID28_13 & 0xFF;
  114. CANx->DI5_OR_AMR2 = f1->MASK.ef.ID12_0 >> 5;
  115. CANx->DI6_OR_AMR3 = (f1->MASK.ef.ID12_0 & 0x1F) << 3;
  116. CANx->DI6_OR_AMR3 |= f1->MASK.ef.RTR << 2;
  117. } else {
  118. CANx->FI_OR_ACR0 = f1->ACCEPT.ef.ID28_13 >> 8;
  119. CANx->DI0_OR_ACR1 = f1->ACCEPT.ef.ID28_13 & 0xFF;
  120. CANx->DI3_OR_AMR0 = f1->MASK.ef.ID28_13 >> 8;
  121. CANx->DI4_OR_AMR1 = f1->MASK.ef.ID28_13 & 0xFF;
  122. }
  123. if (IS_CAN_FLT_DUAL(f1->type)) {
  124. if (f2->type == CAN_FLT_STANDARD_DUAL) {
  125. CANx->DI1_OR_ACR2 = f2->ACCEPT.sf.ID28_18 >> 3;
  126. CANx->DI2_OR_ACR3 |= (f2->ACCEPT.sf.ID28_18 & 0x07) << 5;
  127. CANx->DI2_OR_ACR3 |= f2->ACCEPT.sf.RTR << 4;
  128. CANx->DI5_OR_AMR2 = f2->MASK.sf.ID28_18 >> 3;
  129. CANx->DI6_OR_AMR3 |= (f2->MASK.sf.ID28_18 & 0x07) << 5;
  130. CANx->DI6_OR_AMR3 |= f2->MASK.sf.RTR << 4;
  131. } else {
  132. CANx->DI1_OR_ACR2 = f2->ACCEPT.ef.ID28_13 >> 8;
  133. CANx->DI2_OR_ACR3 = f2->ACCEPT.ef.ID28_13 & 0xFF;
  134. CANx->DI5_OR_AMR2 = f2->MASK.ef.ID28_13 >> 8;
  135. CANx->DI6_OR_AMR3 = f2->MASK.ef.ID28_13 & 0xFF;
  136. }
  137. }
  138. if (IS_CAN_FLT_SINGLE(f1->type)) {
  139. CANx->MODE_b.AFM = 1;
  140. } else {
  141. CANx->MODE_b.AFM = 0;
  142. }
  143. return TRUE;
  144. }
  145. BOOL CAN_Init(CAN0_Type* CANx, CAN_InitTypeDef* Init,
  146. CAN_FILTER *f1, CAN_FILTER *f2) {
  147. assert_param(IS_CAN_ALL_PERIPH(CANx));
  148. assert_param(Init);
  149. assert_param(IS_CAN_CDR_DIV(Init->CAN_ClockDiv));
  150. /* Quit to sleep mode in operation mode */
  151. if (CANx->MODE_b.SM) {
  152. CANx->MODE_b.RM = FALSE;
  153. CANx->MODE_b.SM = FALSE;
  154. }
  155. /* switch to reset mode to set parameter */
  156. CANx->MODE_b.RM = TRUE;
  157. /* disable all interrupts and clear except receive interrupt */
  158. {
  159. uint8_t tmp;
  160. CANx->INT_EN &= ~CAN_INT_All;
  161. tmp = CANx->INT;
  162. tmp = tmp;
  163. }
  164. CANx->MODE_b.LOM = (Init->CAN_TxEn) ? FALSE : TRUE;
  165. CANx->MODE_b.STM = Init->CAN_Loopback;
  166. CANx->CDR_b.OFF = FALSE;
  167. CANx->CDR_b.DIVIDER = Init->CAN_ClockDiv;
  168. CANx->BTR0_b.BRP = Init->CAN_Prescaler;
  169. CANx->BTR0_b.SJW = Init->CAN_SJW;
  170. CANx->BTR1_b.TSEG1 = Init->CAN_TSEG1;
  171. CANx->BTR1_b.TSEG2 = Init->CAN_TSEG2;
  172. CANx->BTR1_b.SAM = !Init->CAN_HighSpeed;
  173. CANx->OCR_b.MODE = CAN_OCR_CLOCK;
  174. if (!can_SetFilter(CANx, f1, f2)) {
  175. return FALSE;
  176. }
  177. /* switch to operation mode */
  178. CANx->MODE_b.RM = FALSE;
  179. return TRUE;
  180. }
  181. void CAN_SetSleepMode(CAN0_Type* CANx, BOOL enable) {
  182. assert_param(IS_CAN_ALL_PERIPH(CANx));
  183. /* switch to operation mode */
  184. CANx->MODE_b.RM = FALSE;
  185. CANx->MODE_b.SM = enable;
  186. }
  187. void CAN_EnableInt(CAN0_Type* CANx, uint32_t Int, BOOL enable) {
  188. assert_param(IS_CAN_ALL_PERIPH(CANx));
  189. assert_param(IS_CAN_INT(Int));
  190. if (enable) {
  191. CANx->INT_EN |= CAN_INT_All;
  192. } else {
  193. CANx->INT_EN &= ~CAN_INT_All;
  194. }
  195. }
  196. uint8_t CAN_GetIntStatus(CAN0_Type* CANx) {
  197. assert_param(IS_CAN_ALL_PERIPH(CANx));
  198. return CANx->INT;
  199. }
  200. BOOL CAN_Transmit(CAN0_Type* CANx, CAN_Frame* frame) {
  201. assert_param(IS_CAN_ALL_PERIPH(CANx));
  202. if (!frame) {
  203. return FALSE;
  204. }
  205. if (CANx->MODE_b.LOM) {
  206. return FALSE;
  207. }
  208. if (CANx->MODE_b.SM) {
  209. CANx->MODE_b.RM = FALSE;
  210. CANx->MODE_b.SM = FALSE;
  211. }
  212. {
  213. CAN_FRAME_INFO fi;
  214. fi.U.FI_b.FF = !frame->SFF;
  215. fi.U.FI_b.RTR = frame->RTR;
  216. fi.U.FI_b.DLC = frame->DLC;
  217. CANx->FI_OR_ACR0 = fi.U.FI;
  218. }
  219. if (frame->SFF) {
  220. CAN_STANDARD_ID id;
  221. id.U.ID_b.ID28_21 = frame->Id >> 3;
  222. id.U.ID_b.RTR = frame->RTR;
  223. id.U.ID_b.ID20_18 = frame->Id & 0x07;
  224. CANx->DI0_OR_ACR1 = id.U.ID & 0xFF;
  225. CANx->DI1_OR_ACR2 = id.U.ID >> 8;
  226. CANx->DI2_OR_ACR3 = frame->Data[0];
  227. CANx->DI3_OR_AMR0 = frame->Data[1];
  228. CANx->DI4_OR_AMR1 = frame->Data[2];
  229. CANx->DI5_OR_AMR2 = frame->Data[3];
  230. CANx->DI6_OR_AMR3 = frame->Data[4];
  231. CANx->DI7 = frame->Data[5];
  232. CANx->DI8 = frame->Data[6];
  233. CANx->DI9 = frame->Data[7];
  234. } else {
  235. CAN_EXTENDED_ID id;
  236. id.U.ID_b.ID28_21 = frame->Id >> 21;
  237. id.U.ID_b.ID20_13 = (frame->Id >> 13) & 0xFF;
  238. id.U.ID_b.ID12_5 = (frame->Id >> 5) & 0xFF;
  239. id.U.ID_b.RTR = frame->RTR;
  240. id.U.ID_b.ID4_0 = frame->Id & 0x1F;
  241. CANx->DI0_OR_ACR1 = id.U.ID & 0xFF;
  242. CANx->DI1_OR_ACR2 = (id.U.ID >> 8) & 0xFF;
  243. CANx->DI2_OR_ACR3 = (id.U.ID >> 16) & 0xFF;
  244. CANx->DI3_OR_AMR0 = (id.U.ID >> 24) & 0xFF;
  245. CANx->DI4_OR_AMR1 = frame->Data[0];
  246. CANx->DI5_OR_AMR2 = frame->Data[1];
  247. CANx->DI6_OR_AMR3 = frame->Data[2];
  248. CANx->DI7 = frame->Data[3];
  249. CANx->DI8 = frame->Data[4];
  250. CANx->DI9 = frame->Data[5];
  251. CANx->DI10 = frame->Data[6];
  252. CANx->DI11 = frame->Data[7];
  253. }
  254. if (CANx->MODE_b.STM) {
  255. CANx->CMD_b.SSR = TRUE;
  256. } else {
  257. CANx->CMD_b.TR = TRUE;
  258. }
  259. return TRUE;
  260. }
  261. BOOL CAN_Receive(CAN0_Type* CANx, CAN_Frame* frame) {
  262. assert_param(IS_CAN_ALL_PERIPH(CANx));
  263. if (!frame) {
  264. return FALSE;
  265. }
  266. if (CANx->MODE_b.SM) {
  267. CANx->MODE_b.RM = FALSE;
  268. CANx->MODE_b.SM = FALSE;
  269. }
  270. {
  271. CAN_FRAME_INFO fi;
  272. fi.U.FI = CANx->FI_OR_ACR0;
  273. frame->SFF = fi.U.FI_b.FF ? FALSE : TRUE;
  274. frame->RTR = fi.U.FI_b.RTR ? TRUE : FALSE;
  275. frame->DLC = fi.U.FI_b.DLC;
  276. }
  277. if (frame->SFF) {
  278. CAN_STANDARD_ID id;
  279. id.U.ID = CANx->DI0_OR_ACR1;
  280. id.U.ID |= CANx->DI1_OR_ACR2 << 8;
  281. frame->Id = id.U.ID_b.ID28_21 << 3;
  282. frame->Id |= id.U.ID_b.ID20_18;
  283. frame->Data[0] = CANx->DI2_OR_ACR3;
  284. frame->Data[1] = CANx->DI3_OR_AMR0;
  285. frame->Data[2] = CANx->DI4_OR_AMR1;
  286. frame->Data[3] = CANx->DI5_OR_AMR2;
  287. frame->Data[4] = CANx->DI6_OR_AMR3;
  288. frame->Data[5] = CANx->DI7;
  289. frame->Data[6] = CANx->DI8;
  290. frame->Data[7] = CANx->DI9;
  291. } else {
  292. CAN_EXTENDED_ID id;
  293. id.U.ID = CANx->DI0_OR_ACR1;
  294. id.U.ID |= CANx->DI1_OR_ACR2 << 8;
  295. id.U.ID |= CANx->DI2_OR_ACR3 << 16;
  296. id.U.ID |= CANx->DI3_OR_AMR0 << 24;
  297. frame->Id = id.U.ID_b.ID28_21 << 21;
  298. frame->Id |= id.U.ID_b.ID20_13 << 13;
  299. frame->Id |= id.U.ID_b.ID12_5 << 5;
  300. frame->Id |= id.U.ID_b.ID4_0;
  301. frame->Data[0] = CANx->DI4_OR_AMR1;
  302. frame->Data[1] = CANx->DI5_OR_AMR2;
  303. frame->Data[2] = CANx->DI6_OR_AMR3;
  304. frame->Data[3] = CANx->DI7;
  305. frame->Data[4] = CANx->DI8;
  306. frame->Data[5] = CANx->DI9;
  307. frame->Data[6] = CANx->DI10;
  308. frame->Data[7] = CANx->DI11;
  309. }
  310. CANx->CMD_b.RRB = TRUE;
  311. return TRUE;
  312. }