From: Erich W. <ew....@na...> - 2012-01-28 13:27:38
|
Hello, I'm currently working on a sensor which must be powered on battery. Measurements show that the idle atmega-32 sinks some 24 mA when idle. When going to "powersave" mode, energy consumption drops to 1 mA. In this mode timer2 (connected to a clock crystal) will continue to run. On timer2 overflow, the controller wakes up and continues the program. First, the timer2 interrupt service routine is run, which will increment ticks by 1. Then the main loop "run" will continue. If the counter "ticks" is above some threshold "idle.ticks", the scheduled job is called. Then the controller is sent back to sleep. Ticks are 8 seconds in the example below. Please find 2 files below: 1. sleep-m32.asm The bits controlling sleep mode are in a different register and position than in the atmega328p, from which the code in the repository is derived. I have not made any attempt to solve the problem at hand in a general way. Add this file instead in dict_appl_core.inc. 2. run_powersave.fs A working example which will light up LEDs connected to +5V and PORTB for 1 second, then go to sleep for 4 ticks (32 seconds). For timer2 a clock crystal must be connected. Enjoy, Erich \ ----------------------------------------------------------------- ; sleep-m32.asm ; sleep ( mode -- ) ; \ ---<snip>--- ; 2012-01-15 ew ; on atmega-32 sleep modes are handled via a different register ; MCUCR, not SMCR and bits at different bit location ; 6-4, not 3-1. ; SE is bit 7 not 0 ; ( mode -- ) ; MCU ; put the controller into the specified sleep mode VE_SLEEP: .dw $ff05 .db "sleep", 0 .dw VE_HEAD .set VE_HEAD = VE_SLEEP XT_SLEEP: .dw PFA_SLEEP PFA_SLEEP: andi tosl, 7 ; leave only legal mode bits swap tosl ; move to correct location (bits 6-4, atmega32) ori tosl, $80 ; set the SE bit (atmega32: bit 7, not bit 0) out MCUCR, tosl ; set the sleep config (atmega32: MCUCR not SMCR) sleep ; nighty-night ;; atmega32: the 4 lower bits of MCUCR should not be touched in tosl, MCUCR andi tosl, $0F out MCUCR, tosl ;clr tosl ; need to clean up the SMCR reg before we leave ;out SMCR, tosl ; 0 protects against accidental sleeps loadtos ; pop argument from stack jmp DO_NEXT \ ----------------------------------------------------------------- \ 2012-01-26 ew run_powersafe.fs \ tested on atmega-32, amforth-4.6 \ timer2 on clock crystal, overflow after 8 secs \ timer2-isr: increment counter ticks \ stolen from devices/atmega32/atmega32.frt $38 constant PORTB \ Port B Data Register $37 constant DDRB \ Port B Data Direction Register $45 constant TCCR2 \ Timer/Counter2 Control Register $59 constant TIMSK \ Timer/Counter Interrupt Mask Register $42 constant ASSR \ Asynchronous Status Register $45 constant TCCR2 \ Timer/Counter2 Control Register $58 constant TIFR \ Timer/Counter Interrupt Flag register $0A constant TIMER2_OVFAddr \ Timer/Counter2 Overflow variable ticks \ overflow2 interupt service routine: increment ticks : tick_isr_slow 1 ticks +! ; \ enable ticks \ crystal: 32768 /sec \ clock src: 32768/1024 /sec = 32 /sec \ overflow: 32/256 /sec = 1/8 /sec: T=8 sec : +ticks-slow $7 TCCR2 c! \ 111 = clock_ts2/1024 $8 ASSR c! \ source: 32 kiHz crystal ['] tick_isr_slow TIMER2_OVFAddr int! \ register interupt TIMSK c@ $40 or TIMSK c! \ enable timer2 interupt ; \ disable ticks : -ticks TIMSK c@ [ $40 invert $ff and ] literal and TIMSK c! \ clr Timer 2 $00 ASSR c! $00 TCCR2 c! $C0 TIFR c! \ clear interrupt flags, jibc ; 4 constant idle.ticks \ 4 * 8 = 32 seconds wait : init idle.ticks 1+ ticks ! \ run job once on startup +ticks-slow $ff DDRB c! \ make PORTB output $ff PORTB c! ; \ job does one round of work, whatever it is : ms 0 ?do 1ms loop ; : job $00 PORTB c! &1000 ms $ff PORTB c! ; : run init begin ticks @ idle.ticks > if job 1 ticks ! \ reset ticks counter then $03 sleep \ goto sleep here again ; : run-turnkey applturnkey run ; \ ' run-turnkey is turnkey \ fin \ ----------------------------------------------------------------- \ ----------------------------------------------------------------- |