Code:
; ==========================================
; Servotester für den Modellbau mit ATtiny13
; ==========================================
;
; Version 1.00 (23.05.2008)
;
; Fuse-Bits: BODLEVEL1=0 \ BrownOut-Spannung
; BODLEVEL0=0 / =4,3V
; CKSEL1=1 \ Interner Oszillator
; CKSEL0=0 / =9,6MHz
; CKDIV8=1 - Vorteiler /8 aus
; SUT1=1 \ Maximale
; SUT0=0 / Startverzögerung
;
; Ports: PB0 - Eingang (Pull-up) nicht genutzt
; PB1 - Eingang (Pull-up) nicht genutzt
; PB2 - Eingang (Pull-up) nicht genutzt
; PB3 - Eingang (analog) Potentiometer
; PB4 - Ausgang (H-aktiv) Impuls-Ausgang zum Servo
; PB5 - Eingang (Pull-up) Reset
;
; Timer: Timer0, wird mit Vorteiler 64 betrieben, Taktfrequenz=
; 150kHz, Interrupt bei Overflow und Zählung eines H-Byte
;
.nolist
.include "tn13def.inc"
.list
;
; Register-Definitionen
;
.def timerh= r2 ;High-Byte für Timer0, wird bei jedem
;Timer0 Overflow Interrupt um 1 erhöht
.def backup= r3 ;SREG-Zwischenspeicher für Interrupts
.def servol= r4 ;berechneter Servo-Zählerstand Low
.def servoh= r5 ;berechneter Servo-Zählerstand High
.def flags= r25 ;Bit0: Impuls-Ende wurde bearbeitet
;
.cseg
.org 0
;
reset: rjmp start ;Programm-Beginn
int0ad: reti ;External Int 0 (nicht genutzt)
pci0ad: reti ;Pin Change Interrupt (nicht genutzt)
ovf0ad: rjmp timer0 ;Timer0 Overflow Interrupt - 585,9Hz
;bzw. alle 1,707ms
erdyad: reti ;EEPROM Ready (nicht genutzt)
aciadd: reti ;Analog Comparator (nicht genutzt)
oc0aad: reti ;Timer0 Compare Match A (nicht genutzt)
oc0bad: reti ;Timer0 Compare Match B (nicht genutzt)
wdtadd: reti ;Watchdog Time-out (nicht genutzt)
adccad: reti ;ADC Conversion Complete (nicht gen.)
;
; Initialisierung ---------------------
;
start: ldi r16,0b010000
out ddrb,r16 ;PB4 auf Ausgang setzen
ldi r16,0b100111 ;PB4 auf Low und Pull-up an den
out portb,r16 ;Eingängen PB0-PB2 aktivieren
;
; ldi r16,neuer-wert ;hier lässt sich der Oszillator
; out osccal,r16 ;anpassen, falls das Ausgangs-
; ;signal stark von 20ms abweicht
;
clr r16
out tcnt0,r16 ;Timer0 Zähler löschen
out tccr0a,r16 ;Timer0 im Normal-Modus
ldi r16,0b11<<cs00
out tccr0b,r16 ;Timer0, Vorteiler=64 setzen
ldi r16,1<<toie0 ;Overflow Interrupt aktivieren
out timsk0,r16 ;Interrupt einschalten
;
ldi r16,(1<<adlar)+(0b11<<mux0);Vcc als Referenz und PB3
out admux,r16 ;als Eingang, Wert linksbündig
ldi r16,(1<<aden)+(1<<adsc)+(0b111<<adps0);ADC ein, Start,
out adcsra,r16 ;Vorteiler=128
ldi r16,1<<adc3d ;Digital Input Disable PB3
out didr0,r16 ;setzen
;
clr timerh ;Timer H-Byte löschen
sei ;Interrupt aktivieren
wdr ;Watchdog-Timer zurücksetzen
ldi r16,1<<wde ;Watchdog ein, 2k (16ms)
out wdtcr,r16 ;Watchdog aktivieren
;
; Hauptprogramm -----------------------
;
main: wdr ;Watchdog-Timer zurücksetzen
;
; Impuls-Ende ermitteln und bearbeiten
;
bst flags,0 ;Impuls-Ende-Flag gesetzt?
brts main10 ;ja -> Bearbeitung überspringen
in r16,tcnt0 ;sonst Timer0 Zählerstand holen
mov r17,timerh ;Timer H-Byte holen
sub r16,servol
sbc r17,servoh ;Zählerstand erreicht?
brmi main10 ;nein -> überspringen
;
sbr flags,0b00000001 ;Ende-Flag setzen
cbi portb,4 ;Ausgang PB4 auf Low setzen
;
; Zyklus-Ende / Impuls-Start ermitteln und bearbeiten
;
main10: in r16,tcnt0 ;Timer0 Zählerstand holen
mov r17,timerh ;Timer H-Byte holen
ldi r18,low(3000)
ldi r19,high(3000) ;Zählerwert für 20ms laden
sub r16,r18
sbc r17,r19 ;Zählerstand erreicht?
brmi main ;nein -> Hauptschleife
;
; Timer zurücksetzen, ADC lesen
;
clr r16 ;sonst
out tcnt0,r16 ;Timer0 auf 0 setzen
clr timerh ;H-Byte auf 0 setzen
sbi portb,4 ;Ausgang PB4 auf High setzen
clr flags ;Flags löschen
;
in r16,adch ;ADC-Wert lesen (0-255)
ldi r17,181 ;Multiplikator für Poti-Bereich
;1,2ms laden (Zählerstand 181)
;
; Multiplikation ADC-Wert mit 181 zur Ermittlung des Timer-Zählerstan-
; des, 8Bit * 8Bit Multiplikation nach Atmel Application Note AVR200
;
clr r18 ;Ergebnis H-Byte löschen
ldi r19,8 ;Schleifenzähler setzen
lsr r17 ;Multiplikator rotieren
main20: brcc main30 ;LSB=0? ja -> weiter, sonst
add r18,r16 ;Multiplikand zum H-Byte add.
main30: ror r18 ;Ergebnis H-Byte rotieren
ror r17 ;Ergebnis L-Byte rotieren
dec r19 ;alle Schleifen durchlaufen
brne main20 ;nein -> Schleife
;
; Zählerstand für Servo-Position ermitteln, ADC neu starten
;
ldi r16,low(135)
ldi r17,high(135) ;Zählerwert für 0,9ms laden
clr r19 ;H-Byte des Multiplikations-
add r16,r18 ;Ergebnisses addieren
adc r17,r19 ;Übertrag addieren
mov servol,r16 ;berechneten Zählerwert
mov servoh,r17 ;speichern
sbi adcsra,adsc ;ADC neu starten
rjmp main
;
; Timer0 Overflow Interrupt -----------
;
timer0: in backup,sreg ;SREG sichern
inc timerh ;Timer0 H-Byte erhöhen
out sreg,backup ;SREG wiederherstellen
reti
;
danke schon mal
Lesezeichen