1 ###############################################################################
\r
3 # IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 #
\r
4 # Copyright 1996-2007 IAR Systems. All rights reserved. #
\r
6 # Source file = C:\home\kevin\pub\src\bc100\IAR\PWM.c #
\r
7 # Command line = C:\home\kevin\pub\src\bc100\IAR\PWM.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\PW #
\r
33 # Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM #
\r
37 ###############################################################################
\r
39 C:\home\kevin\pub\src\bc100\IAR\PWM.c
\r
40 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
41 2 /*! \file *********************************************************************
\r
44 5 * Functions for use of PWM
\r
46 7 * Contains functions for initializing and controlling PWM output.
\r
48 9 * \par Application note:
\r
49 10 * AVR458: Charging Li-Ion Batteries with BC100\n
\r
50 11 * AVR463: Charging NiMH Batteries with BC100
\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: 2299 $
\r
64 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
65 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n
\r
66 27 ******************************************************************************/
\r
68 29 #include <ioavr.h>
\r
70 \ In segment ABSOLUTE, at 0x50
\r
71 \ <unnamed> volatile __io _A_TCCR1A
\r
75 \ In segment ABSOLUTE, at 0x4f
\r
76 \ <unnamed> volatile __io _A_TCCR1B
\r
80 \ In segment ABSOLUTE, at 0x4d
\r
81 \ <unnamed> volatile __io _A_OCR1A
\r
85 \ In segment ABSOLUTE, at 0x4c
\r
86 \ <unnamed> volatile __io _A_OCR1B
\r
90 \ In segment ABSOLUTE, at 0x4b
\r
91 \ <unnamed> volatile __io _A_OCR1C
\r
95 \ In segment ABSOLUTE, at 0x4a
\r
96 \ <unnamed> volatile __io _A_OCR1D
\r
100 \ In segment ABSOLUTE, at 0x49
\r
101 \ <unnamed> volatile __io _A_PLLCSR
\r
105 \ In segment ABSOLUTE, at 0x47
\r
106 \ <unnamed> volatile __io _A_TCCR1C
\r
110 \ In segment ABSOLUTE, at 0x46
\r
111 \ <unnamed> volatile __io _A_TCCR1D
\r
115 \ In segment ABSOLUTE, at 0x44
\r
116 \ <unnamed> volatile __io _A_DT1
\r
120 \ In segment ABSOLUTE, at 0x37
\r
121 \ <unnamed> volatile __io _A_DDRB
\r
125 \ In segment ABSOLUTE, at 0x20
\r
126 \ <unnamed> volatile __io _A_TCCR1E
\r
130 31 #include "enums.h"
\r
132 33 #include "main.h"
\r
133 34 #include "PWM.h"
\r
134 35 #include "time.h"
\r
137 38 //******************************************************************************
\r
139 40 //******************************************************************************
\r
140 41 /*! \brief Stops PWM output
\r
144 \ In segment CODE, align 2, keep-with-next
\r
145 44 void PWM_Stop(void)
\r
148 46 OCR1B = 0; // Reset compare level.
\r
149 \ 00000000 E000 LDI R16, 0
\r
150 \ 00000002 BD0C OUT 0x2C, R16
\r
151 47 PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.
\r
152 \ 00000004 BD09 OUT 0x29, R16
\r
153 48 TCCR1A = 0; // Set normal port operation, disable PWM modes.
\r
154 \ 00000006 BF00 OUT 0x30, R16
\r
155 49 TCCR1B = 0; // Stop timer/counter1.
\r
156 \ 00000008 BD0F OUT 0x2F, R16
\r
157 50 TCCR1C = 0; // Set normal port operation.
\r
158 \ 0000000A BD07 OUT 0x27, R16
\r
159 51 TCCR1D = 0; // No fault protection, normal waveform.
\r
160 \ 0000000C BD06 OUT 0x26, R16
\r
161 52 OCR1C = 0; // Reset compare.
\r
162 \ 0000000E BD0B OUT 0x2B, R16
\r
163 53 OCR1D = 0; // Reset compare.
\r
164 \ 00000010 BD0A OUT 0x2A, R16
\r
165 54 DT1 = 0; // No dead time values.
\r
166 \ 00000012 BD04 OUT 0x24, R16
\r
168 \ 00000014 9508 RET
\r
169 \ 00000016 REQUIRE _A_TCCR1A
\r
170 \ 00000016 REQUIRE _A_TCCR1B
\r
171 \ 00000016 REQUIRE _A_OCR1B
\r
172 \ 00000016 REQUIRE _A_OCR1C
\r
173 \ 00000016 REQUIRE _A_OCR1D
\r
174 \ 00000016 REQUIRE _A_PLLCSR
\r
175 \ 00000016 REQUIRE _A_TCCR1C
\r
176 \ 00000016 REQUIRE _A_TCCR1D
\r
177 \ 00000016 REQUIRE _A_DT1
\r
180 58 /*! \brief Initializes and starts PWM output
\r
182 60 * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n
\r
183 61 * Its comparator is connected to PB3 and will output high until timer1 reaches
\r
184 62 * the value of OCR1B. It is then dropped to 0.\n
\r
185 63 * The comparator outputs high again when the counter overflows, which will
\r
186 64 * happen at a rate of 250 kHz.
\r
189 \ In segment CODE, align 2, keep-with-next
\r
190 66 void PWM_Start(void)
\r
193 68 // Clear OC1B on compare match, enable PWM on comparator OCR1B.
\r
194 69 TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);
\r
195 \ 00000000 E201 LDI R16, 33
\r
196 \ 00000002 BF00 OUT 0x30, R16
\r
198 71 // Non-inverted PWM, T/C stopped.
\r
200 \ 00000004 E000 LDI R16, 0
\r
201 \ 00000006 BD0F OUT 0x2F, R16
\r
203 74 // Copy shadow bits, disconnect OC1D.
\r
204 75 TCCR1C = (TCCR1A & 0xF0);
\r
205 \ 00000008 B700 IN R16, 0x30
\r
206 \ 0000000A 7F00 ANDI R16, 0xF0
\r
207 \ 0000000C BD07 OUT 0x27, R16
\r
209 77 // No fault protection, use phase & frequency correct PWM.
\r
210 78 TCCR1D = (0<<WGM11)|(1<WGM10);
\r
211 \ 0000000E E000 LDI R16, 0
\r
212 \ 00000010 BD06 OUT 0x26, R16
\r
214 80 // Does not matter -- PWM6 mode not used.
\r
216 \ 00000012 B900 OUT 0x00, R16
\r
218 83 // Does not matter -- OC1A is disabled.
\r
220 \ 00000014 BD0D OUT 0x2D, R16
\r
222 86 // Set reset compare level. (Offset is used, or JumperCheck() will fail.)
\r
223 87 OCR1B = PWM_OFFSET;
\r
224 \ 00000016 E00C LDI R16, 12
\r
225 \ 00000018 BD0C OUT 0x2C, R16
\r
227 89 // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.
\r
229 \ 0000001A EF0F LDI R16, 255
\r
230 \ 0000001C BD0B OUT 0x2B, R16
\r
232 92 // Does not matter -- OC1D is disabled.
\r
234 \ 0000001E E000 LDI R16, 0
\r
235 \ 00000020 BD0A OUT 0x2A, R16
\r
237 95 // No dead time values.
\r
239 \ 00000022 BD04 OUT 0x24, R16
\r
241 98 // Set PWM port pin to output.
\r
242 99 DDRB |= (1<<PB3);
\r
243 \ 00000024 9ABB SBI 0x17, 0x03
\r
245 101 // Enable PLL, use full speed mode.
\r
246 102 PLLCSR = (0<<LSM) | (1<<PLLE);
\r
247 \ 00000026 E002 LDI R16, 2
\r
248 \ 00000028 BD09 OUT 0x29, R16
\r
250 104 // Use general timer and wait 1 ms for PLL lock to settle.
\r
251 105 Time_Set(TIMER_GEN,0,0,1);
\r
252 \ 0000002A E041 LDI R20, 1
\r
253 \ 0000002C E010 LDI R17, 0
\r
254 \ 0000002E E020 LDI R18, 0
\r
255 \ 00000030 E030 LDI R19, 0
\r
256 \ 00000032 .... RCALL Time_Set
\r
258 107 }while(Time_Left(TIMER_GEN));
\r
260 \ 00000034 E002 LDI R16, 2
\r
261 \ 00000036 .... RCALL Time_Left
\r
262 \ 00000038 2300 TST R16
\r
263 \ 0000003A F7E1 BRNE ??PWM_Start_0
\r
265 109 // Now wait for PLL to lock.
\r
267 111 }while((PLLCSR & (1<<PLOCK)) == 0);
\r
269 \ 0000003C B509 IN R16, 0x29
\r
270 \ 0000003E FF00 SBRS R16, 0
\r
271 \ 00000040 CFFD RJMP ??PWM_Start_1
\r
273 113 // Use PLL as clock source.
\r
274 114 PLLCSR |= (1<<PCKE);
\r
275 \ 00000042 B509 IN R16, 0x29
\r
276 \ 00000044 6004 ORI R16, 0x04
\r
277 \ 00000046 BD09 OUT 0x29, R16
\r
279 116 // CLK PCK = 64MHz / 1 = 64MHz.
\r
280 117 TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);
\r
281 \ 00000048 B50F IN R16, 0x2F
\r
282 \ 0000004A 6001 ORI R16, 0x01
\r
283 \ 0000004C BD0F OUT 0x2F, R16
\r
285 \ 0000004E 9508 RET
\r
286 \ 00000050 REQUIRE _A_TCCR1A
\r
287 \ 00000050 REQUIRE _A_TCCR1B
\r
288 \ 00000050 REQUIRE _A_OCR1A
\r
289 \ 00000050 REQUIRE _A_OCR1B
\r
290 \ 00000050 REQUIRE _A_OCR1C
\r
291 \ 00000050 REQUIRE _A_OCR1D
\r
292 \ 00000050 REQUIRE _A_PLLCSR
\r
293 \ 00000050 REQUIRE _A_TCCR1C
\r
294 \ 00000050 REQUIRE _A_TCCR1D
\r
295 \ 00000050 REQUIRE _A_DT1
\r
296 \ 00000050 REQUIRE _A_DDRB
\r
297 \ 00000050 REQUIRE _A_TCCR1E
\r
300 121 /*! \brief Increments the PWM duty cycle, if not already at max
\r
302 123 * \retval TRUE Success, duty cycle could be incremented.
\r
303 124 * \retval FALSE Failure, duty cycle already at maximum.
\r
306 \ In segment CODE, align 2, keep-with-next
\r
307 126 unsigned char PWM_IncrementDutyCycle(void){
\r
308 \ PWM_IncrementDutyCycle:
\r
310 128 if (OCR1B < PWM_MAX) {
\r
311 \ 00000000 B50C IN R16, 0x2C
\r
312 \ 00000002 3F0F CPI R16, 255
\r
313 \ 00000004 F029 BREQ ??PWM_IncrementDutyCycle_0
\r
315 \ 00000006 B50C IN R16, 0x2C
\r
316 \ 00000008 9503 INC R16
\r
317 \ 0000000A BD0C OUT 0x2C, R16
\r
319 \ 0000000C E001 LDI R16, 1
\r
320 \ 0000000E 9508 RET
\r
323 \ ??PWM_IncrementDutyCycle_0:
\r
324 \ 00000010 E000 LDI R16, 0
\r
325 \ 00000012 9508 RET
\r
326 \ 00000014 REQUIRE _A_OCR1B
\r
331 137 /*! \brief Decrements the PWM duty cycle, if not already at zero.
\r
333 139 * \retval TRUE Success, duty cycle could be decremented.
\r
334 140 * \retval FALSE Failure, duty cycle already at zero.
\r
337 \ In segment CODE, align 2, keep-with-next
\r
338 142 unsigned char PWM_DecrementDutyCycle(void){
\r
339 \ PWM_DecrementDutyCycle:
\r
341 144 if (OCR1B > 0) {
\r
342 \ 00000000 B50C IN R16, 0x2C
\r
343 \ 00000002 2300 TST R16
\r
344 \ 00000004 F029 BREQ ??PWM_DecrementDutyCycle_0
\r
346 \ 00000006 B50C IN R16, 0x2C
\r
347 \ 00000008 950A DEC R16
\r
348 \ 0000000A BD0C OUT 0x2C, R16
\r
350 \ 0000000C E001 LDI R16, 1
\r
351 \ 0000000E 9508 RET
\r
354 \ ??PWM_DecrementDutyCycle_0:
\r
355 \ 00000010 E000 LDI R16, 0
\r
356 \ 00000012 9508 RET
\r
357 \ 00000014 REQUIRE _A_OCR1B
\r
361 Maximum stack usage in bytes:
\r
363 Function CSTACK RSTACK
\r
364 -------- ------ ------
\r
365 PWM_DecrementDutyCycle 0 2
\r
366 PWM_IncrementDutyCycle 0 2
\r
373 Segment part sizes:
\r
375 Function/Label Bytes
\r
376 -------------- -----
\r
391 PWM_IncrementDutyCycle 20
\r
392 PWM_DecrementDutyCycle 20
\r
395 12 bytes in segment ABSOLUTE
\r
396 142 bytes in segment CODE
\r
398 142 bytes of CODE memory
\r
399 0 bytes of DATA memory (+ 12 bytes shared)
\r