1 ###############################################################################
\r
3 # IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 #
\r
4 # Copyright 1996-2007 IAR Systems. All rights reserved. #
\r
6 # Source file = C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c #
\r
7 # Command line = C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c #
\r
8 # --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #
\r
9 # 0\IAR\Release\Obj\ -D NDEBUG -lCN #
\r
10 # C:\home\kevin\pub\src\bc100\IAR\Release\List\ #
\r
11 # -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #
\r
12 # t\ --initializers_in_flash -s9 --no_cross_call #
\r
13 # --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I #
\r
14 # "C:\Program Files\IAR Systems\Embedded #
\r
15 # Workbench 4.0\avr\INC\" -I "C:\Program #
\r
16 # Files\IAR Systems\Embedded Workbench #
\r
17 # 4.0\avr\INC\CLIB\" --eeprom_size 512 #
\r
18 # --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, #
\r
19 # 34-35,38-39,42-43,46,50,52-54,56-59,61-62, #
\r
20 # 64-65,68-80,83-84,87-91,94-95,98-100,103-110, #
\r
22 # Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, #
\r
23 # 38-39,42-43,46,50,52-54,56-59,61-62,64-65, #
\r
24 # 68-80,83-84,87-91,94-95,98-100,103-110,112-126 #
\r
25 # Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, #
\r
26 # 42,46,50,52-54,56-59,61-62,64,68-69,71-80, #
\r
27 # 83-84,87-89,91,94-95,98,100,104-105,108-109, #
\r
29 # Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, #
\r
31 # List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\NI #
\r
33 # Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIM #
\r
37 ###############################################################################
\r
39 C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c
\r
40 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
41 2 /*! \file *********************************************************************
\r
44 5 * Charge state function for NiMH batteries
\r
46 7 * Contains the charge state function, in which the NiMH charging
\r
47 8 * algorithm is, plus the associated functions.
\r
49 10 * \par Application note:
\r
50 11 * AVR463: Charging NiMH Batteries with BC100 \n
\r
52 13 * \par Documentation
\r
53 14 * For comprehensive code documentation, supported compilers, compiler
\r
54 15 * settings and supported devices see readme.html
\r
57 18 * Atmel Corporation: http://www.atmel.com \n
\r
58 19 * Support email: avr@atmel.com
\r
62 23 * $Revision: 2255 $
\r
64 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $
\r
65 26 * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n
\r
66 27 ******************************************************************************/
\r
68 29 #include <ioavr.h>
\r
70 31 #include "enums.h"
\r
71 32 #include "structs.h"
\r
73 34 #include "battery.h"
\r
74 35 #include "charge.h"
\r
75 36 #include "chargefunc.h"
\r
76 37 #include "main.h"
\r
77 38 #include "menu.h"
\r
78 39 #include "NIMHspecs.h"
\r
80 41 #include "time.h"
\r
83 44 #error NIMH not defined in main.h!
\r
87 48 //******************************************************************************
\r
89 50 //******************************************************************************
\r
90 51 /*! \brief Controls the charging.
\r
92 53 * This function contains the charging algorithm itself, divided into stages.\n
\r
93 54 * For each stage the PWM may be started/stopped, and the timer,
\r
94 55 * halt-requirements and charge parameters may be set.\n
\r
95 56 * The charging functions return whatever state is next, and as long as no
\r
96 57 * errors occur this is the next charging stage.
\r
98 59 * \note If more stages are needed simply define more states in menu.h, include
\r
99 60 * them in \ref menu_state[] in menu.c, then add the cases to this function.
\r
101 62 * \note This algorithm is for NiMH batteries.
\r
104 \ In segment CODE, align 2, keep-with-next
\r
105 64 unsigned char Charge(unsigned char inp)
\r
108 66 unsigned char NextState;
\r
110 68 switch (CurrentState) {
\r
111 \ 00000000 9100.... LDS R16, CurrentState
\r
112 \ 00000004 510E SUBI R16, 30
\r
113 \ 00000006 F049 BREQ ??Charge_0
\r
114 \ 00000008 5104 SUBI R16, 20
\r
115 \ 0000000A F149 BREQ ??Charge_1
\r
116 \ 0000000C 500A SUBI R16, 10
\r
117 \ 0000000E F409 BRNE $+2+2
\r
118 \ 00000010 C04A RJMP ??Charge_2
\r
119 \ 00000012 500A SUBI R16, 10
\r
120 \ 00000014 F409 BRNE $+2+2
\r
121 \ 00000016 C05E RJMP ??Charge_3
\r
122 \ 00000018 C077 RJMP ??Charge_4
\r
123 69 // First stage is a prequalification. Attempt to charge battery to 1 V,
\r
124 70 // using a 0.1 C current, within 2 minutes.
\r
125 71 // If this fails, the battery is likely damaged.
\r
126 72 // If it succeeds, start a fast charge.
\r
127 73 case ST_PREQUAL:
\r
129 75 // Set up charge current and next state.
\r
130 76 ChargeParameters.Current = BattData.Capacity / 10;
\r
132 \ 0000001A .... LDI R30, LOW(BattData)
\r
133 \ 0000001C .... LDI R31, (BattData) >> 8
\r
134 \ 0000001E 8104 LDD R16, Z+4
\r
135 \ 00000020 8115 LDD R17, Z+5
\r
136 \ 00000022 E04A LDI R20, 10
\r
137 \ 00000024 E050 LDI R21, 0
\r
138 \ 00000026 .... RCALL ?US_DIVMOD_L02
\r
139 \ 00000028 .... LDI R30, LOW(ChargeParameters)
\r
140 \ 0000002A .... LDI R31, (ChargeParameters) >> 8
\r
141 \ 0000002C 8302 STD Z+2, R16
\r
142 \ 0000002E 8313 STD Z+3, R17
\r
143 77 ChargeParameters.NextState = ST_FASTCHARGE;
\r
144 \ 00000030 E302 LDI R16, 50
\r
145 \ 00000032 8304 STD Z+4, R16
\r
147 79 // Halt charge on voltage limit or timeout.
\r
148 80 // Timeout means battery exhaustion.
\r
149 81 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |
\r
150 82 HALT_FLAG_EXHAUSTION);
\r
151 \ 00000034 .... LDI R30, LOW(HaltParameters)
\r
152 \ 00000036 .... LDI R31, (HaltParameters) >> 8
\r
153 \ 00000038 8300 ST Z, R16
\r
155 84 // Set up voltage limit and temperature limits.
\r
156 85 HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;
\r
157 \ 0000003A EB08 LDI R16, 184
\r
158 \ 0000003C E01B LDI R17, 11
\r
159 \ 0000003E 8303 STD Z+3, R16
\r
160 \ 00000040 8314 STD Z+4, R17
\r
161 86 HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;
\r
162 \ 00000042 E005 LDI R16, 5
\r
163 \ 00000044 E010 LDI R17, 0
\r
164 \ 00000046 8701 STD Z+9, R16
\r
165 \ 00000048 8712 STD Z+10, R17
\r
166 87 HaltParameters.TemperatureMax = 35;
\r
167 \ 0000004A E203 LDI R16, 35
\r
168 \ 0000004C 8307 STD Z+7, R16
\r
169 \ 0000004E 8710 STD Z+8, R17
\r
171 89 // Reset temperature measurement for HaltNow().
\r
172 90 HaltParameters.LastNTC = 0;
\r
173 \ 00000050 8717 STD Z+15, R17
\r
174 \ 00000052 8B10 STD Z+16, R17
\r
176 92 // Start PWM and charge timer before calling the charge function.
\r
178 \ 00000054 .... RCALL PWM_Start
\r
179 94 Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);
\r
180 \ 00000056 E040 LDI R20, 0
\r
181 \ 00000058 E010 LDI R17, 0
\r
182 \ 0000005A E022 LDI R18, 2
\r
183 \ 0000005C C037 RJMP ??Charge_5
\r
185 96 // Call charge function, get next state.
\r
186 97 NextState = ConstantCurrent();
\r
190 101 // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,
\r
191 102 // until either rate of temperature increase or voltage reaches limit, or
\r
192 103 // the voltage drops sufficiently.
\r
193 104 // Timeout doesn't mean battery exhaustion now.
\r
194 105 case ST_FASTCHARGE:
\r
196 107 // Set up charge current and next state.
\r
197 108 ChargeParameters.Current = BattData.Capacity;
\r
199 \ 0000005E .... LDI R18, LOW(BattData)
\r
200 \ 00000060 .... LDI R19, (BattData) >> 8
\r
201 \ 00000062 01F9 MOVW R31:R30, R19:R18
\r
202 \ 00000064 8104 LDD R16, Z+4
\r
203 \ 00000066 8115 LDD R17, Z+5
\r
204 \ 00000068 .... LDI R30, LOW(ChargeParameters)
\r
205 \ 0000006A .... LDI R31, (ChargeParameters) >> 8
\r
206 \ 0000006C 8302 STD Z+2, R16
\r
207 \ 0000006E 8313 STD Z+3, R17
\r
208 109 ChargeParameters.NextState = ST_LOWRATECHARGE;
\r
209 \ 00000070 E30C LDI R16, 60
\r
210 \ 00000072 8304 STD Z+4, R16
\r
212 111 // Halt charge on voltage limit, timeout, voltage drop or rate of
\r
213 112 // temperature increase.
\r
214 113 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |
\r
215 114 HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);
\r
216 \ 00000074 .... LDI R30, LOW(HaltParameters)
\r
217 \ 00000076 .... LDI R31, (HaltParameters) >> 8
\r
218 \ 00000078 E10B LDI R16, 27
\r
219 \ 0000007A 8300 ST Z, R16
\r
221 116 // Set up limits for voltage, voltage drop, temperature and rate of
\r
222 117 // temperature increase (1 degree C per minute).
\r
223 118 HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;
\r
224 \ 0000007C EC00 LDI R16, 192
\r
225 \ 0000007E E112 LDI R17, 18
\r
226 \ 00000080 8303 STD Z+3, R16
\r
227 \ 00000082 8314 STD Z+4, R17
\r
228 119 HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;
\r
229 \ 00000084 E20D LDI R16, 45
\r
230 \ 00000086 E010 LDI R17, 0
\r
231 \ 00000088 8301 STD Z+1, R16
\r
232 \ 0000008A 8312 STD Z+2, R17
\r
233 120 HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;
\r
234 \ 0000008C E302 LDI R16, 50
\r
235 \ 0000008E 8307 STD Z+7, R16
\r
236 \ 00000090 8710 STD Z+8, R17
\r
237 121 HaltParameters.TemperatureRise = 1;
\r
238 \ 00000092 E001 LDI R16, 1
\r
239 \ 00000094 8703 STD Z+11, R16
\r
240 \ 00000096 8714 STD Z+12, R17
\r
242 123 // Reset maximum voltage measurement for HaltNow().
\r
243 124 HaltParameters.VBATMax = 0;
\r
244 \ 00000098 8715 STD Z+13, R17
\r
245 \ 0000009A 8716 STD Z+14, R17
\r
247 126 // Start timer, PWM should still be running.
\r
248 127 Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);
\r
249 \ 0000009C E040 LDI R20, 0
\r
250 \ 0000009E 01F9 MOVW R31:R30, R19:R18
\r
251 \ 000000A0 8520 LDD R18, Z+8
\r
252 \ 000000A2 8531 LDD R19, Z+9
\r
253 \ 000000A4 C015 RJMP ??Charge_6
\r
255 129 // Call charge function, get next state.
\r
256 130 NextState = ConstantCurrent();
\r
260 134 // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,
\r
261 135 // until either rate of temperature increase or voltage reaches limit.
\r
262 136 case ST_LOWRATECHARGE:
\r
264 138 // Set up charge current and next state.
\r
265 139 ChargeParameters.Current = BattData.Capacity / 10;
\r
267 \ 000000A6 .... LDI R30, LOW(BattData)
\r
268 \ 000000A8 .... LDI R31, (BattData) >> 8
\r
269 \ 000000AA 8104 LDD R16, Z+4
\r
270 \ 000000AC 8115 LDD R17, Z+5
\r
271 \ 000000AE E04A LDI R20, 10
\r
272 \ 000000B0 E050 LDI R21, 0
\r
273 \ 000000B2 .... RCALL ?US_DIVMOD_L02
\r
274 \ 000000B4 .... LDI R30, LOW(ChargeParameters)
\r
275 \ 000000B6 .... LDI R31, (ChargeParameters) >> 8
\r
276 \ 000000B8 8302 STD Z+2, R16
\r
277 \ 000000BA 8313 STD Z+3, R17
\r
278 140 ChargeParameters.NextState = ST_ENDCHARGE;
\r
279 \ 000000BC E406 LDI R16, 70
\r
280 \ 000000BE 8304 STD Z+4, R16
\r
282 142 // Halt charge on voltage limit, timeout or temperature rise.
\r
283 143 // Use the same requirements as during the last stage (ST_FASTCHARGE).
\r
284 144 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |
\r
285 145 HALT_TEMPERATURE_RISE);
\r
286 \ 000000C0 E10A LDI R16, 26
\r
287 \ 000000C2 9300.... STS HaltParameters, R16
\r
289 147 // Start timer, 30 minutes.
\r
290 148 Time_Set(TIMER_CHG, 30, 0, 0);
\r
291 \ 000000C6 E040 LDI R20, 0
\r
292 \ 000000C8 E010 LDI R17, 0
\r
293 \ 000000CA E12E LDI R18, 30
\r
295 \ 000000CC E030 LDI R19, 0
\r
296 \ 000000CE E001 LDI R16, 1
\r
298 \ 000000D0 .... RCALL Time_Set
\r
300 150 // Call charge function, get next state.
\r
301 151 NextState = ConstantCurrent();
\r
302 \ 000000D2 .... RJMP ConstantCurrent
\r
306 155 // Charging is done!
\r
307 156 case ST_ENDCHARGE:
\r
309 158 // Stop the PWM output and flag battery as charged.
\r
312 \ 000000D4 .... RCALL PWM_Stop
\r
313 160 BattData.Charged = TRUE;
\r
314 \ 000000D6 .... LDI R30, LOW(BattData)
\r
315 \ 000000D8 .... LDI R31, (BattData) >> 8
\r
316 \ 000000DA 8100 LD R16, Z
\r
317 \ 000000DC 6002 ORI R16, 0x02
\r
318 \ 000000DE 8300 ST Z, R16
\r
320 162 // If the other battery is enabled go to ST_BATCON, otherwise
\r
321 163 // go to ST_SLEEP.
\r
322 164 if (BattControl[(BattActive+1)%2].Enabled) {
\r
323 \ 000000E0 9100.... LDS R16, BattActive
\r
324 \ 000000E4 E010 LDI R17, 0
\r
325 \ 000000E6 5F0F SUBI R16, 255
\r
326 \ 000000E8 4F1F SBCI R17, 255
\r
327 \ 000000EA E042 LDI R20, 2
\r
328 \ 000000EC E050 LDI R21, 0
\r
329 \ 000000EE .... RCALL ?SS_DIVMOD_L02
\r
330 \ 000000F0 .... LDI R18, LOW(BattControl)
\r
331 \ 000000F2 .... LDI R19, (BattControl) >> 8
\r
332 \ 000000F4 0F24 ADD R18, R20
\r
333 \ 000000F6 1F35 ADC R19, R21
\r
334 \ 000000F8 01A9 MOVW R21:R20, R19:R18
\r
335 \ 000000FA .... RCALL __eeget8_16
\r
336 \ 000000FC 7001 ANDI R16, 0x01
\r
337 \ 000000FE F011 BREQ ??Charge_7
\r
338 165 NextState = ST_BATCON;
\r
339 \ 00000100 E104 LDI R16, 20
\r
340 \ 00000102 9508 RET
\r
342 167 NextState = ST_SLEEP;
\r
344 \ 00000104 E208 LDI R16, 40
\r
345 \ 00000106 9508 RET
\r
350 172 default: // Shouldn't end up here. Reinitialize for safety.
\r
351 173 NextState = ST_INIT;
\r
353 \ 00000108 E00A LDI R16, 10
\r
357 177 // Return the next state to main().
\r
358 178 return(NextState);
\r
359 \ 0000010A 9508 RET
\r
362 Maximum stack usage in bytes:
\r
364 Function CSTACK RSTACK
\r
365 -------- ------ ------
\r
369 -> ConstantCurrent 2 2
\r
371 -> ConstantCurrent 2 2
\r
373 -> ConstantCurrent 2 2
\r
377 Segment part sizes:
\r
379 Function/Label Bytes
\r
380 -------------- -----
\r
384 268 bytes in segment CODE
\r
386 268 bytes of CODE memory
\r