BMS_Slave.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*********************************************************************
  2. *
  3. * BMS Slave Main File
  4. *
  5. *********************************************************************
  6. * FileName: BMS_Slave.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. *********************************************************************/
  15. /*********************************************************************
  16. *
  17. * Include Files
  18. *
  19. ********************************************************************/
  20. #include "BMS_Slave.h"
  21. /*********************************************************************
  22. *
  23. * Pragmas
  24. *
  25. *********************************************************************/
  26. #pragma config XINST = OFF
  27. #pragma config FOSC = HS1
  28. #pragma config WDTEN = OFF // SWDTDIS
  29. #pragma config WDTPS = 256 // WD TimeOut 1024ms
  30. #pragma config SOSCSEL = DIG // Port C, Pin 0 & 1 => Digital
  31. #pragma config PLLCFG = ON
  32. /*********************************************************************
  33. *
  34. * Globals
  35. *
  36. *********************************************************************/
  37. uint32_t CAN_BAL = 0;
  38. uint16_t gEvent = 0;
  39. uint8_t gCounter = 0;
  40. uint8_t MuxCounter = 0; // MuxCounter for Temp.
  41. uint8_t SlaveMode = INITIALISATION_MODE; // UI Initialisierung
  42. uint8_t Alive_Master = 0; // Alivecounter Master
  43. uint8_t Alive_Slave = 0; // Alivecounter Slave
  44. uint8_t Check_Alive_Master = 0; // Check Alivecounter Master
  45. uint8_t Count_Error_Master = 0; // Counter-Error Master
  46. uint8_t SPI_SyncFlag = SPI_SYNC_OFF;
  47. uint8_t STATE_STATUS = RUN_SLAVE;
  48. volatile uint16_t timeout_cnt=0;
  49. SERIAL_NR_t gSerial;
  50. extern ERROR_flags gERROR;
  51. /*********************************************************************
  52. *
  53. * Interrupt Vector Tabelle
  54. *
  55. *********************************************************************/
  56. #pragma code low_vetor=0x18
  57. void interrupt_at_low_vector(void)
  58. {
  59. _asm GOTO my_isr _endasm
  60. }
  61. #pragma code // Return to default code section
  62. /*********************************************************************
  63. *
  64. * Interrupt High-priority service
  65. *
  66. *********************************************************************/
  67. #pragma interrupt my_isr
  68. void my_isr( void )
  69. {
  70. static int32_t gTimeSlotCount = 0;
  71. /***** Timer 1 Code *****/
  72. if((PIE1bits.TMR1IE)&&(PIR1bits.TMR1IF))
  73. {
  74. TMR1H = 178; // reload Timer
  75. TMR1L = 0; // 10 ms bei 16 Mhz OSC
  76. PIR1bits.TMR1IF=0; // clear event flag
  77. if(!(gTimeSlotCount % 3)) // jeder 3. Interrupt ist 30ms Event
  78. gEvent |= EV__TimeSlot30ms;
  79. if(!(gTimeSlotCount % 10)) // jeder 10. Interrupt ist 100ms Event
  80. {
  81. gEvent |= EV__TimeSlot100ms;
  82. LATE ^= 2; // toggle LED_1
  83. if(SlaveMode == RUN_MODE) {
  84. timeout_cnt++;
  85. }
  86. }
  87. if(gTimeSlotCount == 5) // 1. Temperature Event
  88. gEvent |= EV__TimeSlotT;
  89. if(gTimeSlotCount == 8) // 2. Temperature Event
  90. gEvent |= EV__TimeSlotT;
  91. if(gTimeSlotCount == 11) // 3. Temperature Event
  92. gEvent |= EV__TimeSlotT;
  93. if(gTimeSlotCount == 14) // 4. Temperature Event
  94. gEvent |= EV__TimeSlotT;
  95. if(gTimeSlotCount == 17) // 5. Temperature Event
  96. gEvent |= EV__TimeSlotT;
  97. if(gTimeSlotCount == 20) // 6. Temperature Event
  98. gEvent |= EV__TimeSlotT;
  99. if(!(gTimeSlotCount % 100)) // jeder 100. Interrupt ist 1000ms Event
  100. {
  101. gEvent |= EV__TimeSlot1000ms;
  102. gTimeSlotCount = 0;
  103. }
  104. gTimeSlotCount++; // naechster Slot
  105. }
  106. if(PIR5bits.RXBnIF && PIE5bits.RXBnIE) // bei Auslösen des CAN-Empfangen-Interrupts
  107. {
  108. SPI_SyncFlag = SPI_SYNC_ON;
  109. PIR5bits.RXBnIF = 0;
  110. CAN_Write_Voltage(); // Tx CAN Spannungswerte
  111. CAN_Write_Temperature(); // Tx CAN Temperaturwerte
  112. CAN_Write_Status(); // Tx CAN Statuswerte
  113. CAN_Read_Balancing(); // CAN RX Auswertung
  114. timeout_cnt=0;
  115. gCounter++;
  116. MuxCounter++;
  117. if(gCounter >= MAX_ALIVE) // After 7 alive Counter is set to 0
  118. {
  119. gCounter = 0;
  120. }
  121. if(MuxCounter >= MAX_MUX) // After 5 Mux Counter is set to 0
  122. {
  123. MuxCounter = 0;
  124. }
  125. }
  126. }
  127. #pragma interrupt my_isr
  128. /*********************************************************************
  129. *
  130. * Intialisierung des BMS Slave
  131. *
  132. *********************************************************************/
  133. void ini( uint8_t SlaveStatus )
  134. {
  135. uint8_t RCONcopy = RCON;
  136. RCONcopy &= 0x3B; // IPEN, SBOREN und /PD wegfiltern
  137. switch(RCONcopy)
  138. {
  139. case 0x33: // Watch Dog Timer Reset
  140. ClrWdt(); // WDT Reset
  141. break;
  142. case 0x38: // Power On Reset
  143. break;
  144. case 0x3A: // Brown Out Reset
  145. break;
  146. case 0x2B: // Reset by Software
  147. break;
  148. case 0x1B: // Configuration Mismatch Reset
  149. break;
  150. default: // Stack Over/Under Flow Reset or Combinations
  151. break;
  152. }
  153. RCON |= 0x3F; // Reset Flags clear
  154. LTC_Init( );
  155. SlaveMode = SlaveStatus;
  156. }
  157. // ***** MAIN SLAVE ***************************************************************
  158. void main(void)
  159. {
  160. uint16_t PEC = 0;
  161. uint8_t EEPROM_DATA = 0;
  162. int32_t adc_value = 0;
  163. // ***** SLAVE STATUS *************************************************************
  164. switch( SlaveMode )
  165. {
  166. // ***** OFF or POWERUP ********************************************************
  167. case STANDBY_MODE :
  168. CAN_Read_Master(); // Read Master Frame
  169. if(SlaveMode == RUN_MODE)
  170. {
  171. IPR5bits.RXBnIP = 0; // 0 = make this a low priority interrupt
  172. PIE5bits.RXBnIE = 1; // enable CAN-Receive interrupt
  173. PIR5bits.RXBnIF = 0; // clear any pending events
  174. BIE0 = 0x0F;
  175. }
  176. break;
  177. // ***** SLAVE INITIALISATION ********************************************************
  178. case INITIALISATION_MODE :
  179. EEPROM_DATA = EEread(EE_START_a); // Read data from EEPROM
  180. SlaveMode = CALIBRATION_MODE;
  181. if( !(EEPROM_DATA == EE_LOAD) )
  182. {
  183. SlaveMode = RESET_MODE;
  184. }
  185. ini(SlaveMode); // Ini des BMS Slaves
  186. // Readout AN0 and AN1
  187. adc_value = ADC_supply_voltage();
  188. if( (adc_value > SUPPLY_MAX) | (adc_value < SUPPLY_MIN) )
  189. {
  190. gERROR.LIMITVOLTAGE = 1;
  191. }
  192. break;
  193. // ***** SLAVE CALIBRATION ********************************************************
  194. case CALIBRATION_MODE :
  195. PEC = LTC_SelfTest(); // Selbsttest der LTCs
  196. SlaveMode = STANDBY_MODE; // Standby Mode
  197. break;
  198. // ***** RUN MODE **************************************************************
  199. case RUN_MODE :
  200. if( gEvent & EV__TimeSlot30ms ) // wenn 30ms Slot
  201. {
  202. gEvent &= (~EV__TimeSlot30ms); // reset 30ms Flag
  203. if(gEvent & EV__LTC_V_Start)
  204. Set_LTC_TimeOut();
  205. else
  206. {
  207. gEvent |= EV__LTC_V_Start; // set Spg Messung Start
  208. }
  209. }
  210. if( gEvent & EV__TimeSlot100ms ) // wenn 100ms Slot
  211. {
  212. gEvent &= (~EV__TimeSlot100ms); // reset 100ms Flag
  213. }
  214. if( gEvent & EV__TimeSlotT ) // wenn T Slot
  215. {
  216. gEvent &= (~EV__TimeSlotT); // reset T Slot
  217. if(gEvent & EV__LTC_T_Start)
  218. Set_LTC_TimeOut();
  219. else
  220. gEvent |= EV__LTC_T_Start; // set Temperatur Messung Start
  221. }
  222. if( gEvent & EV__TimeSlot1000ms ) // wenn 1000ms Slot
  223. {
  224. gEvent &= (~EV__TimeSlot1000ms); // reset 1000ms Flag
  225. if(Count_Error_Master >= 4)
  226. {
  227. SlaveMode = ERROR_MODE; // Slave Error Case
  228. }
  229. gERROR.LIMITVOLTAGE = 0; // Clear Errorflag
  230. // Readout AN0 and AN1
  231. adc_value = ADC_supply_voltage();
  232. if( (adc_value > SUPPLY_MAX) | (adc_value < SUPPLY_MIN) )
  233. {
  234. gERROR.LIMITVOLTAGE = 1;
  235. }
  236. Count_Error_Master = 0; // clear Error Master
  237. }
  238. if( !(gEvent & ( EV__LTC_V_Wait + EV__LTC_T_Wait ))) // wenn keine Messung laeuft
  239. {
  240. if(timeout_cnt > 10) // Shutdown LTC if there is no longer response from Master
  241. {
  242. CAN_BAL = 0x00; //Set Balancing off
  243. LTC_Terminate(); //Shutdown LTC
  244. }
  245. if(SPI_SyncFlag == SPI_SYNC_ON)
  246. {
  247. SPI_SyncFlag = SPI_SYNC_OFF;
  248. LTC_SetCFG(CDC_1, CAN_BAL, ~CAN_BAL); // Set Balancing Outs
  249. }
  250. }
  251. LTC_Do(&gEvent); // Ablaufsteuerung Messung ausführen
  252. break;
  253. // ***** ERROR MODE ************************************************************
  254. case ERROR_MODE :
  255. LATE = LATE & 0xFC; // LED0, LED1 = off
  256. STATE_STATUS = RUN_SLAVE;
  257. SlaveMode = RUN_MODE;
  258. break;
  259. // ***** RESET SLAVE **************************************************************
  260. case RESET_MODE :
  261. if(STATE_STATUS == RUN_SLAVE)
  262. {
  263. LATE |= 3; // LED0, LED1 = on
  264. INTCONbits.GIE = 0; // disable Interrupt
  265. INTCONbits.PEIE = 0;
  266. PIE5bits.RXBnIE = 0; // disable CAN-Receive interrupt
  267. STATE_STATUS = UNLOCK_SYSTEM_CAN;
  268. // Unlock System Frame for autom. ID allocation
  269. ECANSetRXM0Value(0xDFF, ECAN_MSG_STD); // activate 0x300 Frame
  270. ECANSetRXF0Value(0x100, ECAN_MSG_STD); // Change start adress for new Canid
  271. }
  272. CAN_Read_System(); // CAN RX System
  273. break;
  274. // ***** PV__STAND_BY **********************************************************
  275. default :
  276. break;
  277. }
  278. ClrWdt(); // WDT Reset
  279. }