BMS_LTC.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219
  1. /*********************************************************************
  2. *
  3. * LTC6803 API File
  4. *
  5. *********************************************************************
  6. * FileName: MBS_LTC.c
  7. * Processor: PIC18F45K80
  8. * Compiler: Microchip C18 v3.41
  9. * Company: KIT - CN - IPE
  10. *
  11. * Author Date Comment
  12. *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13. * Reiling V. 17.02.2012 Release
  14. * Reiling V. 27.02.2012 Debug: Odd Voltage = 0V
  15. * Reiling V. 29.03.2012 Release 2. see change log file
  16. *********************************************************************/
  17. #include "BMS_Slave.h"
  18. /*********************************************************************
  19. *
  20. * Globals
  21. *
  22. *********************************************************************/
  23. static LTC_CFG gCFG;
  24. static LTC_CVAD gCVAD;
  25. static LTC_TMP gTMP;
  26. static LTC_DRG gDRG;
  27. static uint16_t gLTC_SelfTest_Result = LTC_OK;
  28. static uint16_t gLTC_TimeOut = LTC_OK;
  29. extern SERIAL_NR_t gSerial;
  30. extern ERROR_flags gERROR;
  31. extern LTC_STATUS LTC_Status;
  32. /*********************************************************************
  33. * Function: void LTC_Init( void )
  34. *
  35. * Overview: API Function
  36. * Use this function to initialize LTC6803 module
  37. *
  38. * PreCondition: None
  39. *
  40. * Input: None
  41. *
  42. * Output: Return: LTC_OK,
  43. *
  44. * Side Effects: Change gCFG
  45. **********************************************************************/
  46. void LTC_Init( void )
  47. {
  48. int8_t i = 0;
  49. CAN_CONFIG gCAN_CONFIG ={ SlaveNo_VAL,
  50. BRP_VAL,
  51. PROPSEG_VAL,
  52. PHSEG1_VAL,
  53. PHSEG2_VAL,
  54. SJW_VAL,
  55. PHSEG2_MODE_VAL,
  56. BUS_SAMPLE_MODE_VAL,
  57. WAKEUP_MODE_VAL,
  58. FILTER_MODE_VAL };
  59. OSCCONbits.IRCF0 = 0; // 2MHz Prescaler für SPI
  60. OSCCONbits.IRCF1 = 1;
  61. OSCCONbits.IRCF2 = 1;
  62. OSCTUNEbits.PLLEN = 0; // PLL on
  63. // 12 Bit ADC Settings
  64. ADCON0 = 0x00; // Clear ADCON0 register
  65. ADCON1 = 0x30; // Internal Vref+ = 4,1V, Vreg- = 0V
  66. ADCON2 = 0x92; // right justifield, 4Tad, Fosc/32
  67. ANCON0 = 0x0B; // AN0 and AN1 and AN3 as analog inputs
  68. ANCON1 = 0x00;
  69. ADCON0bits.ADON = 0x01; //Enable A/D module
  70. TRISAbits.TRISA0 = 1; // PortA.0 = Analog In
  71. TRISAbits.TRISA1 = 1; // PortA.1 = Analog In
  72. TRISAbits.TRISA3 = 1; // PortA.3 = Analog In (Balancing Temperature)
  73. LATAbits.LATA5 = 1; // LTC SPI CS OFF
  74. TRISAbits.TRISA5 = 0; // Output LTC SPI CS
  75. TRISB = 0xFB; // Port B Input (PB.2 = CAN_1_TX Output)
  76. TRISCbits.TRISC0 = 0; // Output MUX 0,1,2
  77. TRISCbits.TRISC1 = 0;
  78. TRISCbits.TRISC2 = 0;
  79. LATD = 0; // Port D alle Latches off
  80. TRISD = 0; // Port D Output
  81. TRISEbits.TRISE0 = 0; // Out LED0
  82. TRISEbits.TRISE1 = 0; // Out LED1
  83. LATE |= 3; // LED0 = on; LED1 = on
  84. LATC = LATC & 0xF8; // Clear C0,C1,C2
  85. LATC |= 1; // Set MUX Counter = 1 to avoid MUX input = 0
  86. InitSPI();
  87. InitTimer();
  88. //gCAN_CONFIG.SlaveNo = ((PORTB >> 2) & 0xC);
  89. //gCAN_CONFIG.SlaveNo += (PORTB & 0x3);
  90. //gCAN_CONFIG.SlaveNo <<= 4;
  91. //gCAN_CONFIG.SlaveNo ^= 0xF0; //!! entfällt bei eWolf
  92. //gSerial.SLAVE_ID = gCAN_CONFIG.SlaveNo;
  93. gCAN_CONFIG.SlaveNo = gSerial.EE_BYTE.SLAVE_ID;
  94. CAN_Init( &gCAN_CONFIG );
  95. for(i=0;i<24;i++) // Start Voltage and Temperature with 0xFFFF / 0xFF
  96. {
  97. gCVAD.CVAD[i] = -1; // init. value for voltage => not connected
  98. gTMP.ETMP[i] = -51; // init. value for temperature => not connected
  99. }
  100. // Config LTC6803, Run Mode, Balancing OFF
  101. LTC_SetCFG(CDC_1, 0, 0x0FFFFFF );
  102. gDRG.PEC_Counter = 0; // Com Error Counter ini
  103. INTCONbits.GIE = 1;
  104. INTCONbits.PEIE = 1;
  105. }
  106. /*********************************************************************
  107. * Function: void LTC_Do( uint16_t *gEvent)
  108. *
  109. * Overview: API Function
  110. * Use this function to run LTC6803 module
  111. *
  112. * PreCondition: LTC_Init()
  113. *
  114. * Input: Pointer to gEvent
  115. *
  116. * Output: None
  117. *
  118. * Side Effects: Change gCVAD, gTMP, gDRG
  119. **********************************************************************/
  120. void LTC_Do(uint16_t *ptr_gEvent)
  121. {
  122. int8_t MUXcopy = 0;
  123. if(*ptr_gEvent & EV__LTC_V_Start)
  124. {
  125. if(PORTC & LTC_ADC_Ready) // ADC not running
  126. {
  127. if(LTC_MeasureVoltage( STCVAD_ALL, STCVAD_ALL_PEC, EV__LTC_V_Start ))
  128. gDRG.PEC_Counter++;
  129. *ptr_gEvent &= (~EV__LTC_V_Start);
  130. *ptr_gEvent |= EV__LTC_V_Wait;
  131. }
  132. }
  133. if(*ptr_gEvent & EV__LTC_V_Wait)
  134. {
  135. if(PORTC & LTC_ADC_Ready) // ADC not running
  136. {
  137. if(LTC_MeasureVoltage( STCVAD_ALL, STCVAD_ALL_PEC, EV__LTC_V_Wait ))
  138. gDRG.PEC_Counter++;
  139. *ptr_gEvent &= (~EV__LTC_V_Wait);
  140. }
  141. }
  142. if(*ptr_gEvent & EV__LTC_T_Start)
  143. {
  144. if(PORTC & LTC_ADC_Ready) // ADC not running
  145. {
  146. if(LTC_MeasureTemperature( STTMPAD_ALL, STTMPAD_ALL_PEC, EV__LTC_T_Start ))
  147. gDRG.PEC_Counter++;
  148. *ptr_gEvent |= EV__LTC_T_Wait;
  149. *ptr_gEvent &= (~EV__LTC_T_Start);
  150. }
  151. }
  152. if(*ptr_gEvent & EV__LTC_T_Wait)
  153. {
  154. if(PORTC & LTC_ADC_Ready) // ADC not running
  155. {
  156. if(LTC_MeasureTemperature( STTMPAD_ALL, STTMPAD_ALL_PEC, EV__LTC_T_Wait ))
  157. gDRG.PEC_Counter++;
  158. //IMPORTANT: RCT Power Version to avoid MUX INPUT = 0
  159. MUXcopy = LATC & 0x07; // extract MUX
  160. LATC = LATC & 0xF8; // clear old MUX
  161. if( MUXcopy < 6)
  162. {
  163. LATC = (LATC | MUXcopy) + 1; // set new MUX
  164. }
  165. else
  166. {
  167. LATC = 0x01; // Set Mux Counter = 1
  168. }
  169. *ptr_gEvent &= (~EV__LTC_T_Wait);
  170. }
  171. }
  172. }
  173. /*********************************************************************
  174. * Function: void LTC_BalanceOn(uint8_t No)
  175. *
  176. * Overview: API Function
  177. * Use this function to start Balancing Cell No
  178. * thru LTC6803 module
  179. *
  180. * PreCondition: None
  181. *
  182. * Input: Number of Cell to Balance
  183. *
  184. * Output: None
  185. *
  186. * Side Effects: None
  187. **********************************************************************/
  188. void LTC_BalanceOn(uint8_t No)
  189. {
  190. uint32_t DCC = 1; // Start for Shift
  191. DCC = DCC << No; // Shift Bitmask into Position
  192. LTC_SetCFG(CDC_1, DCC, 0);
  193. }
  194. /*********************************************************************
  195. * Function: void LTC_BalanceOff(uint8_t No)
  196. *
  197. * Overview: API Function
  198. * Use this function to stop Balancing Cell(n)
  199. * thru LTC6803 module
  200. *
  201. * PreCondition: None
  202. *
  203. * Input: Number of Cell to Balance
  204. *
  205. * Output: None
  206. *
  207. * Side Effects: None
  208. **********************************************************************/
  209. void LTC_BalanceOff(uint8_t No)
  210. {
  211. uint32_t DCC = 1; // Start for Shift
  212. DCC = DCC << No; // Shift Bitmask into Position
  213. LTC_SetCFG(CDC_1, 0, DCC);
  214. }
  215. /*********************************************************************
  216. * Function: void LTC_Terminate(void)
  217. *
  218. * Overview: API Function
  219. * Use this function to End LTC6803 module
  220. *
  221. * PreCondition: None
  222. *
  223. * Input: None
  224. *
  225. * Output: None
  226. *
  227. * Side Effects: None
  228. ********************************************************************/
  229. void LTC_Terminate(void)
  230. {
  231. LTC_SetCFG(CDC_0, 0, 0x0FFF); // LTC StandBy, Balance OFF
  232. }
  233. /*********************************************************************
  234. * Function: int16_t LTC_GetVoltage(uint8_t No)
  235. *
  236. * Overview: API Funktion
  237. * Use this function to read out one Cell Voltage
  238. *
  239. * PreCondition: None
  240. *
  241. * Input: Number of Cell to read out Voltage
  242. *
  243. * Output: Cell Voltage
  244. *
  245. * Side Effects: None
  246. ********************************************************************/
  247. int16_t LTC_GetVoltage(uint8_t No)
  248. {
  249. int16_t copyCVAD = gCVAD.CVAD[No];
  250. if (gERROR.LIMITCELLVOLTAGE == 0)
  251. {
  252. if(copyCVAD >= CELL_BYPASSED)
  253. {
  254. if( !((copyCVAD > VOLTAGE_MIN) && (copyCVAD < VOLTAGE_MAX)) )
  255. {
  256. gERROR.LIMITCELLVOLTAGE = 1;
  257. }
  258. }
  259. }
  260. gCVAD.CVAD[No] = -1;
  261. return copyCVAD;
  262. }
  263. /*********************************************************************
  264. * Function: int16_t LTC_GetTemperature(uint8_t No)
  265. *
  266. * Overview: API Funktion
  267. * Use this function to read out one Temperature Sensor
  268. *
  269. * PreCondition: None
  270. *
  271. * Input: Number of Sensor to read out Temperature
  272. *
  273. * Output: Sensor Temperature
  274. *
  275. * Side Effects: None
  276. ********************************************************************/
  277. int16_t LTC_GetTemperature(uint8_t No)
  278. {
  279. int8_t copyETMP = gTMP.ETMP[No];
  280. if (gERROR.LIMITCELLTEMP == 0)
  281. {
  282. if( (copyETMP >= TEMP_NOT_CON) )
  283. {
  284. if( !((copyETMP > TEMP_MIN) && (copyETMP < TEMP_MAX)) )
  285. {
  286. gERROR.LIMITCELLTEMP = 1;
  287. }
  288. }
  289. }
  290. gTMP.ETMP[No] = -51;
  291. return copyETMP;
  292. }
  293. /*********************************************************************
  294. * Function: void LTC_GetStatus( LTC_STATUS *LTC_Status )
  295. *
  296. * Overview: API Funktion
  297. * Show LTC_Status, PEC Counter and LTC_SelfTest
  298. *
  299. * PreCondition: None
  300. *
  301. * Input: Global gDRG, PEC_Counter, gLTC_SelfTest_Result, gLTC_TimeOut
  302. *
  303. * Output: None
  304. *
  305. *
  306. * Side Effects: Reset gDRG.PEC_Counter, change LTC_Status
  307. ********************************************************************/
  308. void LTC_GetStatus( LTC_STATUS *LTC_Status )
  309. {
  310. // Build LTC_StatusSlave
  311. LTC_Status->LTC_StatusSlave = LTC_OK;
  312. if(gTMP.ITMP[0] < WarnLowTemp)
  313. LTC_Status->LTC_StatusSlave |= LTC1_LowTemp_NOK;
  314. if(gTMP.ITMP[1] < WarnLowTemp)
  315. LTC_Status->LTC_StatusSlave |= LTC2_LowTemp_NOK;
  316. if(gTMP.ITMP[0] > WarnHighTemp)
  317. LTC_Status->LTC_StatusSlave |= LTC1_HighTemp_NOK;
  318. if(gTMP.ITMP[1] > WarnHighTemp)
  319. LTC_Status->LTC_StatusSlave |= LTC2_HighTemp_NOK;
  320. if(gTMP.THSD[0])
  321. LTC_Status->LTC_StatusSlave |= LTC1_THSD_NOK;
  322. if(gTMP.THSD[1])
  323. LTC_Status->LTC_StatusSlave |= LTC2_THSD_NOK;
  324. if(gLTC_TimeOut)
  325. LTC_Status->LTC_StatusSlave |= LTC_TimeOut;
  326. gLTC_TimeOut = LTC_OK;
  327. if(gDRG.PEC_Counter)
  328. LTC_Status->LTC_StatusSlave |= LTC_PEC_NOK;
  329. if(!(PORTA & 0x04) )
  330. LTC_Status->LTC_StatusSlave |= RELAIS_ON;
  331. // Build LTC_PECFailCounter
  332. LTC_Status->LTC_PECFailCounter = gDRG.PEC_Counter;
  333. gDRG.PEC_Counter = 0; // Reset Error Counter after readout
  334. // Build LTC_SelfTest
  335. LTC_Status->LTC_SelfTest = gLTC_SelfTest_Result;
  336. }
  337. /*********************************************************************
  338. * Function: void LTC_GetHeatSink( LTC_STATUS *LTC_Status )
  339. *
  340. * Overview: API Funktion
  341. * Show HeatSinkTemperature
  342. *
  343. * PreCondition: None
  344. *
  345. * Input: Global gDRG
  346. *
  347. * Output: None
  348. *
  349. *
  350. * Side Effects: change LTC_Status
  351. ********************************************************************/
  352. void LTC_GetHeatSink( LTC_STATUS *LTC_Status )
  353. {
  354. int16_t HeatSinkTemp = 0;
  355. ADCON0bits.CHS = 3; // Set adc channel to read
  356. ADCON0bits.GO = 1; //Start A/D Conversion
  357. while(ADCON0bits.GO == 1)
  358. {
  359. //Loop here until A/D conversion completes
  360. };
  361. HeatSinkTemp = ( (((uint16_t)ADRESH << 8)+ADRESL)); // readout ADC
  362. HeatSinkTemp -= 500; // correct 0°C Offset
  363. HeatSinkTemp /= 10; // correct Slope
  364. LTC_Status->HeatSinkTemperature = (int8_t)HeatSinkTemp;
  365. }
  366. /*********************************************************************
  367. * Function: uint16_t LTC_SelfTest( void )
  368. *
  369. * Overview: API Funktion
  370. * Use this function to Self Test LTC6803
  371. *
  372. * PreCondition: LTC_Init()
  373. *
  374. * Input: none
  375. *
  376. * Output: LTC_OK, LTC1_VST1_NOK, LTC1_VST2_NOK, LTC1_VST1_NOK, LTC1_VST2_NOK,
  377. * LTC1_TST1_NOK, LTC1_TST2_NOK, LTC2_TST1_NOK, LTC2_TST2_NOK,
  378. * LTC1_RefL_NOK, LTC1_RefH_NOK, LTC2_RefL_NOK, LTC2_RefH_NOK,
  379. * LTC1_MUX_NOK, LTC2_MUX_NOK, LTC_PEC_NOK
  380. *
  381. * Side Effects: ~85ms stall
  382. ********************************************************************/
  383. uint16_t LTC_SelfTest( void )
  384. {
  385. int8_t i = 0;
  386. gLTC_SelfTest_Result = LTC_OK;
  387. // Spannungsmessung im SelfTest1 dh alle Datenbyte müssen 0x55 sein
  388. Delay10KTCYx(96);
  389. LTC_MeasureVoltage( STCVAD_ST1, STCVAD_ST1_PEC, EV__LTC_V_Start );
  390. Delay10KTCYx(96);
  391. if(LTC_MeasureVoltage( STCVAD_ST1, STCVAD_ST1_PEC, EV__LTC_V_Wait ))
  392. gLTC_SelfTest_Result |= LTC_PEC_NOK;
  393. else
  394. {
  395. for(i=2; i<20; i++)
  396. {
  397. if(gCVAD.LTC_CVAD_RAW[i] == (0x55 || 0xAA ))
  398. gLTC_SelfTest_Result |= LTC1_VST1_NOK;
  399. if(gCVAD.LTC_CVAD_RAW[i+19] == (0x55 || 0xAA ))
  400. gLTC_SelfTest_Result |= LTC2_VST1_NOK;
  401. }
  402. }
  403. // Spannungsmessung im SelfTest2 dh alle Datenbyte müssen 0xAA sein
  404. LTC_MeasureVoltage( STCVAD_ST2, STCVAD_ST2_PEC, EV__LTC_V_Start );
  405. Delay10KTCYx(96);
  406. if(LTC_MeasureVoltage( STCVAD_ST2, STCVAD_ST2_PEC, EV__LTC_V_Wait ))
  407. {
  408. gLTC_SelfTest_Result |= LTC_PEC_NOK;
  409. }
  410. else
  411. {
  412. for(i=2; i<20; i++)
  413. {
  414. if(gCVAD.LTC_CVAD_RAW[i] == (0x55 || 0xAA ))
  415. gLTC_SelfTest_Result |= LTC1_VST2_NOK;
  416. if(gCVAD.LTC_CVAD_RAW[i+19] == (0x55 || 0xAA ))
  417. gLTC_SelfTest_Result |= LTC2_VST2_NOK;
  418. }
  419. }
  420. // Normale Spannungsmessung um SelfTest zu beenden
  421. LTC_MeasureVoltage( STCVAD_ALL, STCVAD_ALL_PEC, EV__LTC_V_Start );
  422. Delay10KTCYx(96);
  423. if(LTC_MeasureVoltage( STCVAD_ALL, STCVAD_ALL_PEC, EV__LTC_V_Wait )) //Reset Self Test
  424. gLTC_SelfTest_Result |= LTC_PEC_NOK;
  425. // Temperaturmessung im SelfTest1 dh alle Datenbyte müssen 0x55 sein
  426. LTC_MeasureTemperature( STTMPAD_ST1, STTMPAD_ST1_PEC, EV__LTC_T_Start );
  427. Delay10KTCYx(20);
  428. if(LTC_MeasureTemperature( STTMPAD_ST1, STTMPAD_ST1_PEC, EV__LTC_T_Wait ))
  429. {
  430. gLTC_SelfTest_Result |= LTC_PEC_NOK;
  431. }
  432. else
  433. {
  434. for(i=2; i<6; i++)
  435. {
  436. if(gTMP.LTC_TMP_RAW[i] == (0x55 || 0xAA ))
  437. gLTC_SelfTest_Result |= LTC1_TST1_NOK;
  438. if(gTMP.LTC_TMP_RAW[i+6] == (0x55 || 0xAA ))
  439. gLTC_SelfTest_Result |= LTC2_TST1_NOK;
  440. }
  441. if(gTMP.LTC_TMP_RAW[6] == (0x05 || 0x0A ))
  442. gLTC_SelfTest_Result |= LTC1_TST1_NOK;
  443. if(gTMP.LTC_TMP_RAW[12] == (0x05 || 0x0A ))
  444. gLTC_SelfTest_Result |= LTC2_TST1_NOK;
  445. }
  446. // Temperaturmessung im SelfTest2 dh alle Datenbyte müssen 0xAA sein
  447. LTC_MeasureTemperature( STTMPAD_ST2, STTMPAD_ST2_PEC, EV__LTC_T_Start );
  448. Delay10KTCYx(20);
  449. if(LTC_MeasureTemperature( STTMPAD_ST2, STTMPAD_ST2_PEC, EV__LTC_T_Wait ))
  450. {
  451. gLTC_SelfTest_Result |= LTC_PEC_NOK;
  452. }
  453. else
  454. {
  455. for(i=2; i<6; i++)
  456. {
  457. if(gTMP.LTC_TMP_RAW[i] == (0x55 || 0xAA ))
  458. gLTC_SelfTest_Result |= LTC1_TST2_NOK;
  459. if(gTMP.LTC_TMP_RAW[i+6] == (0x55 || 0xAA ))
  460. gLTC_SelfTest_Result |= LTC2_TST2_NOK;
  461. }
  462. if(gTMP.LTC_TMP_RAW[6] == (0x05 || 0x0A ))
  463. gLTC_SelfTest_Result |= LTC1_TST2_NOK;
  464. if(gTMP.LTC_TMP_RAW[12] == (0x05 || 0x0A ))
  465. gLTC_SelfTest_Result |= LTC2_TST2_NOK;
  466. }
  467. // Normale Temperaturmessung um SelfTest zu beenden
  468. LTC_MeasureTemperature( STTMPAD_ALL, STTMPAD_ALL_PEC, EV__LTC_T_Start ); // Reset Self Test
  469. Delay10KTCYx(20);
  470. if(LTC_MeasureTemperature( STTMPAD_ALL, STTMPAD_ALL_PEC, EV__LTC_T_Wait ))
  471. gLTC_SelfTest_Result |= LTC_PEC_NOK;
  472. // Normale StatusAbfrage
  473. LTC_MeasureDiag( EV__LTC_S_Start );
  474. Delay10KTCYx(110);
  475. if(LTC_MeasureDiag( EV__LTC_S_Wait ))
  476. {
  477. gLTC_SelfTest_Result |= LTC_PEC_NOK;
  478. }
  479. else
  480. {
  481. if(gDRG.REF[0]<2100)
  482. gLTC_SelfTest_Result |= LTC1_RefL_NOK;
  483. if(gDRG.REF[0]>2900)
  484. gLTC_SelfTest_Result |= LTC1_RefH_NOK;
  485. if(gDRG.MUXFAIL[0])
  486. gLTC_SelfTest_Result |= LTC1_MUX_NOK;
  487. if(gDRG.REF[1]<2100)
  488. gLTC_SelfTest_Result |= LTC2_RefL_NOK;
  489. if(gDRG.REF[1]>2900)
  490. gLTC_SelfTest_Result |= LTC2_RefH_NOK;
  491. if(gDRG.MUXFAIL[1])
  492. gLTC_SelfTest_Result |= LTC2_MUX_NOK;
  493. }
  494. return gLTC_SelfTest_Result;
  495. }
  496. /*********************************************************************
  497. * Function: void LTC_SetCFG(uint8_t CDC,
  498. * uint32_t SetDCC,
  499. * uint32_t ClearDCC)
  500. *
  501. * Overview: Use this function to initialize LTC6803 module
  502. *
  503. * PreCondition: None
  504. *
  505. * Input: Variable: CDC (Mode), set/clear DCC (Balancing Mask)
  506. * Fix: CELL10 = 0 (12-Cell Mode)
  507. * LVLPL = 1 (Level Polling)
  508. * GPIO = 0 (Pull-Down ON)
  509. * WDT = 0 (WDT pin al logic '0')
  510. * MC = 0 (enable interrupts)
  511. * VUV = 0x77 (~2,1V)
  512. * VOV = 0xAA (~3,3V)
  513. *
  514. * Output: None
  515. *
  516. * Side Effects: None
  517. ********************************************************************/
  518. void LTC_SetCFG(uint8_t CDC, uint32_t setDCC, uint32_t clearDCC)
  519. {
  520. static uint32_t gDCC=0; // dauerhafter Kopie von Balance
  521. uint8_t DCC1L, DCC1H, DCC2L, DCC2H; // DCC Mask to CFG
  522. uint8_t LTC_CFG_TxBuffer[16]; // Speicher für Command&PEC Data&PEC
  523. uint32_t DCC=0; // work copy of gDCC
  524. gDCC = gDCC | setDCC; // Backup DCC for SetBalance
  525. gDCC = gDCC & ~clearDCC; // Backup DCC for ClearBalance
  526. DCC = gDCC; // Load new DCC
  527. DCC2L = (unsigned char)(DCC & 0x000000FF);
  528. DCC = DCC>>8;
  529. DCC2H = (unsigned char)(DCC & 0x0000000F);
  530. DCC = DCC>>4;
  531. DCC1L = (unsigned char)(DCC & 0x000000FF);
  532. DCC = DCC>>8;
  533. DCC1H = (unsigned char)(DCC & 0x0000000F);
  534. LTC_CFG_TxBuffer[2] = CDC + LVLPL; // Runmode
  535. LTC_CFG_TxBuffer[3] = DCC1L; // Balancing
  536. LTC_CFG_TxBuffer[4] = DCC1H; // 0xX0 = Zellen maskieren; Balancing = 0x0X
  537. LTC_CFG_TxBuffer[5] = 0x00; // 0xXX Zellen maskieren
  538. LTC_CFG_TxBuffer[6] = 0x77; // 0xXX = Unterspannung
  539. LTC_CFG_TxBuffer[7] = 0xAA; // 0xXX = Oberspannung
  540. LTC_CFG_TxBuffer[8] = LTC_CalcPEC(&LTC_CFG_TxBuffer[2], 6);
  541. LTC_CFG_TxBuffer[9] = CDC + LVLPL; // Runmode
  542. LTC_CFG_TxBuffer[10] = DCC2L; // Balancing
  543. LTC_CFG_TxBuffer[11] = DCC2H; // 0xX0 = Zellen maskieren; Balancing = 0x0X
  544. LTC_CFG_TxBuffer[12] = 0x00; // 0xXX Zellen maskieren
  545. LTC_CFG_TxBuffer[13] = 0x77; // 0xXX = Unterspannung
  546. LTC_CFG_TxBuffer[14] = 0xAA; // 0xXX = Oberspannung
  547. LTC_CFG_TxBuffer[15] = LTC_CalcPEC(&LTC_CFG_TxBuffer[9], 6);
  548. // Send CFG Buffer to LTC
  549. LTC_Read(WRCFG, WRCFG_PEC, 16, &LTC_CFG_TxBuffer[0]);
  550. }
  551. /*********************************************************************
  552. * Function: uint8_t LTC_GetCFG( void )
  553. *
  554. * Overview: Use this function to read back LTC6803 module CFG
  555. * Check PEC
  556. *
  557. * PreCondition: None
  558. *
  559. * Input: Global gCFG
  560. *
  561. * Output: OK = PEC OK, NOK = PEC NOK
  562. *
  563. * Side Effects: None
  564. ********************************************************************/
  565. uint8_t LTC_GetCFG( void )
  566. {
  567. uint8_t PECStatus = LTC_OK;
  568. // Read CFG
  569. LTC_Read(RDCFG, RDCFG_PEC, 16, (unsigned char *)&gCFG.LTC_CFG_RAW[0]);
  570. if( LTC_CalcPEC(&gCFG.LTC_CFG_RAW[2], 6) != gCFG.LTC_CFG_RAW[8])
  571. {
  572. PECStatus = LTC_NOK;
  573. }
  574. else
  575. {
  576. if( LTC_CalcPEC(&gCFG.LTC_CFG_RAW[9], 6) != gCFG.LTC_CFG_RAW[15])
  577. {
  578. PECStatus = LTC_NOK;
  579. }
  580. else
  581. {
  582. gCFG.CDC[1] = gCFG.LTC_CFG_RAW[9] & 0x7;
  583. gCFG.CDC[0] = gCFG.LTC_CFG_RAW[2] & 0x7;
  584. gCFG.CELL10[1] = (gCFG.LTC_CFG_RAW[9] >> 3) & 0x1;
  585. gCFG.CELL10[0] = (gCFG.LTC_CFG_RAW[2] >> 3) & 0x1;
  586. gCFG.LVL_PL[1] = (gCFG.LTC_CFG_RAW[9] >> 4) & 0x1;
  587. gCFG.LVL_PL[0] = (gCFG.LTC_CFG_RAW[2] >> 4) & 0x1;
  588. gCFG.GPIO[1] = (gCFG.LTC_CFG_RAW[9] >> 5) & 0x3;
  589. gCFG.GPIO[0] = (gCFG.LTC_CFG_RAW[2] >> 5) & 0x3;
  590. gCFG.WDT[1] = (gCFG.LTC_CFG_RAW[9] >> 7) & 0x1;
  591. gCFG.WDT[0] = (gCFG.LTC_CFG_RAW[2] >> 7) & 0x1;
  592. gCFG.DCC[1] = gCFG.LTC_CFG_RAW[11] & 0xF;
  593. gCFG.DCC[1] = (gCFG.DCC[1] << 8) + gCFG.LTC_CFG_RAW[10];
  594. gCFG.DCC[0] = gCFG.LTC_CFG_RAW[4] & 0xF;
  595. gCFG.DCC[0] = (gCFG.DCC[0] << 8) + gCFG.LTC_CFG_RAW[3];
  596. gCFG.MC[1] = gCFG.LTC_CFG_RAW[12];
  597. gCFG.MC[1] = (gCFG.MC[1] << 4) + (gCFG.LTC_CFG_RAW[11] >> 4);
  598. gCFG.MC[0] = gCFG.LTC_CFG_RAW[5];
  599. gCFG.MC[0] = (gCFG.MC[0] << 4) + (gCFG.LTC_CFG_RAW[4] >> 4);
  600. gCFG.VUV[1] = gCFG.LTC_CFG_RAW[13] - 31;
  601. gCFG.VUV[1] = gCFG.VUV[1] << 4;
  602. gCFG.VUV[1] = gCFG.VUV[1] + (gCFG.VUV[1] >> 1);
  603. gCFG.VUV[0] = gCFG.LTC_CFG_RAW[6] - 31;
  604. gCFG.VUV[0] = gCFG.VUV[0] << 4;
  605. gCFG.VUV[0] = gCFG.VUV[0] + (gCFG.VUV[0] >> 1);
  606. gCFG.VOV[1] = gCFG.LTC_CFG_RAW[14] - 32;
  607. gCFG.VOV[1] = gCFG.VOV[1] << 4;
  608. gCFG.VOV[1] = gCFG.VOV[1] + (gCFG.VOV[1] >> 1);
  609. gCFG.VOV[0] = gCFG.LTC_CFG_RAW[7] - 32;
  610. gCFG.VOV[0] = gCFG.VOV[0] << 4;
  611. gCFG.VOV[0] = gCFG.VOV[0] + (gCFG.VOV[0] >> 1);
  612. }
  613. }
  614. return PECStatus;
  615. }
  616. /*********************************************************************
  617. * Function: uint8_t LTC_MeasureDiag( uint16_t Status )
  618. *
  619. * Overview: API Funktion
  620. * Use this function to readout Status of LTC6803
  621. *
  622. * PreCondition: None
  623. *
  624. * Input: Global gDRG, Status
  625. * Status = EV__LTC_S_Start, EV__LTC_S_Wait
  626. *
  627. * Output: OK = PEC OK, NOK = PEC NOK
  628. *
  629. * Side Effects: ~17ms stall of LTC
  630. ********************************************************************/
  631. uint8_t LTC_MeasureDiag( uint16_t Status )
  632. {
  633. uint8_t PECStatus = LTC_OK;
  634. if(Status == (unsigned)EV__LTC_S_Start)
  635. {
  636. LTC_StartMeasure(DAGN, DAGN_PEC); // S Start
  637. }
  638. if(Status == (unsigned)EV__LTC_S_Wait)
  639. {
  640. if(PORTC & LTC_ADC_Ready) // ADC not running
  641. {
  642. LATAbits.LATA5 = 1; // CS SPI OFF
  643. // Read Diagnostic Register Group (DRG)
  644. LTC_Read(RDDGNR, RDDGNR_PEC, 8, (uint8_t *)&gDRG.LTC_DRG_RAW[0]);
  645. // Check for Errors
  646. if( LTC_CalcPEC(&gDRG.LTC_DRG_RAW[2], 2) != gDRG.LTC_DRG_RAW[4])
  647. {
  648. PECStatus = LTC_NOK;
  649. }
  650. else
  651. {
  652. if( LTC_CalcPEC(&gDRG.LTC_DRG_RAW[5], 2) != gDRG.LTC_DRG_RAW[7])
  653. {
  654. PECStatus = LTC_NOK;
  655. }
  656. else
  657. {
  658. // Extract Data
  659. // siehe Applications Note LTC 6803-3 Seite 25
  660. gDRG.REF[0] = LTC_Field2IntEven( gDRG.LTC_DRG_RAW[2], gDRG.LTC_DRG_RAW[3] );
  661. gDRG.REF[1] = LTC_Field2IntEven( gDRG.LTC_DRG_RAW[5], gDRG.LTC_DRG_RAW[6] );
  662. gDRG.MUXFAIL[0] = (gDRG.LTC_DRG_RAW[3] >> 5) & 0x1;
  663. gDRG.MUXFAIL[1] = (gDRG.LTC_DRG_RAW[6] >> 5) & 0x1;
  664. gDRG.REV[0] = gDRG.LTC_DRG_RAW[3] >> 6;
  665. gDRG.REV[1] = gDRG.LTC_DRG_RAW[6] >> 6;
  666. }
  667. }
  668. }
  669. }
  670. return PECStatus;
  671. }
  672. /*********************************************************************
  673. * Function: uint8_t LTC_MeasureVoltage( uint16_t Status );
  674. *
  675. * Overview: Use this function to start measuring cell voltage
  676. * with LTC6803 module
  677. *
  678. * PreCondition: None
  679. *
  680. * Input: Global gCVAD, Status = EV__LTC_V_Start / EV__LTC_V_Wait
  681. * *
  682. * Output: OK = PEC OK, NOK = PEC NOK
  683. *
  684. * Side Effects: ~13ms stall
  685. // ********************************************************************/
  686. uint8_t LTC_MeasureVoltage( uint8_t CMD, uint8_t CMD_PEC, uint16_t Status )
  687. {
  688. int8_t i, j; // Laufindex
  689. uint8_t PECStatus = LTC_OK;
  690. if(Status == (unsigned)EV__LTC_V_Start)
  691. {
  692. LTC_SetCFG(CDC_1, 0x00, 0x00FFFFFF); // Set Balancing Off
  693. LTC_StartMeasure( CMD, CMD_PEC); // Start Voltage Measure
  694. }
  695. if(Status == (unsigned)EV__LTC_V_Wait)
  696. {
  697. if(PORTC & LTC_ADC_Ready) // ADC not running
  698. {
  699. LATAbits.LATA5 = 1; // CS SPI OFF
  700. LTC_SetCFG(CDC_1, CAN_BAL, ~CAN_BAL); // Set Balancing Outs
  701. // Read all cell voltage
  702. LTC_Read(RDCV, RDCV_PEC, 40, (unsigned char *)&gCVAD.LTC_CVAD_RAW[0]);
  703. if( LTC_CalcPEC(&gCVAD.LTC_CVAD_RAW[2], 18) != gCVAD.LTC_CVAD_RAW[20])
  704. {
  705. PECStatus = LTC_NOK;
  706. }
  707. else
  708. {
  709. if( LTC_CalcPEC(&gCVAD.LTC_CVAD_RAW[21], 18) != gCVAD.LTC_CVAD_RAW[39])
  710. {
  711. PECStatus = LTC_NOK;
  712. }
  713. else
  714. {
  715. //reassemble Data and calc Voltage
  716. for(i=0; i<24 ; i=i+2) // Loop über alle Zellen
  717. {
  718. j = i + (i>>1); // Index j = 1.5 x i
  719. if(i>11) j++; // jump PEC_L
  720. // siehe Applications Note LTC 6803-3 Seite 24
  721. gCVAD.CVAD[i] = LTC_Field2IntEven( gCVAD.LTC_CVAD_RAW[j+2], gCVAD.LTC_CVAD_RAW[j+3]);
  722. gCVAD.CVAD[i+1] = LTC_Field2IntOdd( gCVAD.LTC_CVAD_RAW[j+3], gCVAD.LTC_CVAD_RAW[j+4]);
  723. }
  724. }
  725. }
  726. }
  727. }
  728. return PECStatus;
  729. }
  730. /*********************************************************************
  731. * Function: uint8_t LTC_runMeasureTemperature( uint8_t CMD,
  732. * uint8_t CMD_PEC,
  733. * uint16_t Status );
  734. *
  735. * Overview: Use this function to start measuring Temperature
  736. * with LTC6803 module
  737. *
  738. * PreCondition: None
  739. *
  740. * Input: CMD & CMD_PEC, Global gTMP, Status
  741. * Status = EV__LTC_T_Start, EV__LTC_T_Wait
  742. * CMD = STTMPAD_ALL, STTMPAD_ST1, STTMPAD_ST
  743. *
  744. * Output: OK = PEC OK, NOK = PEC NOK
  745. *
  746. * Side Effects: ~4ms stall of LTC
  747. ********************************************************************/
  748. uint8_t LTC_MeasureTemperature( uint8_t CMD, uint8_t CMD_PEC, uint16_t Status )
  749. {
  750. int8_t i, j; // Laufindex
  751. int16_t iBufTMP; // Zwischenspeicher
  752. uint8_t Cycle = 0; // Temperature MUX Count
  753. uint8_t RCT_Cycle = 0; // new runindex for MUX2
  754. uint8_t PECStatus = LTC_OK;
  755. // Start Cell Temperature ADC Conversions - poll status
  756. if(Status == (unsigned)EV__LTC_T_Start)
  757. {
  758. LTC_StartMeasure(CMD, CMD_PEC);
  759. }
  760. if(Status == (unsigned)EV__LTC_T_Wait)
  761. {
  762. if(PORTC & LTC_ADC_Ready) // ADC not running
  763. {
  764. LATAbits.LATA5 = 1; // CS SPI OFF
  765. // Read all cell temperature
  766. LTC_Read(RDTMP, RDTMP_PEC, 14, (unsigned char *)&gTMP.LTC_TMP_RAW[0]);
  767. // Check for Errors
  768. if( LTC_CalcPEC(&gTMP.LTC_TMP_RAW[2], 5) != gTMP.LTC_TMP_RAW[7])
  769. {
  770. PECStatus = LTC_NOK;
  771. }
  772. else
  773. {
  774. if( LTC_CalcPEC(&gTMP.LTC_TMP_RAW[8], 5) != gTMP.LTC_TMP_RAW[13])
  775. {
  776. PECStatus = LTC_NOK;
  777. }
  778. else
  779. {
  780. // Extract Data
  781. j=2; // Index in RAW
  782. Cycle = LATC & 0x07; // Extract MUX
  783. Cycle--;
  784. RCT_Cycle = 5 - Cycle; // set new Cycle
  785. for(i=0; i<24; i=i+12) // Loop over LTC Modules*2*TMP
  786. {
  787. // siehe Applications Note LTC 6803-3 Seite 25
  788. iBufTMP = LTC_Field2IntEven( gTMP.LTC_TMP_RAW[j], gTMP.LTC_TMP_RAW[j+1] );
  789. gTMP.ETMP[2*Cycle+i] = LTC_CONV_UMESS_2_TEMP(iBufTMP);
  790. j++;
  791. iBufTMP = LTC_Field2IntOdd( gTMP.LTC_TMP_RAW[j], gTMP.LTC_TMP_RAW[j+1] );
  792. gTMP.ETMP[2*RCT_Cycle+i+1] = LTC_CONV_UMESS_2_TEMP(iBufTMP);
  793. j = j + 2;
  794. iBufTMP = LTC_Field2IntEven( gTMP.LTC_TMP_RAW[j], gTMP.LTC_TMP_RAW[j+1] );
  795. gTMP.ITMP[i/12] = (iBufTMP >> 3) - 273;
  796. j = j + 3;
  797. }
  798. gTMP.THSD[0] = (gTMP.LTC_TMP_RAW[6] >> 4) & 0x1;
  799. gTMP.THSD[1] = (gTMP.LTC_TMP_RAW[12] >> 4) & 0x1;
  800. }
  801. }
  802. }
  803. }
  804. return PECStatus;
  805. }
  806. /*********************************************************************
  807. * Function: uint8_t LTC_CalcPEC(uint8_t *Array, uint8_t SizeOf)
  808. *
  809. * Overview: Use this function to calculate CRC Checksum (PEC)
  810. * for LTC6803 module
  811. *
  812. * PreCondition: None
  813. *
  814. * Input: *Array, SizeOf - Number of Elements
  815. *
  816. * Output: PEC
  817. *
  818. * Side Effects: None
  819. **********************************************************************/
  820. uint8_t LTC_CalcPEC(uint8_t *Array, uint8_t Size_Of)
  821. {
  822. uint8_t i; // Laufindex
  823. int8_t k; // Laufindex
  824. uint8_t PEC = 0x41; // PEC Startwert
  825. uint8_t DIN = 0; // Input Buffer
  826. uint8_t IN0 = 0; // Zwischenspeicher
  827. uint8_t IN1 = 0; // Zwischenspeicher
  828. uint8_t IN2 = 0; // Zwischenspeicher
  829. for(i=0;i<Size_Of;i++) // Loop über alle Elemente
  830. {
  831. for(k=0;k<8;k++) // Loop über alle Bits
  832. {
  833. DIN = Array[i] & (0x0080 >> k); // Berechnung nach Datenblatt
  834. DIN = (DIN >> (7 - k));
  835. IN0 = DIN ^ ((PEC & 0x0080) >> 7);
  836. IN1 = (PEC & 0x0001) ^ IN0;
  837. IN2 = ((PEC & 0x0002) >> 1) ^ IN0;
  838. PEC = (PEC << 1);
  839. PEC = (PEC & 0x00F8) | ((IN2 << 2) |(IN1 << 1) | IN0);
  840. }
  841. }
  842. return PEC;
  843. }
  844. /*********************************************************************
  845. * Function: void InitSPI( void )
  846. *
  847. * Overview: Use this function to config SPI for LTC6803 module
  848. *
  849. * PreCondition: None
  850. *
  851. * Input: None
  852. *
  853. * Output: None
  854. *
  855. * Side Effects: None
  856. **********************************************************************/
  857. void InitSPI( void )
  858. {
  859. // RC3 is connected to SCK: Serial clock input
  860. TRISCbits.TRISC3 = 0;
  861. // RC5 is connected to SI: Serial data I/O (MCP23017), Serial data input (MCP23S17)
  862. TRISCbits.TRISC5 = 0;
  863. // SSPxCON1: MSSPx CONTROL REGISTER 1 (I2C? MODE)
  864. // SSPEN=1, 1 = Enables the serial port and configures the SDAx and SCLx pins as the serial port pins
  865. // SSPM<3:0>=0010, 0010 = SPI Master mode, clock = FOSC/64
  866. // CKP=1, 1 = Idle state for clock is a high level
  867. SSPCON1 = 0x32;//SSP1CON1 = 0x32; // 00100010
  868. // CKE: SPI Clock Select bit
  869. // 1 = Transmit occurs on transition from active to Idle clock state
  870. // 0 = Transmit occurs on transition from Idle to active clock state
  871. SSPSTATbits.CKE = 0;//SSP1STATbits.CKE = 0;
  872. // SSP1IF: MSSP1 Interrupt Flag bit
  873. //1 = The transmission/reception is complete (must be cleared in software)
  874. //0 = Waiting to transmit/receive
  875. PIR1bits.SSPIF = 0;
  876. }
  877. /*********************************************************************
  878. * Function: int16_t LTC_Field2IntEven( uint8_t ucByteLow,
  879. * uint8_t ucByteHigh)
  880. *
  881. * Overview: Use this function to extract an int Variable
  882. * out of LTC-Bitfield at known even Address and calculate
  883. * Voltage
  884. *
  885. * PreCondition: None
  886. *
  887. * Input: 2 Byte out of LTC_Bitfield
  888. *
  889. * Output: Extracted Integer representing Voltage (mV)
  890. *
  891. * Side Effects: None
  892. **********************************************************************/
  893. int16_t LTC_Field2IntEven( uint8_t ucByteLow, uint8_t ucByteHigh)
  894. {
  895. int16_t iBuffer = 0;
  896. iBuffer = ucByteHigh & 0xF; // H Nibble isolieren
  897. iBuffer = (iBuffer << 8) + ucByteLow; // H Nibble in Position + M + L
  898. iBuffer = iBuffer - 512; // Offset 512 Korrektur
  899. if(iBuffer>=0)
  900. iBuffer = iBuffer + (iBuffer >> 1); // ADCinc x 1,5 = X mV
  901. else
  902. iBuffer = iBuffer + ((iBuffer >> 1) + 0x8000); // ADCinc x 1,5 = X mV (bei negativen Zahlen)
  903. return iBuffer;
  904. }
  905. /*********************************************************************
  906. * Function: int16_t LTC_Field2IntOdd( uint8_t ucByteLow,
  907. * uint8_t ucByteHigh)
  908. *
  909. * Overview: Use this function to extract an int Variable
  910. * out of LTC-Bitfield at known odd Address and calculate
  911. * Voltage
  912. *
  913. * PreCondition: None
  914. *
  915. * Input: 2 Byte out of LTC_Bitfield
  916. *
  917. * Output: Extracted Integer representing Voltage (mV)
  918. *
  919. * Side Effects: None
  920. **********************************************************************/
  921. int16_t LTC_Field2IntOdd( uint8_t ucByteLow, uint8_t ucByteHigh)
  922. {
  923. int16_t iBuffer = 0;
  924. iBuffer = ucByteHigh; // H und M Nibble isolieren
  925. iBuffer = (iBuffer << 4) + (ucByteLow >> 4); // H und M Nibble in Position + L Nibble
  926. iBuffer = iBuffer - 512; // Offset 512 Korrektur
  927. if(iBuffer>=0)
  928. iBuffer = iBuffer + (iBuffer >> 1); // ADCinc x 1,5 = X mV
  929. else
  930. iBuffer = iBuffer + ((iBuffer >> 1) + 0x8000); // ADCinc x 1,5 = X mV (bei negativen Zahlen)
  931. return iBuffer;
  932. }
  933. /*********************************************************************
  934. * Function: void LTC_StartMeasure(uint8_t COMAND, uint8_t COMAND_PEC);
  935. *
  936. * Overview: Use this function sends Command Sequence for Measurment
  937. *
  938. * PreCondition: None
  939. *
  940. * Input: Command Byte & Command PEC
  941. *
  942. * Output: none
  943. *
  944. * Side Effects: uses SPI
  945. **********************************************************************/
  946. void LTC_StartMeasure(uint8_t COMAND, uint8_t COMAND_PEC)
  947. {
  948. LATAbits.LATA5 = 0; // CS SPI ON
  949. SSPBUF=COMAND; // Send Command Byte
  950. while(!PIR1bits.SSPIF); // Warten bis die Daten gesendet wurden
  951. PIR1bits.SSPIF = 0; // clear SSPIF Bit
  952. SSPBUF=COMAND_PEC; // PEC Byte
  953. while(!PIR1bits.SSPIF); // Warten bis die Daten gesendet wurden
  954. PIR1bits.SSPIF = 0; // clear SSPIF Bit
  955. }
  956. /*********************************************************************
  957. * Function: void LTC_Read( uint8_t CMD,
  958. * uint8_t CMD_PEC,
  959. * uint8_t Length,
  960. * uint8_t *ptr),
  961. *
  962. * Overview: Use this function read Data from LTC
  963. *
  964. * PreCondition: None
  965. *
  966. * Input: Command Byte & Command PEC & Data Length & Pointer 2 Start Buffer
  967. *
  968. * Output: none
  969. *
  970. * Side Effects: uses SPI
  971. **********************************************************************/
  972. void LTC_Read(uint8_t CMD, uint8_t CMD_PEC, uint8_t Length, uint8_t *ptr)
  973. {
  974. uint8_t i; // Laufindex
  975. *ptr = CMD; // Load Command to Buffer
  976. *(ptr+1) = CMD_PEC; // Load Command PEC to Buffer
  977. LATAbits.LATA5 = 0; // CS SPI ON
  978. for(i=0;i<Length; i++)
  979. {
  980. SSPBUF = *(ptr+i); // Send Byte
  981. while(!PIR1bits.SSPIF); // wait until Send complete
  982. PIR1bits.SSPIF = 0; // clear SSPIF Bit
  983. *(ptr+i) = SSPBUF; // store Data to Buffer
  984. }
  985. LATAbits.LATA5 = 1; // CS SPI OFF
  986. }
  987. /*********************************************************************
  988. * Function: void InitTimer( void );
  989. *
  990. * Overview: Use this function to init Timer 1 for 20ms TimeSlot
  991. *
  992. * PreCondition: None
  993. *
  994. * Input: -
  995. *
  996. * Output: -
  997. *
  998. * Side Effects: run Timer 1
  999. **********************************************************************/
  1000. void InitTimer(void)
  1001. {
  1002. T1CONbits.T1CKPS0 = 1; // Timer 1 prescalar = 0b00
  1003. T1CONbits.T1CKPS1 = 1; // = (Fosc/4) / 8 = 2MHz
  1004. IPR1bits.TMR1IP = 0; // 1 = make this a low priority interrupt
  1005. PIE1bits.TMR1IE = 1; // enable Timer interrupt
  1006. PIR1bits.TMR1IF = 0; // clear any pending events
  1007. T1CONbits.RD16 = 1; // 16 Bit read-write mode
  1008. T1CONbits.TMR1ON = 1; // Timer A run
  1009. }
  1010. /*********************************************************************
  1011. * Function: void Set_LTC_TimeOut( void )
  1012. *
  1013. * Overview: Use this function to set LTC_TimeOut Flag
  1014. *
  1015. * PreCondition: None
  1016. *
  1017. * Input: -
  1018. *
  1019. * Output: -
  1020. *
  1021. * Side Effects: change LTC_TimeOut
  1022. **********************************************************************/
  1023. void Set_LTC_TimeOut( void )
  1024. {
  1025. gLTC_TimeOut |= LTC_TimeOut;
  1026. }
  1027. int16_t ADC_supply_voltage( void )
  1028. {
  1029. int16_t analog_reading = 0;
  1030. ADCON0bits.CHS = 0; // Set adc channel to read
  1031. ADCON0bits.GO = 1; //Start A/D Conversion
  1032. while(ADCON0bits.GO == 1)
  1033. {
  1034. //Loop here until A/D conversion completes
  1035. };
  1036. analog_reading= ( (((uint16_t)ADRESH << 8)+ADRESL)); // readout ADC
  1037. return analog_reading;
  1038. }