BMS_CAN.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. /*********************************************************************
  2. *
  3. * BMS_CAN File
  4. *
  5. *********************************************************************
  6. * FileName: BMS_CAN.c
  7. * Processor: PIC18F45K80
  8. * Compiler: Microchip C18 v3.41
  9. * Company: KIT - CN - IPE
  10. *
  11. * Author Date Comment
  12. *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13. * Reiling V. 04.04.2012 Release
  14. * Reiling V. 24.05.2012 Change CAN_Init() Input Parameter
  15. * Add CAN_Rx_Overrun, CAN_Rx_Passiv,
  16. * CAN_Rx_Warning, CAN_Tx_Passiv,
  17. * CAN_Tx_Warning;
  18. * Reiling V. 30.05.2012 TimeOut for Tx and Rx implemented
  19. * Reiling V. 07.11.2012 All Temp. transmit CAN_ID 0x402 add
  20. *
  21. *********************************************************************/
  22. #include "BMS_Slave.h"
  23. /*********************************************************************
  24. *
  25. * Globals
  26. *
  27. *********************************************************************/
  28. static CAN_MAILBOX gCAN_MAILBOX[11];
  29. static uint8_t gCAN_Data[8];
  30. static uint8_t gCAN_Rx_Overrun;
  31. extern SERIAL_NR_t gSerial;
  32. extern uint8_t STATE_STATUS;
  33. extern uint16_t gEvent;
  34. ERROR_flags gERROR = {0,0,0,0,0,0,0};
  35. /*********************************************************************
  36. * Function: void CAN_Init( CAN_CONFIG *config )
  37. *
  38. * Overview: API Function
  39. * Use this function to initialize ECAN module
  40. *
  41. * PreCondition: None
  42. *
  43. * Input: config
  44. *
  45. * Output: return: CAN_OK / CAN_NOK
  46. *
  47. * Side Effects: change CAN_Mailbox
  48. **********************************************************************/
  49. int8_t CAN_Init( CAN_CONFIG *config )
  50. {
  51. // Enter CAN module into config mode
  52. ECANSetOperationMode(ECAN_OP_MODE_CONFIG);
  53. // Enter CAN module into Mode 1
  54. ECANSetFunctionalMode(ECAN_MODE_1);
  55. // Initialize CAN Timing
  56. // 1 Mbps @ 64Mhz
  57. // BRP = 2, Propagation Delay =1, Phase Segment 1 = 8, Phase Segment 2 = 6
  58. // SJW = 1, Multiple bit sampling is on
  59. BRGCON1 = ((config->SJW-1) << 6) | (config->BRP-1);
  60. BRGCON2 = (config->PHSEG2_MODE << 7) | \
  61. (config->BUS_SAMPLE_MODE << 6) | \
  62. ((config->PHSEG1-1) << 3) | \
  63. (config->PROPSEG-1);
  64. BRGCON3 = (config->WAKEUP_MODE << 7) |
  65. (config->FILTER_MODE << 6) |
  66. (config->PHSEG2-1);
  67. // Setup Programmable buffers
  68. // B0 is a receive buffer AND B2,B3,B4,B5 are Transmit buffers
  69. ECANSetBnTxRxMode(B0, ECAN_BUFFER_RX);
  70. // Initialize Receive Masks
  71. // The first mask is used to accepts 0x100 Master Frame
  72. ECANSetRXM0Value(0x07FF, ECAN_MSG_STD);
  73. // Enable Filters
  74. // Only using first three filters, so the rest can be disabled.
  75. RXFCON0 = 0; //First disable all Filters
  76. RXFCON1 = 0; //First disable all Filters
  77. ECANSetRXF0Value(0x100 + config->SlaveNo, ECAN_MSG_STD); // Master --> SlaveID Frame
  78. // Assign Filters to Masks
  79. // Only two mask are used
  80. ECANLinkRXF0Thru3ToMask(ECAN_RXM0, 0xFF, 0xFF, 0xFF);
  81. // Assign Filters to Buffers
  82. // Have the first buffer only accept the first filter, the second buffer accept
  83. // the second filter, and the third buffer accept the third filter.
  84. ECANLinkRXF0F1ToBuffer(RXB0, 0xFF); //Assign Filter 0 to RXB0, and Filter 1 to RXB1
  85. ECANLinkRXF2F3ToBuffer(0xFF, 0xFF); //Assign Filter 2 to B0
  86. // Enable Port C Pin 2 for CAN capture
  87. CIOCON = 0x20; //CANCAP on
  88. // Enter CAN module into normal mode
  89. ECANSetOperationMode(ECAN_OP_MODE_NORMAL);
  90. // Set Receive Mode for buffers
  91. RXB0CON = 0x00;
  92. RXB1CON = 0x00;
  93. B0CON = 0x00;
  94. Load_Mailbox( config->SlaveNo );
  95. return CAN_OK;
  96. }
  97. /*********************************************************************
  98. * Function: int8_t CAN_Init_Mailbox( CAN_MAILBOX *mbox)
  99. *
  100. * Overview: API Function
  101. * Use this function to initialize CAN Mailbox
  102. *
  103. * PreCondition: None
  104. *
  105. * Input: *mbox
  106. *
  107. * Output: return: CAN_OK / CAN_NOK
  108. *
  109. * Side Effects: change CAN_Mailbox
  110. **********************************************************************/
  111. int8_t CAN_Init_Mailbox( CAN_MAILBOX *mbox)
  112. {
  113. uint8_t i = mbox->BOX_No;
  114. gCAN_MAILBOX[i].BOX_No = i;
  115. gCAN_MAILBOX[i].CAN_Id = mbox->CAN_Id;
  116. gCAN_MAILBOX[i].DLC = mbox->DLC;
  117. gCAN_MAILBOX[i].ACCEPTANCE_FILTER = mbox->ACCEPTANCE_FILTER;
  118. return CAN_OK;
  119. }
  120. /*********************************************************************
  121. * Function: int8_t CAN_Write( CAN_MAILBOX *mbox, uint8_t *data )
  122. *
  123. * Overview: API Function
  124. * Use this function to write Data to CAN Bus
  125. *
  126. * PreCondition: None
  127. *
  128. * Input: *mbox, *data
  129. *
  130. * Output: return: CAN_OK / CAN_NOK
  131. *
  132. * Side Effects: None
  133. **********************************************************************/
  134. int8_t CAN_Write( CAN_MAILBOX *mbox, uint8_t *data )
  135. {
  136. int8_t CAN_Status_Tx = CAN_NOK;
  137. uint8_t i=0;
  138. // 50 Fehlversuche entspricht 5,5ms oder CAN_Tx_Voltage von 8 Slaves
  139. for(i=0;i<CAN_Tx_TimeOut;i++)
  140. {
  141. CAN_Status_Tx = ECANSendMessage( mbox->CAN_Id, data, mbox->DLC, ECAN_TX_STD_FRAME);
  142. if(CAN_Status_Tx) // wenn Tx complete
  143. break; // break loop
  144. Delay100TCYx(11); // loop time ca 0,1ms => 1 CAN Telegramm bei 1MBaud
  145. }
  146. return CAN_Status_Tx;
  147. }
  148. /*********************************************************************
  149. * Function: int8_t CAN_Read( uint8_t MailBoxNo, uint8_t *data )
  150. *
  151. * Overview: API Function
  152. * Use this function to read Data from CAN Bus
  153. *
  154. * PreCondition: None
  155. *
  156. * Input: *mbox, *data
  157. *
  158. * Output: return: CAN_OK / CAN_NOK
  159. *
  160. * Side Effects: change Data
  161. **********************************************************************/
  162. int8_t CAN_Read( CAN_MAILBOX *mbox, uint8_t *data )
  163. {
  164. ECAN_RX_MSG_FLAGS flags;
  165. int8_t CAN_Status_Rx = CAN_NOK;
  166. CAN_Status_Rx = ECANReceiveMessage( &mbox->CAN_Id, data, &mbox->DLC, &flags);
  167. gCAN_Rx_Overrun = (flags & ECAN_RX_OVERFLOW);
  168. return CAN_Status_Rx;
  169. }
  170. /*********************************************************************
  171. * Function: int8_t CAN_Write_Voltage( void )
  172. *
  173. * Overview: Use this function to write Voltage Frames to CAN
  174. *
  175. * PreCondition: None
  176. *
  177. * Input: None
  178. *
  179. * Output: return: CAN_OK / CAN_NOK
  180. *
  181. * Side Effects: None
  182. **********************************************************************/
  183. int8_t CAN_Write_Voltage( void )
  184. {
  185. int8_t i=0;
  186. int8_t CAN_Status_Voltage = CAN_NOK;
  187. int16_t copyVoltage = 0;
  188. for(i=0; i<6; i++) // loop all 6 Voltage Frame
  189. {
  190. copyVoltage = LTC_GetVoltage(4*i+0);
  191. gCAN_Data[0] = ( (gCounter << 5)& 0xE0 );
  192. gCAN_Data[0] = ( (gCAN_Data[0]) | (copyVoltage >> 8) );
  193. gCAN_Data[1] = (copyVoltage & 0xFF);
  194. copyVoltage = LTC_GetVoltage(4*i+1);
  195. gCAN_Data[2] = (copyVoltage >> 8);
  196. gCAN_Data[3] = (copyVoltage & 0xFF);
  197. copyVoltage = LTC_GetVoltage(4*i+2);
  198. gCAN_Data[4] = (copyVoltage >> 8);
  199. gCAN_Data[5] = (copyVoltage & 0xFF);
  200. copyVoltage = LTC_GetVoltage(4*i+3);
  201. gCAN_Data[6] = (copyVoltage >> 8);
  202. gCAN_Data[7] = (copyVoltage & 0xFF);
  203. // Send one Frame
  204. CAN_Status_Voltage = CAN_Write( &gCAN_MAILBOX[1+i], &gCAN_Data[0] );
  205. }
  206. return CAN_Status_Voltage;
  207. }
  208. /*********************************************************************
  209. * Function: int8_t CAN_Write_Temperature( void )
  210. *
  211. * Overview: Use this function to write Temperature Frames to CAN
  212. *
  213. * PreCondition: None
  214. *
  215. * Input: None
  216. *
  217. * Output: return: CAN_OK / CAN_NOK
  218. *
  219. * Side Effects: None
  220. **********************************************************************/
  221. int8_t CAN_Write_Temperature( void )
  222. {
  223. LTC_STATUS LTC_Status;
  224. int8_t CAN_Status_Temperature = CAN_NOK;
  225. int8_t BoardTemp;
  226. LTC_GetHeatSink( &LTC_Status );
  227. BoardTemp = LTC_Status.HeatSinkTemperature;
  228. if( !((BoardTemp > BAL_TEMP_MIN) && (BoardTemp < BAL_TEMP_MAX)) )
  229. {
  230. gERROR.LIMITBOARDTEMP = 1;
  231. }
  232. gCAN_Data[0] = (( gCounter << 5 ) + (MuxCounter << 2) ); // formating dataC
  233. gCAN_Data[1] = BoardTemp;
  234. gCAN_Data[2] = LTC_GetTemperature(0 + 4 * MuxCounter);
  235. gCAN_Data[3] = LTC_GetTemperature(1 + 4 * MuxCounter);
  236. gCAN_Data[4] = LTC_GetTemperature(2 + 4 * MuxCounter);
  237. gCAN_Data[5] = LTC_GetTemperature(3 + 4 * MuxCounter);
  238. gCAN_Data[6] = 0;
  239. gCAN_Data[7] = 0;
  240. // Send first Frame
  241. CAN_Status_Temperature = CAN_Write( &gCAN_MAILBOX[8], &gCAN_Data[0] );
  242. return CAN_Status_Temperature;
  243. }
  244. /*********************************************************************
  245. * Function: int8_t CAN_Read_Master( void )
  246. *
  247. * Overview: Use this function to read Data from Master
  248. *
  249. * PreCondition: None
  250. *
  251. * Input: None
  252. *
  253. * Output: return: CAN_OK / CAN_NOK
  254. *
  255. * Side Effects: None
  256. **********************************************************************/
  257. int8_t CAN_Read_Master( void )
  258. {
  259. uint8_t data[8]; // Datenpuffer & Pufferlaenge
  260. int8_t CAN_Status = CAN_NOK;
  261. if(CAN_Read(&gCAN_MAILBOX[0], &data[0])) // lese CAN aus
  262. {
  263. CAN_Status = CAN_OK;
  264. LATE ^= 1; // wenn CAN RX toggle LED_0
  265. Alive_Master = ( (data[0] & 0xE0) >> 5 );
  266. SlaveMode = ( data[0] & 0x1F );
  267. Check_Alive_Master = Alive_Master;
  268. Check_Alive_Master++;
  269. if(Check_Alive_Master >= MAX_ALIVE)
  270. {
  271. Check_Alive_Master = 0;
  272. }
  273. }
  274. return CAN_Status;
  275. }
  276. /*********************************************************************
  277. * Function: int8_t CAN_Read_Balancing( void )
  278. *
  279. * Overview: Use this function to read Balancing Frames from CAN
  280. *
  281. * PreCondition: None
  282. *
  283. * Input: None
  284. *
  285. * Output: return: CAN_OK / CAN_NOK
  286. *
  287. * Side Effects: change Data
  288. **********************************************************************/
  289. int8_t CAN_Read_Balancing( void )
  290. {
  291. uint8_t data[8]; // Datenpuffer & Pufferlaenge
  292. int8_t CAN_Status_Balancing = CAN_NOK;
  293. if(CAN_Read(&gCAN_MAILBOX[0], &data[0])) // lese CAN aus
  294. {
  295. CAN_Status_Balancing = CAN_OK;
  296. PIR5bits.RXBnIF = 0;
  297. LATE ^= 1; // wenn CAN RX toggle LED_0
  298. Alive_Master = ( (data[0] & 0xE0) >> 5 );
  299. SlaveMode = ( data[0] & 0x1F );
  300. if( Alive_Master == Check_Alive_Master)
  301. {
  302. Check_Alive_Master++;
  303. }
  304. else
  305. {
  306. Check_Alive_Master = Alive_Master;
  307. Check_Alive_Master++;
  308. Count_Error_Master++; // Set Count Error
  309. }
  310. if(Check_Alive_Master >= MAX_ALIVE)
  311. {
  312. Check_Alive_Master = 0;
  313. }
  314. // Balancing
  315. CAN_BAL = data[3]; // Build 24 Bit Balancing Flag
  316. CAN_BAL = (CAN_BAL << 8) + data[2];
  317. CAN_BAL = (CAN_BAL << 8) + data[1];
  318. }
  319. return CAN_Status_Balancing;
  320. }
  321. /*********************************************************************
  322. * Function: int8_t CAN_Read_System( void )
  323. *
  324. * Overview: Use this function to system initialization
  325. *
  326. * PreCondition: None
  327. *
  328. * Input: None
  329. *
  330. * Output: return: CAN_OK / CAN_NOK
  331. *
  332. * Side Effects: change ID, readout seriescode
  333. **********************************************************************/
  334. int8_t CAN_Read_System( void )
  335. {
  336. uint8_t data[8]; // Datenpuffer & Pufferlaenge
  337. uint8_t IDSEARCH_check = 0x03; // XOR Checksum for IDSEARCH
  338. uint8_t SERNRPRG_check = 0x00; // XOR Checksum for SERNRPRG
  339. uint8_t GETSERNR_check = 0x0E; // XOR Checksum for GETSERNR
  340. uint8_t CHECK_temp = 0;
  341. int8_t CAN_Status_System = CAN_NOK;
  342. uint8_t DLC = 8;
  343. uint32_t id=0;
  344. ECAN_RX_MSG_FLAGS flags;
  345. uint8_t i;
  346. uint8_t DATA_temp[8];
  347. CAN_Status_System = ECANReceiveMessage( &id, data, &DLC, &flags);
  348. gCAN_Rx_Overrun = (flags & ECAN_RX_OVERFLOW);
  349. // Request with ID 0x300 from Master for IDsearch or to programm new Serialcode
  350. if(id == 0x300)
  351. {
  352. // XOR Checksum calculation
  353. // 'IDSEARCH' => 0x49 ^ 0x44 ^ 0x53 ^ 0x45 ^ 0x41 ^ 0x52 ^ 0x43 ^ 0x48 = 0x03
  354. // 'SERNRPRG' => 0x53 ^ 0x45 ^ 0x52 ^ 0x4E ^ 0x52 ^ 0x50 ^ 0x4F ^ 0x47 = 0x00
  355. // 'GETSERNR' => 0x47 ^ 0x45 ^ 0x54 ^ 0x53 ^ 0x45 ^ 0x52 ^ 0x4E ^ 0x52 = 0x0E
  356. CHECK_temp = data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4] ^ data[5] ^ data[6] ^ data[7];
  357. if(CHECK_temp == IDSEARCH_check)
  358. {
  359. STATE_STATUS = SYSTEM_IDSEARCH;
  360. gSerial.EE_BYTE.SLAVE_ID = 0x00; // Clear Canid
  361. Load_Mailbox( gSerial.EE_BYTE.SLAVE_ID ); // new slave ID canbox initialization
  362. ECANSetRXM0Value(0xDF5, ECAN_MSG_STD); // activate 0x10A and 0x30A Frame
  363. }
  364. else if(CHECK_temp == SERNRPRG_check)
  365. {
  366. STATE_STATUS = SYSTEM_SERNRPRG;
  367. ECANSetRXM0Value(0xDF6, ECAN_MSG_STD); // activate 0x308 and 0x309 Frame
  368. }
  369. else if(CHECK_temp == GETSERNR_check)
  370. {
  371. STATE_STATUS = SYSTEM_GETSERNR;
  372. }
  373. }
  374. switch(STATE_STATUS)
  375. {
  376. case SYSTEM_IDSEARCH:
  377. // Request with ID 0x10A from Master to reply with ID 0x20A from Slave
  378. if(id == 0x10A)
  379. {
  380. CAN_Write_System();
  381. }
  382. // Request with ID 0x30A from Master to save the new serialcode and deactivate
  383. // the IDs 0x10A and 0x30A
  384. if(id == 0x30A)
  385. {
  386. //Get Data from Master and save to DATA_temp
  387. for(i = 0; i < DLC; i++)
  388. {
  389. DATA_temp[i] = data[i];
  390. }
  391. if( (gSerial.EE_BYTE.LFT_1 == DATA_temp[0]) &&
  392. (gSerial.EE_BYTE.LFT_2 == DATA_temp[1]) &&
  393. (gSerial.EE_BYTE.LIEF == DATA_temp[2]) &&
  394. (gSerial.EE_BYTE.EE_REV == DATA_temp[4]) )
  395. {
  396. Load_Mailbox( DATA_temp[7] ); // new slave ID canbox initialization
  397. ECANSetRXM0Value(0xDFF, ECAN_MSG_STD); // deactivate 0x10A and 0x30A Frame
  398. EEwrite_new(0x0D, DATA_temp[7]); // write new data to EEPROM
  399. // Restart main programm
  400. SlaveMode = INITIALISATION_MODE;
  401. STATE_STATUS = RUN_SLAVE;
  402. }
  403. }
  404. break;
  405. case SYSTEM_SERNRPRG:
  406. // Request with ID 0x308 and 0x309 from System to save the new Serialcode
  407. if( (id == 0x308) | (id == 0x309))
  408. {
  409. //Get Data from Master and save to DATA_temp
  410. for(i = 0; i < DLC; i++)
  411. {
  412. DATA_temp[i] = data[i];
  413. }
  414. if(id == 0x308)
  415. {
  416. EEwrite(EE_308_a, &DATA_temp[0] ); // Write initialization data to EEPROM
  417. }
  418. else if(id == 0x309)
  419. {
  420. EEwrite(EE_309_a, &DATA_temp[0] ); // Write initialization data to EEPROM
  421. // Restart main programm
  422. SlaveMode = INITIALISATION_MODE;
  423. STATE_STATUS = RUN_SLAVE;
  424. }
  425. }
  426. break;
  427. case SYSTEM_GETSERNR:
  428. // Reply with ID 0x2XA from Slave to Master
  429. CAN_Write_System();
  430. // Restart main programm
  431. SlaveMode = INITIALISATION_MODE;
  432. STATE_STATUS = RUN_SLAVE;
  433. break;
  434. default:
  435. break;
  436. }
  437. return CAN_Status_System;
  438. }
  439. /*********************************************************************
  440. * Function: int8_t CAN_Write_System( void )
  441. *
  442. * Overview: Use this function to write Serialframe to Master
  443. *
  444. * PreCondition: None
  445. *
  446. * Input: None
  447. *
  448. * Output: return: CAN_OK / CAN_NOK
  449. *
  450. * Side Effects: None
  451. **********************************************************************/
  452. int8_t CAN_Write_System( void )
  453. {
  454. int8_t CAN_Status_System = CAN_NOK;
  455. uint16_t DELAY_t = 0;
  456. uint16_t i_time = 0;
  457. uint8_t Delay_256us = 4;
  458. gCAN_Data[0]= gSerial.EE_BYTE.LFT_1;
  459. gCAN_Data[1]= gSerial.EE_BYTE.LFT_2;
  460. gCAN_Data[2]= gSerial.EE_BYTE.LIEF;
  461. gCAN_Data[3]= gSerial.EE_BYTE.BAU_1;
  462. gCAN_Data[4]= gSerial.EE_BYTE.EE_REV;
  463. gCAN_Data[5]= gSerial.EE_BYTE.FAM_1;
  464. gCAN_Data[6]= gSerial.EE_BYTE.GERAET;
  465. gCAN_Data[7]= gSerial.EE_BYTE.LAEN;
  466. // LFT1(LSB) and LFT2(MSB) to 16 Bit DELAY_t value
  467. DELAY_t = gSerial.EE_BYTE.LFT_2;
  468. DELAY_t = DELAY_t << 8;
  469. DELAY_t = DELAY_t | gSerial.EE_BYTE.LFT_1;
  470. // Delay_t 0 - 9999 --> 1 - 10000
  471. DELAY_t++;
  472. // Generate delay time with 8 Bit Delay1KTCYx(Delay_256us) function
  473. while(i_time <= DELAY_t )
  474. {
  475. Delay1KTCYx(Delay_256us);
  476. i_time++;
  477. }
  478. CAN_Status_System = CAN_Write( &gCAN_MAILBOX[9], &gCAN_Data[0] );
  479. return CAN_Status_System;
  480. }
  481. /*********************************************************************
  482. * Function: int8_t CAN_Write_Status( void )
  483. *
  484. * Overview: Use this function to write Status Frames to CAN
  485. *
  486. * PreCondition: None
  487. *
  488. * Input: None
  489. *
  490. * Output: return: CAN_OK / CAN_NOK
  491. *
  492. * Side Effects: None
  493. **********************************************************************/
  494. int8_t CAN_Write_Status( void )
  495. {
  496. LTC_STATUS LTC_Status;
  497. int8_t CAN_Status_Status = CAN_NOK;
  498. gERROR.SLAVE_SPI = 0;
  499. gERROR.SLAVE_TIMING = 0;
  500. gERROR.SLAVE_HARDWARE = 0;
  501. LTC_GetStatus( &LTC_Status ); // read LTC Status
  502. gERROR.SLAVE_TIMING = (LTC_Status.LTC_StatusSlave & 0x40) >> 6;
  503. if (LTC_Status.LTC_SelfTest >= 0x0001)
  504. {
  505. gERROR.SLAVE_HARDWARE = 1;
  506. }
  507. gCAN_Data[0] = 0x00;
  508. gCAN_Data[0] = (( gCounter << 5 ) + SlaveMode );
  509. gCAN_Data[1] = 0x00;
  510. gCAN_Data[1] = (gERROR.LIMITVOLTAGE << 6);
  511. gCAN_Data[1] |= (gERROR.SLAVE_SPI << 5); // Onboard comunication Fail
  512. gCAN_Data[1] |= (gERROR.SLAVE_TIMING << 4); // Measure Timing Error
  513. gCAN_Data[1] |= (gERROR.SLAVE_HARDWARE << 3); // ADC / MUX / REF Error
  514. gCAN_Data[1] |= (gERROR.LIMITBOARDTEMP << 2);
  515. gCAN_Data[1] |= (gERROR.LIMITCELLTEMP << 1);
  516. gCAN_Data[1] |= (gERROR.LIMITCELLVOLTAGE);
  517. gCAN_Data[2] = 0;
  518. gCAN_Data[3] = 0;
  519. gCAN_Data[4] = 0;
  520. gCAN_Data[5] = 0;
  521. gCAN_Data[6] = 0;
  522. gCAN_Data[7] = 0;
  523. // send one Status Frame
  524. CAN_Status_Status = CAN_Write( &gCAN_MAILBOX[7], &gCAN_Data[0] );
  525. return CAN_Status_Status;
  526. }
  527. /*********************************************************************
  528. * Function: int8_t Load_Mailbox( uint8_t SlaveNo )
  529. *
  530. * Overview: Use this function to initialize all CAN Mailboxes
  531. *
  532. * PreCondition: None
  533. *
  534. * Input: SlaveNo
  535. *
  536. * Output: return: CAN_OK / CAN_NOK
  537. *
  538. * Side Effects: change CAN_Mailbox
  539. **********************************************************************/
  540. int8_t Load_Mailbox( uint8_t SlaveNo )
  541. {
  542. gCAN_MAILBOX[0].BOX_No = 0; // Balancing Frame 1
  543. gCAN_MAILBOX[0].CAN_Id = 0x100+SlaveNo;
  544. gCAN_MAILBOX[0].DLC = 5;
  545. gCAN_MAILBOX[0].ACCEPTANCE_FILTER = 0x100+SlaveNo;
  546. gCAN_MAILBOX[1].BOX_No = 1; // Voltage Frame 1
  547. gCAN_MAILBOX[1].CAN_Id = 0x200+SlaveNo;
  548. gCAN_MAILBOX[1].DLC = 8;
  549. gCAN_MAILBOX[1].ACCEPTANCE_FILTER = 0;
  550. gCAN_MAILBOX[2].BOX_No = 2; // Voltage Frame 2
  551. gCAN_MAILBOX[2].CAN_Id = 0x201+SlaveNo;
  552. gCAN_MAILBOX[2].DLC = 8;
  553. gCAN_MAILBOX[2].ACCEPTANCE_FILTER = 0;
  554. gCAN_MAILBOX[3].BOX_No = 3; // Voltage Frame 3
  555. gCAN_MAILBOX[3].CAN_Id = 0x202+SlaveNo;
  556. gCAN_MAILBOX[3].DLC = 8;
  557. gCAN_MAILBOX[3].ACCEPTANCE_FILTER = 0;
  558. gCAN_MAILBOX[4].BOX_No = 4; // Voltage Frame 4
  559. gCAN_MAILBOX[4].CAN_Id = 0x203+SlaveNo;
  560. gCAN_MAILBOX[4].DLC = 8;
  561. gCAN_MAILBOX[4].ACCEPTANCE_FILTER = 0;
  562. gCAN_MAILBOX[5].BOX_No = 5; // Voltage Frame 5
  563. gCAN_MAILBOX[5].CAN_Id = 0x204+SlaveNo;
  564. gCAN_MAILBOX[5].DLC = 8;
  565. gCAN_MAILBOX[5].ACCEPTANCE_FILTER = 0;
  566. gCAN_MAILBOX[6].BOX_No = 6; // Voltage Frame 6
  567. gCAN_MAILBOX[6].CAN_Id = 0x205+SlaveNo;
  568. gCAN_MAILBOX[6].DLC = 8;
  569. gCAN_MAILBOX[6].ACCEPTANCE_FILTER = 0;
  570. gCAN_MAILBOX[7].BOX_No = 7; // Status Frame
  571. gCAN_MAILBOX[7].CAN_Id = 0x206+SlaveNo;
  572. gCAN_MAILBOX[7].DLC = 8;
  573. gCAN_MAILBOX[7].ACCEPTANCE_FILTER = 0;
  574. gCAN_MAILBOX[8].BOX_No = 8; // Temperature Frame
  575. gCAN_MAILBOX[8].CAN_Id = 0x207+SlaveNo;
  576. gCAN_MAILBOX[8].DLC = 8;
  577. gCAN_MAILBOX[8].ACCEPTANCE_FILTER = 0;
  578. gCAN_MAILBOX[9].BOX_No = 8; // Serialcode Frame
  579. gCAN_MAILBOX[9].CAN_Id = 0x20A+SlaveNo;
  580. gCAN_MAILBOX[9].DLC = 8;
  581. gCAN_MAILBOX[9].ACCEPTANCE_FILTER = 0;
  582. return CAN_OK;
  583. }