;Dick Cappels' project pages projects@cappels.org - you should be able to copy and paste this text into an assembler file.
;©2002 Richard Cappels All Rights Reserved. No liability for resuls of use is assumed.See disclaimer on
;web site.email projects@cappels.org
;Use of information presented on this page is for personal, nonprofit educational
;and noncommercial use only. This material (including object files) is copyrighted
;by Richard Cappels and may not be republished or used directly for commercial
;purposes without explicit permission For commercial license, click HERE.
;
;HOME
;
;This is an AVR1200 that is intended to be used in a autozero circuit in a battery
;operated meter. It includes a PWM routine, an indicator to show whether it has zeroed the circuit
;or not and an indicator to show when the noninverting comparitor input is below the inverting
; comparitor input.
;It also includes a timer to shut of external circuits and indicators once the timeout perdiod
;has elapsed (about 20 minutes with a 2.8 volt power supply or 5 minutes with a 5 volt power supply).
;Voltage on the PWM output on pin 14 (PB2) starts from about a 1% duty cycle.
;The pulse duty cycle will increase until either pin 13 (the inverting comparitor input)
;exceeds the voltage on pin 12 (the noninverting comparitor input) or the duty cycle reaches
;its maximum of about 80%. The pulse changes in about 75 eual steps.
;The notCAL pin, pin 15, (PB3) will be low during this time. If the voltage on the comparitor's
;noninverting pin, pin 12 fails to exceed the voltage on teh comparitor's inverting input, pin 13,
;the notCAL pin, pin 15, will remain low (going high indicates that the zeroing process has completed.
;Momentarily grounding pin 2 (PD0) or pin 1 (reset) will restart the zeroing process, as will monetarily grounding
;the interrupt pin, pin 1. When rezeroing process is started by grounding pin 2, the timer is not reset.
;When the rezeroing process is started by grounding pin 1, the timer is restarted since the entire chip
;will be reset.
;There is a short delay after power is applied and the power on pins assert power being on
;(more about this later) before calibration starts. This gives time for the external circuits to settle.
;Power to external circuits and indicators is switched (or supplied) by pin 11, which goes high while
;power to the external circuits is supposed to be on, and pin 9, which goes low while power to the
;external circuit is supposed to be on. These pins are put in the "on" state when power is applied
;to the chip or the chip first comes out of reset, and the pins are switched to the "off" state
;when the timer times out.
;******************************************************
.include "1200def.inc"
;******************************************************
.def statstor = r15
.def pwmcounter = r16 ;keep track of how many ticks in PWM pules
.def pwmvalue = r17 ;requested pwm width
.def temp =r18 ;scratch
.def intemp = r19 ;number of counts in timer cycle (don't know how to make a constant)
.def loopdelay = r20 ;makes response really slow to avoid oscillations. In breadboard pwm lpf is .016 Hz single pole
.def timset = r21 ;value to reload counter with after arithmetic
.def loopdelay2 = r22 ;inner delay register
.def loopdelay3 = r23
.def flagreg = r24 ;Flags
.def sleepdelay = r25
.def sleepdelay1 = r26
.def sleepdelay2 = r27
.ORG $0000
rjmp start
.ORG $0002
rjmp timerservice
rjmp start
start:
ldi pwmvalue,$01
ldi flagreg, $00
ldi loopdelay, $01
ldi loopdelay2,$01
ldi temp,$60 ; set temp to all zeros
out DDRD, temp ; set port D to inputs
ldi temp,$43 ; set Port D bit 0 data high as pullup on pin
; and set PORT D bit 6 high to turn on circuit
out PORTD,temp
ldi temp,$1C
out DDRB,temp ;Set PORTB direction out
ldi temp,$02 ;Enable timer interrupt
ldi temp, $00
out PORTB,temp
ldi temp, $00
out ACSR, temp ;set up comparitor
ldi intemp, $FF ; counter reload value 255 cycles
ldi temp, $01 ; use temp to initaize prescaler to divide by 1
out TCCR0, temp
ldi temp,$00 ; use temp to initialize counter
out TCNT0,temp
ldi temp, $02 ; use temp to initialize TIMSK
out TIMSK,temp
sbi PORTB,3
ldi loopdelay,$00
ldi loopdelay2,$00
ldi loopdelay3,$01 ;****START UP DELAY
turnondelay:
dec loopdelay
cpi loopdelay,$00
brne turnondelay
dec loopdelay2
cpi loopdelay2,$00
brne turnondelay
dec loopdelay3
cpi loopdelay3,$00
brne turnondelay
cbi PORTB,3
ldi loopdelay, $01
ldi loopdelay2,$01
ldi temp, $00 ; clear temp
sei ; enable interrupts
;initiaization is finished
; CHECK - IF PIN 3 IS GROUNDED, SKIP TO LOOP, THAT IS, DON'T ALLOW SLEEP
sbis PIND,$01
rjmp loop ;skipp sleep is pin is grounded
; WAIT UNTIL TIME FOR SLEEP
ldi sleepdelay,$00
ldi sleepdelay1,$00
ldi sleepdelay2,$F0 ; $F0 gets about 20 min at 2.8V and 5 min at 5V
;****START UP DELAY
sleepdelayroutine:
; SAMPLE COMPARITOR AND OUTPUT TO LED (PB4) WHILE WAITING TO SLEEP
; Set state of light on PB4 according to comparitor inputs
sbic acsr,aco ; if + input is higher than - input, ligh on
cbi PORTB,4
sbis acsr,aco ;if + input is not higher than - input, ligh off
sbi PORTB,4
dec sleepdelay
cpi sleepdelay,$00
brne sleepdelayroutine
dec sleepdelay1
cpi sleepdelay1,$00
brne sleepdelayroutine
dec sleepdelay2
cpi sleepdelay2,$00
brne sleepdelayroutine
; GO TO SLEEP
cli ; dispable interupts
ldi temp, $00
out TIMSK,temp ; clear TIMSK bit 1 - TOIE0 enable (disable timer interrupts)
ldi temp, $18
out PORTB, temp ; turn off LEDs, set pulse output to zero
ldi temp, $20
out PORTD, temp ; turn off port D bit 0 pullup and bit 6 power to external circuit
ldi temp, $30
out MCUCR,temp ; set MCUCR bit 4 to set power down mode for sleep and
; set MCUCR bit 5 to enable sleep
sleep ; enter sleep. Reset to wake up.
loop: ; It only gets here if timer is bypassed by grounding pin 3
; SAMPLE COMPARITOR AND OUTPUT TO LED (PB4)
; Set state of light on PB4 according to comparitor inputs
sbic acsr,aco ; if + input is higher than - input, ligh on
cbi PORTB,4
sbis acsr,aco ;if + input is not higher than - input, ligh off
sbi PORTB,4
rjmp loop ; sit and spin
timerservice:
in statstor,SREG
mov pwmcounter, pwmvalue
andi pwmvalue, $FF
breq zeroutput ; if the value is zero, don't turn on output
sbi PORTB,2 ;set output bit high
zeroutput:
decpwm:
dec pwmcounter ; wait time proportional to count
brne decpwm
cbi PORTB,2 ; now PWM is finished
dec loopdelay ; decrement loop dealy counter
brne down ; if not zero yet, skip to end of interrupt
dec loopdelay2
brne down
ldi loopdelay2,$02 ;**** STEPPING delay
andi flagreg,$FF
breq donturnlampoff
sbi PORTB,3 ;turn off (N)cal inidicator
donturnlampoff:
andi flagreg,$FF
brne down ; skip servo if all flag bits are high
; over/underflow prevention
ldi temp,$4B
cpse pwmvalue,temp ;if pwmvalue = 4B then set back to 4A
rjmp servo
ldi pwmvalue, $4A
servo:
sbic acsr,aco ; if comparator is tripped, inc PWM
inc pwmvalue
sbis acsr,aco ;if comparator isn't tripped, STOP searching
ldi flagreg,$FF
down:
in temp,PIND ;Reset flag and value if button down
sbrc temp,$00
rjmp donecheckingbutton
ldi flagreg,$00
ldi pwmvalue,$01
cbi PORTB,3 ;turn off (N)cal inidicator
donecheckingbutton:
return:
out SREG,statstor ;Restore SREG
reti
;http://projects.cappels.org/
;HOME