1 ###############################################################################
\r
3 # IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 #
\r
4 # Copyright 1996-2007 IAR Systems. All rights reserved. #
\r
6 # Source file = C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c #
\r
7 # Command line = C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c #
\r
8 # --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #
\r
9 # \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #
\r
10 # g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #
\r
11 # st\ --initializers_in_flash -z2 --no_cse --no_inline #
\r
12 # --no_code_motion --no_cross_call --no_clustering #
\r
13 # --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e #
\r
14 # --require_prototypes -I "C:\Program Files\IAR #
\r
15 # Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program #
\r
16 # Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" #
\r
17 # --eeprom_size 512 #
\r
18 # List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\NIMHcharg #
\r
20 # Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\NIMHcharge #
\r
24 ###############################################################################
\r
26 C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c
\r
27 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
28 2 /*! \file *********************************************************************
\r
31 5 * Charge state function for NiMH batteries
\r
33 7 * Contains the charge state function, in which the NiMH charging
\r
34 8 * algorithm is, plus the associated functions.
\r
36 10 * \par Application note:
\r
37 11 * AVR463: Charging NiMH Batteries with BC100 \n
\r
39 13 * \par Documentation
\r
40 14 * For comprehensive code documentation, supported compilers, compiler
\r
41 15 * settings and supported devices see readme.html
\r
44 18 * Atmel Corporation: http://www.atmel.com \n
\r
45 19 * Support email: avr@atmel.com
\r
49 23 * $Revision: 2255 $
\r
51 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $
\r
52 26 * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n
\r
53 27 ******************************************************************************/
\r
55 29 #include <ioavr.h>
\r
57 31 #include "enums.h"
\r
58 32 #include "structs.h"
\r
60 34 #include "battery.h"
\r
61 35 #include "charge.h"
\r
62 36 #include "chargefunc.h"
\r
63 37 #include "main.h"
\r
64 38 #include "menu.h"
\r
65 39 #include "NIMHspecs.h"
\r
67 41 #include "time.h"
\r
70 44 #error NIMH not defined in main.h!
\r
74 48 //******************************************************************************
\r
76 50 //******************************************************************************
\r
77 51 /*! \brief Controls the charging.
\r
79 53 * This function contains the charging algorithm itself, divided into stages.\n
\r
80 54 * For each stage the PWM may be started/stopped, and the timer,
\r
81 55 * halt-requirements and charge parameters may be set.\n
\r
82 56 * The charging functions return whatever state is next, and as long as no
\r
83 57 * errors occur this is the next charging stage.
\r
85 59 * \note If more stages are needed simply define more states in menu.h, include
\r
86 60 * them in \ref menu_state[] in menu.c, then add the cases to this function.
\r
88 62 * \note This algorithm is for NiMH batteries.
\r
91 \ In segment CODE, align 2, keep-with-next
\r
92 64 unsigned char Charge(unsigned char inp)
\r
95 \ 00000000 .... RCALL ?PROLOGUE2_L09
\r
96 \ 00000002 2F90 MOV R25, R16
\r
97 66 unsigned char NextState;
\r
99 68 switch (CurrentState) {
\r
100 \ 00000004 9100.... LDS R16, CurrentState
\r
101 \ 00000008 510E SUBI R16, 30
\r
102 \ 0000000A F049 BREQ ??Charge_0
\r
103 \ 0000000C 5104 SUBI R16, 20
\r
104 \ 0000000E F1D1 BREQ ??Charge_1
\r
105 \ 00000010 500A SUBI R16, 10
\r
106 \ 00000012 F409 BRNE $+2+2
\r
107 \ 00000014 C06E RJMP ??Charge_2
\r
108 \ 00000016 500A SUBI R16, 10
\r
109 \ 00000018 F409 BRNE $+2+2
\r
110 \ 0000001A C085 RJMP ??Charge_3
\r
111 \ 0000001C C09F RJMP ??Charge_4
\r
112 69 // First stage is a prequalification. Attempt to charge battery to 1 V,
\r
113 70 // using a 0.1 C current, within 2 minutes.
\r
114 71 // If this fails, the battery is likely damaged.
\r
115 72 // If it succeeds, start a fast charge.
\r
116 73 case ST_PREQUAL:
\r
118 75 // Set up charge current and next state.
\r
119 76 ChargeParameters.Current = BattData.Capacity / 10;
\r
121 \ 0000001E .... LDI R30, LOW(BattData)
\r
122 \ 00000020 .... LDI R31, (BattData) >> 8
\r
123 \ 00000022 8104 LDD R16, Z+4
\r
124 \ 00000024 8115 LDD R17, Z+5
\r
125 \ 00000026 E04A LDI R20, 10
\r
126 \ 00000028 E050 LDI R21, 0
\r
127 \ 0000002A .... RCALL ?US_DIVMOD_L02
\r
128 \ 0000002C .... LDI R30, LOW(ChargeParameters)
\r
129 \ 0000002E .... LDI R31, (ChargeParameters) >> 8
\r
130 \ 00000030 8302 STD Z+2, R16
\r
131 \ 00000032 8313 STD Z+3, R17
\r
132 77 ChargeParameters.NextState = ST_FASTCHARGE;
\r
133 \ 00000034 E302 LDI R16, 50
\r
134 \ 00000036 9300.... STS (ChargeParameters + 4), R16
\r
136 79 // Halt charge on voltage limit or timeout.
\r
137 80 // Timeout means battery exhaustion.
\r
138 81 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |
\r
139 82 HALT_FLAG_EXHAUSTION);
\r
140 \ 0000003A E302 LDI R16, 50
\r
141 \ 0000003C 9300.... STS HaltParameters, R16
\r
143 84 // Set up voltage limit and temperature limits.
\r
144 85 HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;
\r
145 \ 00000040 EB08 LDI R16, 184
\r
146 \ 00000042 E01B LDI R17, 11
\r
147 \ 00000044 .... LDI R30, LOW(HaltParameters)
\r
148 \ 00000046 .... LDI R31, (HaltParameters) >> 8
\r
149 \ 00000048 8303 STD Z+3, R16
\r
150 \ 0000004A 8314 STD Z+4, R17
\r
151 86 HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;
\r
152 \ 0000004C E005 LDI R16, 5
\r
153 \ 0000004E E010 LDI R17, 0
\r
154 \ 00000050 .... LDI R30, LOW(HaltParameters)
\r
155 \ 00000052 .... LDI R31, (HaltParameters) >> 8
\r
156 \ 00000054 8701 STD Z+9, R16
\r
157 \ 00000056 8712 STD Z+10, R17
\r
158 87 HaltParameters.TemperatureMax = 35;
\r
159 \ 00000058 E203 LDI R16, 35
\r
160 \ 0000005A E010 LDI R17, 0
\r
161 \ 0000005C .... LDI R30, LOW(HaltParameters)
\r
162 \ 0000005E .... LDI R31, (HaltParameters) >> 8
\r
163 \ 00000060 8307 STD Z+7, R16
\r
164 \ 00000062 8710 STD Z+8, R17
\r
166 89 // Reset temperature measurement for HaltNow().
\r
167 90 HaltParameters.LastNTC = 0;
\r
168 \ 00000064 E000 LDI R16, 0
\r
169 \ 00000066 E010 LDI R17, 0
\r
170 \ 00000068 .... LDI R30, LOW(HaltParameters)
\r
171 \ 0000006A .... LDI R31, (HaltParameters) >> 8
\r
172 \ 0000006C 8707 STD Z+15, R16
\r
173 \ 0000006E 8B10 STD Z+16, R17
\r
175 92 // Start PWM and charge timer before calling the charge function.
\r
177 \ 00000070 .... RCALL PWM_Start
\r
178 94 Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);
\r
179 \ 00000072 E040 LDI R20, 0
\r
180 \ 00000074 E010 LDI R17, 0
\r
181 \ 00000076 E022 LDI R18, 2
\r
182 \ 00000078 E030 LDI R19, 0
\r
183 \ 0000007A E001 LDI R16, 1
\r
184 \ 0000007C .... RCALL Time_Set
\r
186 96 // Call charge function, get next state.
\r
187 97 NextState = ConstantCurrent();
\r
188 \ 0000007E .... RCALL ConstantCurrent
\r
189 \ 00000080 2F80 MOV R24, R16
\r
190 \ 00000082 C06D RJMP ??Charge_5
\r
194 101 // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,
\r
195 102 // until either rate of temperature increase or voltage reaches limit, or
\r
196 103 // the voltage drops sufficiently.
\r
197 104 // Timeout doesn't mean battery exhaustion now.
\r
198 105 case ST_FASTCHARGE:
\r
200 107 // Set up charge current and next state.
\r
201 108 ChargeParameters.Current = BattData.Capacity;
\r
203 \ 00000084 .... LDI R30, LOW(BattData)
\r
204 \ 00000086 .... LDI R31, (BattData) >> 8
\r
205 \ 00000088 8104 LDD R16, Z+4
\r
206 \ 0000008A 8115 LDD R17, Z+5
\r
207 \ 0000008C .... LDI R30, LOW(ChargeParameters)
\r
208 \ 0000008E .... LDI R31, (ChargeParameters) >> 8
\r
209 \ 00000090 8302 STD Z+2, R16
\r
210 \ 00000092 8313 STD Z+3, R17
\r
211 109 ChargeParameters.NextState = ST_LOWRATECHARGE;
\r
212 \ 00000094 E30C LDI R16, 60
\r
213 \ 00000096 9300.... STS (ChargeParameters + 4), R16
\r
215 111 // Halt charge on voltage limit, timeout, voltage drop or rate of
\r
216 112 // temperature increase.
\r
217 113 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |
\r
218 114 HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);
\r
219 \ 0000009A E10B LDI R16, 27
\r
220 \ 0000009C 9300.... STS HaltParameters, R16
\r
222 116 // Set up limits for voltage, voltage drop, temperature and rate of
\r
223 117 // temperature increase (1 degree C per minute).
\r
224 118 HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;
\r
225 \ 000000A0 EC00 LDI R16, 192
\r
226 \ 000000A2 E112 LDI R17, 18
\r
227 \ 000000A4 .... LDI R30, LOW(HaltParameters)
\r
228 \ 000000A6 .... LDI R31, (HaltParameters) >> 8
\r
229 \ 000000A8 8303 STD Z+3, R16
\r
230 \ 000000AA 8314 STD Z+4, R17
\r
231 119 HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;
\r
232 \ 000000AC E20D LDI R16, 45
\r
233 \ 000000AE E010 LDI R17, 0
\r
234 \ 000000B0 .... LDI R30, LOW(HaltParameters)
\r
235 \ 000000B2 .... LDI R31, (HaltParameters) >> 8
\r
236 \ 000000B4 8301 STD Z+1, R16
\r
237 \ 000000B6 8312 STD Z+2, R17
\r
238 120 HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;
\r
239 \ 000000B8 E302 LDI R16, 50
\r
240 \ 000000BA E010 LDI R17, 0
\r
241 \ 000000BC .... LDI R30, LOW(HaltParameters)
\r
242 \ 000000BE .... LDI R31, (HaltParameters) >> 8
\r
243 \ 000000C0 8307 STD Z+7, R16
\r
244 \ 000000C2 8710 STD Z+8, R17
\r
245 121 HaltParameters.TemperatureRise = 1;
\r
246 \ 000000C4 E001 LDI R16, 1
\r
247 \ 000000C6 E010 LDI R17, 0
\r
248 \ 000000C8 .... LDI R30, LOW(HaltParameters)
\r
249 \ 000000CA .... LDI R31, (HaltParameters) >> 8
\r
250 \ 000000CC 8703 STD Z+11, R16
\r
251 \ 000000CE 8714 STD Z+12, R17
\r
253 123 // Reset maximum voltage measurement for HaltNow().
\r
254 124 HaltParameters.VBATMax = 0;
\r
255 \ 000000D0 E000 LDI R16, 0
\r
256 \ 000000D2 E010 LDI R17, 0
\r
257 \ 000000D4 .... LDI R30, LOW(HaltParameters)
\r
258 \ 000000D6 .... LDI R31, (HaltParameters) >> 8
\r
259 \ 000000D8 8705 STD Z+13, R16
\r
260 \ 000000DA 8716 STD Z+14, R17
\r
262 126 // Start timer, PWM should still be running.
\r
263 127 Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);
\r
264 \ 000000DC E040 LDI R20, 0
\r
265 \ 000000DE E010 LDI R17, 0
\r
266 \ 000000E0 .... LDI R30, LOW(BattData)
\r
267 \ 000000E2 .... LDI R31, (BattData) >> 8
\r
268 \ 000000E4 8520 LDD R18, Z+8
\r
269 \ 000000E6 8531 LDD R19, Z+9
\r
270 \ 000000E8 E001 LDI R16, 1
\r
271 \ 000000EA .... RCALL Time_Set
\r
273 129 // Call charge function, get next state.
\r
274 130 NextState = ConstantCurrent();
\r
275 \ 000000EC .... RCALL ConstantCurrent
\r
276 \ 000000EE 2F80 MOV R24, R16
\r
277 \ 000000F0 C036 RJMP ??Charge_5
\r
281 134 // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,
\r
282 135 // until either rate of temperature increase or voltage reaches limit.
\r
283 136 case ST_LOWRATECHARGE:
\r
285 138 // Set up charge current and next state.
\r
286 139 ChargeParameters.Current = BattData.Capacity / 10;
\r
288 \ 000000F2 .... LDI R30, LOW(BattData)
\r
289 \ 000000F4 .... LDI R31, (BattData) >> 8
\r
290 \ 000000F6 8104 LDD R16, Z+4
\r
291 \ 000000F8 8115 LDD R17, Z+5
\r
292 \ 000000FA E04A LDI R20, 10
\r
293 \ 000000FC E050 LDI R21, 0
\r
294 \ 000000FE .... RCALL ?US_DIVMOD_L02
\r
295 \ 00000100 .... LDI R30, LOW(ChargeParameters)
\r
296 \ 00000102 .... LDI R31, (ChargeParameters) >> 8
\r
297 \ 00000104 8302 STD Z+2, R16
\r
298 \ 00000106 8313 STD Z+3, R17
\r
299 140 ChargeParameters.NextState = ST_ENDCHARGE;
\r
300 \ 00000108 E406 LDI R16, 70
\r
301 \ 0000010A 9300.... STS (ChargeParameters + 4), R16
\r
303 142 // Halt charge on voltage limit, timeout or temperature rise.
\r
304 143 // Use the same requirements as during the last stage (ST_FASTCHARGE).
\r
305 144 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |
\r
306 145 HALT_TEMPERATURE_RISE);
\r
307 \ 0000010E E10A LDI R16, 26
\r
308 \ 00000110 9300.... STS HaltParameters, R16
\r
310 147 // Start timer, 30 minutes.
\r
311 148 Time_Set(TIMER_CHG, 30, 0, 0);
\r
312 \ 00000114 E040 LDI R20, 0
\r
313 \ 00000116 E010 LDI R17, 0
\r
314 \ 00000118 E12E LDI R18, 30
\r
315 \ 0000011A E030 LDI R19, 0
\r
316 \ 0000011C E001 LDI R16, 1
\r
317 \ 0000011E .... RCALL Time_Set
\r
319 150 // Call charge function, get next state.
\r
320 151 NextState = ConstantCurrent();
\r
321 \ 00000120 .... RCALL ConstantCurrent
\r
322 \ 00000122 2F80 MOV R24, R16
\r
323 \ 00000124 C01C RJMP ??Charge_5
\r
327 155 // Charging is done!
\r
328 156 case ST_ENDCHARGE:
\r
330 158 // Stop the PWM output and flag battery as charged.
\r
333 \ 00000126 .... RCALL PWM_Stop
\r
334 160 BattData.Charged = TRUE;
\r
335 \ 00000128 .... LDI R30, LOW(BattData)
\r
336 \ 0000012A .... LDI R31, (BattData) >> 8
\r
337 \ 0000012C 8100 LD R16, Z
\r
338 \ 0000012E 6002 ORI R16, 0x02
\r
339 \ 00000130 8300 ST Z, R16
\r
341 162 // If the other battery is enabled go to ST_BATCON, otherwise
\r
342 163 // go to ST_SLEEP.
\r
343 164 if (BattControl[(BattActive+1)%2].Enabled) {
\r
344 \ 00000132 9100.... LDS R16, BattActive
\r
345 \ 00000136 E010 LDI R17, 0
\r
346 \ 00000138 5F0F SUBI R16, 255
\r
347 \ 0000013A 4F1F SBCI R17, 255
\r
348 \ 0000013C E042 LDI R20, 2
\r
349 \ 0000013E E050 LDI R21, 0
\r
350 \ 00000140 .... RCALL ?SS_DIVMOD_L02
\r
351 \ 00000142 .... LDI R18, LOW(BattControl)
\r
352 \ 00000144 .... LDI R19, (BattControl) >> 8
\r
353 \ 00000146 0F24 ADD R18, R20
\r
354 \ 00000148 1F35 ADC R19, R21
\r
355 \ 0000014A 01A9 MOVW R21:R20, R19:R18
\r
356 \ 0000014C .... RCALL __eeget8_16
\r
357 \ 0000014E 7001 ANDI R16, 0x01
\r
358 \ 00000150 2300 TST R16
\r
359 \ 00000152 F011 BREQ ??Charge_6
\r
360 165 NextState = ST_BATCON;
\r
361 \ 00000154 E184 LDI R24, 20
\r
362 \ 00000156 C003 RJMP ??Charge_5
\r
364 167 NextState = ST_SLEEP;
\r
366 \ 00000158 E288 LDI R24, 40
\r
367 \ 0000015A C001 RJMP ??Charge_5
\r
372 172 default: // Shouldn't end up here. Reinitialize for safety.
\r
373 173 NextState = ST_INIT;
\r
375 \ 0000015C E08A LDI R24, 10
\r
379 177 // Return the next state to main().
\r
380 178 return(NextState);
\r
382 \ 0000015E 2F08 MOV R16, R24
\r
383 \ 00000160 E0E2 LDI R30, 2
\r
384 \ 00000162 .... RJMP ?EPILOGUE_B2_L09
\r
387 Maximum stack usage in bytes:
\r
389 Function CSTACK RSTACK
\r
390 -------- ------ ------
\r
394 -> ConstantCurrent 2 2
\r
396 -> ConstantCurrent 2 2
\r
398 -> ConstantCurrent 2 2
\r
402 Segment part sizes:
\r
404 Function/Label Bytes
\r
405 -------------- -----
\r
409 356 bytes in segment CODE
\r
411 356 bytes of CODE memory
\r