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\PWM.c #
\r
7 # Command line = C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c --cpu=tiny861 #
\r
8 # -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ #
\r
9 # -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB #
\r
10 # C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ #
\r
11 # --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\PWM.lst #
\r
19 # Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\PWM.r90 #
\r
22 ###############################################################################
\r
24 C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c
\r
25 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
26 2 /*! \file *********************************************************************
\r
29 5 * Functions for use of PWM
\r
31 7 * Contains functions for initializing and controlling PWM output.
\r
33 9 * \par Application note:
\r
34 10 * AVR458: Charging Li-Ion Batteries with BC100\n
\r
35 11 * AVR463: Charging NiMH Batteries with BC100
\r
37 13 * \par Documentation
\r
38 14 * For comprehensive code documentation, supported compilers, compiler
\r
39 15 * settings and supported devices see readme.html
\r
42 18 * Atmel Corporation: http://www.atmel.com \n
\r
43 19 * Support email: avr@atmel.com
\r
47 23 * $Revision: 2299 $
\r
49 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $
\r
50 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n
\r
51 27 ******************************************************************************/
\r
53 29 #include <ioavr.h>
\r
55 \ In segment ABSOLUTE, at 0x50
\r
56 \ <unnamed> volatile __io _A_TCCR1A
\r
60 \ In segment ABSOLUTE, at 0x4f
\r
61 \ <unnamed> volatile __io _A_TCCR1B
\r
65 \ In segment ABSOLUTE, at 0x4d
\r
66 \ <unnamed> volatile __io _A_OCR1A
\r
70 \ In segment ABSOLUTE, at 0x4c
\r
71 \ <unnamed> volatile __io _A_OCR1B
\r
75 \ In segment ABSOLUTE, at 0x4b
\r
76 \ <unnamed> volatile __io _A_OCR1C
\r
80 \ In segment ABSOLUTE, at 0x4a
\r
81 \ <unnamed> volatile __io _A_OCR1D
\r
85 \ In segment ABSOLUTE, at 0x49
\r
86 \ <unnamed> volatile __io _A_PLLCSR
\r
90 \ In segment ABSOLUTE, at 0x47
\r
91 \ <unnamed> volatile __io _A_TCCR1C
\r
95 \ In segment ABSOLUTE, at 0x46
\r
96 \ <unnamed> volatile __io _A_TCCR1D
\r
100 \ In segment ABSOLUTE, at 0x44
\r
101 \ <unnamed> volatile __io _A_DT1
\r
105 \ In segment ABSOLUTE, at 0x37
\r
106 \ <unnamed> volatile __io _A_DDRB
\r
110 \ In segment ABSOLUTE, at 0x20
\r
111 \ <unnamed> volatile __io _A_TCCR1E
\r
115 31 #include "enums.h"
\r
117 33 #include "main.h"
\r
118 34 #include "PWM.h"
\r
119 35 #include "time.h"
\r
122 38 //******************************************************************************
\r
124 40 //******************************************************************************
\r
125 41 /*! \brief Stops PWM output
\r
129 \ In segment CODE, align 2, keep-with-next
\r
130 44 void PWM_Stop(void)
\r
133 46 OCR1B = 0; // Reset compare level.
\r
134 \ 00000000 E000 LDI R16, 0
\r
135 \ 00000002 BD0C OUT 0x2C, R16
\r
136 47 PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.
\r
137 \ 00000004 E000 LDI R16, 0
\r
138 \ 00000006 BD09 OUT 0x29, R16
\r
139 48 TCCR1A = 0; // Set normal port operation, disable PWM modes.
\r
140 \ 00000008 E000 LDI R16, 0
\r
141 \ 0000000A BF00 OUT 0x30, R16
\r
142 49 TCCR1B = 0; // Stop timer/counter1.
\r
143 \ 0000000C E000 LDI R16, 0
\r
144 \ 0000000E BD0F OUT 0x2F, R16
\r
145 50 TCCR1C = 0; // Set normal port operation.
\r
146 \ 00000010 E000 LDI R16, 0
\r
147 \ 00000012 BD07 OUT 0x27, R16
\r
148 51 TCCR1D = 0; // No fault protection, normal waveform.
\r
149 \ 00000014 E000 LDI R16, 0
\r
150 \ 00000016 BD06 OUT 0x26, R16
\r
151 52 OCR1C = 0; // Reset compare.
\r
152 \ 00000018 E000 LDI R16, 0
\r
153 \ 0000001A BD0B OUT 0x2B, R16
\r
154 53 OCR1D = 0; // Reset compare.
\r
155 \ 0000001C E000 LDI R16, 0
\r
156 \ 0000001E BD0A OUT 0x2A, R16
\r
157 54 DT1 = 0; // No dead time values.
\r
158 \ 00000020 E000 LDI R16, 0
\r
159 \ 00000022 BD04 OUT 0x24, R16
\r
161 \ 00000024 9508 RET
\r
162 \ 00000026 REQUIRE _A_TCCR1A
\r
163 \ 00000026 REQUIRE _A_TCCR1B
\r
164 \ 00000026 REQUIRE _A_OCR1B
\r
165 \ 00000026 REQUIRE _A_OCR1C
\r
166 \ 00000026 REQUIRE _A_OCR1D
\r
167 \ 00000026 REQUIRE _A_PLLCSR
\r
168 \ 00000026 REQUIRE _A_TCCR1C
\r
169 \ 00000026 REQUIRE _A_TCCR1D
\r
170 \ 00000026 REQUIRE _A_DT1
\r
173 58 /*! \brief Initializes and starts PWM output
\r
175 60 * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n
\r
176 61 * Its comparator is connected to PB3 and will output high until timer1 reaches
\r
177 62 * the value of OCR1B. It is then dropped to 0.\n
\r
178 63 * The comparator outputs high again when the counter overflows, which will
\r
179 64 * happen at a rate of 250 kHz.
\r
182 \ In segment CODE, align 2, keep-with-next
\r
183 66 void PWM_Start(void)
\r
186 68 // Clear OC1B on compare match, enable PWM on comparator OCR1B.
\r
187 69 TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);
\r
188 \ 00000000 E201 LDI R16, 33
\r
189 \ 00000002 BF00 OUT 0x30, R16
\r
191 71 // Non-inverted PWM, T/C stopped.
\r
193 \ 00000004 E000 LDI R16, 0
\r
194 \ 00000006 BD0F OUT 0x2F, R16
\r
196 74 // Copy shadow bits, disconnect OC1D.
\r
197 75 TCCR1C = (TCCR1A & 0xF0);
\r
198 \ 00000008 B700 IN R16, 0x30
\r
199 \ 0000000A 7F00 ANDI R16, 0xF0
\r
200 \ 0000000C BD07 OUT 0x27, R16
\r
202 77 // No fault protection, use phase & frequency correct PWM.
\r
203 78 TCCR1D = (0<<WGM11)|(1<WGM10);
\r
204 \ 0000000E E000 LDI R16, 0
\r
205 \ 00000010 BD06 OUT 0x26, R16
\r
207 80 // Does not matter -- PWM6 mode not used.
\r
209 \ 00000012 E000 LDI R16, 0
\r
210 \ 00000014 B900 OUT 0x00, R16
\r
212 83 // Does not matter -- OC1A is disabled.
\r
214 \ 00000016 E000 LDI R16, 0
\r
215 \ 00000018 BD0D OUT 0x2D, R16
\r
217 86 // Set reset compare level. (Offset is used, or JumperCheck() will fail.)
\r
218 87 OCR1B = PWM_OFFSET;
\r
219 \ 0000001A E00C LDI R16, 12
\r
220 \ 0000001C BD0C OUT 0x2C, R16
\r
222 89 // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.
\r
224 \ 0000001E EF0F LDI R16, 255
\r
225 \ 00000020 BD0B OUT 0x2B, R16
\r
227 92 // Does not matter -- OC1D is disabled.
\r
229 \ 00000022 E000 LDI R16, 0
\r
230 \ 00000024 BD0A OUT 0x2A, R16
\r
232 95 // No dead time values.
\r
234 \ 00000026 E000 LDI R16, 0
\r
235 \ 00000028 BD04 OUT 0x24, R16
\r
237 98 // Set PWM port pin to output.
\r
238 99 DDRB |= (1<<PB3);
\r
239 \ 0000002A 9ABB SBI 0x17, 0x03
\r
241 101 // Enable PLL, use full speed mode.
\r
242 102 PLLCSR = (0<<LSM) | (1<<PLLE);
\r
243 \ 0000002C E002 LDI R16, 2
\r
244 \ 0000002E BD09 OUT 0x29, R16
\r
246 104 // Use general timer and wait 1 ms for PLL lock to settle.
\r
247 105 Time_Set(TIMER_GEN,0,0,1);
\r
248 \ 00000030 E041 LDI R20, 1
\r
249 \ 00000032 E010 LDI R17, 0
\r
250 \ 00000034 E020 LDI R18, 0
\r
251 \ 00000036 E030 LDI R19, 0
\r
252 \ 00000038 E002 LDI R16, 2
\r
253 \ 0000003A .... RCALL Time_Set
\r
255 107 }while(Time_Left(TIMER_GEN));
\r
257 \ 0000003C E002 LDI R16, 2
\r
258 \ 0000003E .... RCALL Time_Left
\r
259 \ 00000040 2300 TST R16
\r
260 \ 00000042 F7E1 BRNE ??PWM_Start_0
\r
262 109 // Now wait for PLL to lock.
\r
264 111 }while((PLLCSR & (1<<PLOCK)) == 0);
\r
266 \ 00000044 B509 IN R16, 0x29
\r
267 \ 00000046 2F10 MOV R17, R16
\r
268 \ 00000048 FF10 SBRS R17, 0
\r
269 \ 0000004A CFFC RJMP ??PWM_Start_1
\r
271 113 // Use PLL as clock source.
\r
272 114 PLLCSR |= (1<<PCKE);
\r
273 \ 0000004C B509 IN R16, 0x29
\r
274 \ 0000004E 6004 ORI R16, 0x04
\r
275 \ 00000050 BD09 OUT 0x29, R16
\r
277 116 // CLK PCK = 64MHz / 1 = 64MHz.
\r
278 117 TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);
\r
279 \ 00000052 B50F IN R16, 0x2F
\r
280 \ 00000054 6001 ORI R16, 0x01
\r
281 \ 00000056 BD0F OUT 0x2F, R16
\r
283 \ 00000058 9508 RET
\r
284 \ 0000005A REQUIRE _A_TCCR1A
\r
285 \ 0000005A REQUIRE _A_TCCR1B
\r
286 \ 0000005A REQUIRE _A_OCR1A
\r
287 \ 0000005A REQUIRE _A_OCR1B
\r
288 \ 0000005A REQUIRE _A_OCR1C
\r
289 \ 0000005A REQUIRE _A_OCR1D
\r
290 \ 0000005A REQUIRE _A_PLLCSR
\r
291 \ 0000005A REQUIRE _A_TCCR1C
\r
292 \ 0000005A REQUIRE _A_TCCR1D
\r
293 \ 0000005A REQUIRE _A_DT1
\r
294 \ 0000005A REQUIRE _A_DDRB
\r
295 \ 0000005A REQUIRE _A_TCCR1E
\r
298 121 /*! \brief Increments the PWM duty cycle, if not already at max
\r
300 123 * \retval TRUE Success, duty cycle could be incremented.
\r
301 124 * \retval FALSE Failure, duty cycle already at maximum.
\r
304 \ In segment CODE, align 2, keep-with-next
\r
305 126 unsigned char PWM_IncrementDutyCycle(void){
\r
306 \ PWM_IncrementDutyCycle:
\r
308 128 if (OCR1B < PWM_MAX) {
\r
309 \ 00000000 B50C IN R16, 0x2C
\r
310 \ 00000002 3F0F CPI R16, 255
\r
311 \ 00000004 F428 BRCC ??PWM_IncrementDutyCycle_0
\r
313 \ 00000006 B50C IN R16, 0x2C
\r
314 \ 00000008 9503 INC R16
\r
315 \ 0000000A BD0C OUT 0x2C, R16
\r
317 \ 0000000C E001 LDI R16, 1
\r
318 \ 0000000E 9508 RET
\r
321 \ ??PWM_IncrementDutyCycle_0:
\r
322 \ 00000010 E000 LDI R16, 0
\r
323 \ 00000012 9508 RET
\r
324 \ 00000014 REQUIRE _A_OCR1B
\r
329 137 /*! \brief Decrements the PWM duty cycle, if not already at zero.
\r
331 139 * \retval TRUE Success, duty cycle could be decremented.
\r
332 140 * \retval FALSE Failure, duty cycle already at zero.
\r
335 \ In segment CODE, align 2, keep-with-next
\r
336 142 unsigned char PWM_DecrementDutyCycle(void){
\r
337 \ PWM_DecrementDutyCycle:
\r
339 144 if (OCR1B > 0) {
\r
340 \ 00000000 B50C IN R16, 0x2C
\r
341 \ 00000002 3001 CPI R16, 1
\r
342 \ 00000004 F028 BRCS ??PWM_DecrementDutyCycle_0
\r
344 \ 00000006 B50C IN R16, 0x2C
\r
345 \ 00000008 950A DEC R16
\r
346 \ 0000000A BD0C OUT 0x2C, R16
\r
348 \ 0000000C E001 LDI R16, 1
\r
349 \ 0000000E 9508 RET
\r
352 \ ??PWM_DecrementDutyCycle_0:
\r
353 \ 00000010 E000 LDI R16, 0
\r
354 \ 00000012 9508 RET
\r
355 \ 00000014 REQUIRE _A_OCR1B
\r
359 Maximum stack usage in bytes:
\r
361 Function CSTACK RSTACK
\r
362 -------- ------ ------
\r
363 PWM_DecrementDutyCycle 0 2
\r
364 PWM_IncrementDutyCycle 0 2
\r
371 Segment part sizes:
\r
373 Function/Label Bytes
\r
374 -------------- -----
\r
389 PWM_IncrementDutyCycle 20
\r
390 PWM_DecrementDutyCycle 20
\r
393 12 bytes in segment ABSOLUTE
\r
394 168 bytes in segment CODE
\r
396 168 bytes of CODE memory
\r
397 0 bytes of DATA memory (+ 12 bytes shared)
\r