BMS_CAN.c 21 KB

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