![]() |
Anwendungen von AVR-Einchip-Prozessoren AT90S, ATtiny, ATmega und ATxmega Schrittmotorsteuerung mit einem ATtiny24 |
;
; *************************************
; * Schrittmotorsteuerung ATtiny24 *
; * 16-Bit-Position, Voll/Halbschritt *
; * Version 1, Maerz 2018, V1 *
; * (C)2018 by avr-asm-tutorial.net *
; *************************************
;
.nolist
.include "tn24adef.inc" ; Define device ATtiny24A
.list
;
; **********************************
; M O D U S - S C H A L T E R
; **********************************
;
.equ Halfstep = 0 ; 1=Halbschritt, 0=Vollschritt
;
; **********************************
; D E B U G - S C H A L T E R
; **********************************
;
; Debug ausschalten: alle Schalter auf 0
;
; Teste ADC-Wert-Umrechnung
.equ TestAdc = 0 ; Teste Berechnung Kanal 2
.equ TestChannel=2 ; Channel zu Simulieren
.equ TestValue = 255*256
;
; Teste Ausgabe Motor
.equ TestMotor = 0 ; Teste Motorstellung
.equ TestCurr = 32768 ; aktuelle Stellung
.equ TestNext = 32767 ; naechste Stellung
;
; H A R D W A R E
; **********************************
;
; Device: ATtiny24, Package: 14-pin-PDIP_SOIC
; _________
; 1 / |14
; +Ub o--|VCC GND|--o -Ub
; 2| |13
; Duo AnRt o--|PB0 ADC0|--o Poti ZU
; 3| |12
; LED AnGe o--|PB1 ADC1|--o Poti AUF
; 4| |11
; RESET o--|RES ADC2|--o Poti Speed
; 5| |10
; Schalter o--|PB2 PA3|--o LED Ka Gn
; 6| |9
; ULN IN7 o--|PA7 PA4|--o ULN IN4
; 7| |8
; ULN IN6 o--|PA6 PA5|--o ULN IN5
; |__________|
;
; **********************************
; P O R T S A N D P I N S
; **********************************
; Duo-LED-Ansteuerung
.equ pDuoO = PORTB ; Duo-LED-Ausgabeport
.equ pDuoD = DDRB ; Duo-LED-Richtungsport
.equ bDuoAR = PORTB0 ; Rote Anode Portbit
.equ bDuoAY = PORTB1 ; Gelbe Anode Portbit
; Schaltersteuerung
.equ pSwO = PORTB ; Schalter-Ausgabeport
.equ pSwD = DDRB ; Schalter-Richtungsport
.equ pSwI = PINB ; Schalter-Eingabeport
.equ bSwO = PORTB2 ; Schalter-Ausgabepin
.equ bSwD = DDB2 ; Schalter-Richtungspin
.equ bSwI = PINB2 ; Schalter-Eingabepin
; Bereit-LED
.equ pOkO = PORTA ; Bereit-LED-Ausgabeport
.equ pOkD = DDRA ; Bereit-LED-Richtungsport
.equ pOkI = PINA ; Eingabeport
.equ bOkO = PORTA3 ; Bereit-LED-Ausgabepin
.equ bOkD = DDA3 ; Bereit-LED-Richtungspin
.equ bOkI = PINA3 ; Lese-Pin
; Schrittmotor
.equ pStpO = PORTA ; Schrittmotor-Ausgabeport
.equ pStpD = DDRA ; Schrittmotor-Richtungsport
.equ mStpD = 0xF0 ; Maske Schrittmotor-Richtung
;
; **********************************
; A D J U S T A B L E C O N S T
; **********************************
;
; Taktgenerator Default (CLKDIV8 gesetzt)
.equ clock=1000000 ; Define clock frequency
;
; Grad maximaler Drehwinkel =
; maximale Getriebewinkel-Aussteuerung):
.equ cAngleMax = 180 ; Grad maximaler Drehwinkel
;
; Startgeschwindigkeit, Default
; bis zur ersten Potentiometermessung
.equ cSecOpenClose = 20 ; 20 Sekunden
;
; Zeit nach letzter Bewegung bis Motor stromlos
; Minimum: 1 (1 ms), Maximum: 6710 (6,71 s)
.equ cMotOffms = 1000 ; Millisekunden bis Motor aus
;
; **********************************
; F I X & D E R I V. C O N S T
; **********************************
;
; Motor mit Getriebe 1:64
; Schritte pro Umdrehung Motor 64
; Schritte pro Getriebeumdrehung:
.equ cStepsRound = 64 * 64
; Mittenstellung:
.equ cMiddle = 32768
; Schritte pro Maximalwinkeldrehung:
.equ cStepsAngle = (cStepsRound*cAngleMax+180)/ 360
; Schritte pro halber Maximalwinkeldrehung
; (von Mitte aus nach oben bzw. unten):
.equ cStepsUpDown = (cStepsAngle+1) / 2
;
; Berechnung der Startgeschwindigkeit
.equ cTC0Presc = 64 ; Vorteiler TC0
; TC0Ticks in Mikrosekunden:
.equ cTC0Tick = (1000000*cTC0Presc)/clock
; Dauer in Mikrosekunden fuer volles Oeffnen/
; Schliessen ueber den Maximalwinkel
.equ cUsSwing = (1000000*cSecOpenClose)/cStepsAngle
; CTC-Wert fuer 8-Bit-TC0
.equ cCTCDef = (cUsSwing+cTC0Tick/2)/cTC0Tick
;
; CTC-Wert fuer 16-Bit-TC1 Motor aus
.equ cMotOff = (1000*cMotOffms+512)/1024-1
;
; **********************************
; T I M I N G
; **********************************
;
; TC0 ist Schrittmotor-Ansteuerung
; laeuft im CTC-Modus mit Compare A
; clock = 1.000.000 Hz
; Vorteiler = 64
; Timer-Tick = 64 us
; Vollschrittverfahren:
; Schritte 180 Grad = 1.024
; Langsame Bewegung = 16,78 s
; Zeit pro Schritt = 16.384 us
; CTC-Ticks = 256
; Compare-A-Wert = 255
; Schnelle Bewegung = 2,03 s
; Zeit pro Schritt = 1.984 us
; CTC-Ticks = 31
; Compare-A-Wert = 30
; Berechnung aus MSB ADC-Summe ADC2:
; Compare A = (ADC-MSB * 225)/256+30
; Halbschrittverfahren:
; Schritte 180 Grad = 2.048
; Langsame Bewegung = 17,7 s
; Zeit pro Schritt = 16.384 us
; CTC-Ticks = 135
; Compare-A-Wert = 134
; Schnelle Bewegung = 1,97 s
; Zeit pro Schritt = 960 us
; CTC-Ticks = 15
; Compare-A-Wert = 14
; Berechnung aus MSB ADC-Summe ADC2:
; Compare A = (ADC-MSB * 241)/256+14
;
; TC1 ist Motor-Aus-Schalter
; laeuft im Normalmodus mit Compare A
; Clock = 1.000.000 Hz
; Vorteiler = 1.024
; Timer-Tick = 1.024 us
; Maximum bis Ueberl. = 65.536
; Entspricht Zeit = 6,7 s
; Eingestellt auf = 1 s
;
; AD-Wandler misst Potistellungen 1, 2 und 3
; Clock = 1.000.000 Hz
; Vorteiler = 128
; ADC-Tick = 128 us
; Wandlertakte/Messung= 14
; Zeit pro Messung = 1.792 us
; 64 Messungen = 114.688 us
; Drei Kanaele = 344.064 us
; Messungen pro Sek. = 2,9
;
; **********************************
; R E G I S T E R S
; **********************************
;
; R0, R1, R2, R3 benutzt fuer Multiplikationen etc.
; free: R4
; ADC-Werte-Summierung
.def rAdcL = R5 ; Summe ADC-Wert, LSB
.def rAdcH = R6 ; dto., MSB
; Registerwerte fuer Schrittmotorstellung
.equ cStepSetS = 7 ; fuer Lesen/Schreiben EEPROM
.def rMark1 = R7
.def rCloseL = R8
.def rCloseH = R9
.def rOpenL = R10
.def rOpenH = R11
.def rCurrValL = R12
.def rCurrValH = R13
.def rMark2 = R14
.equ cStepSetE = 15 ; Ende des Datensets
.def rSreg = R15 ; Save/Restore status port
.def rmp = R16 ; Define multipurpose register
.def rimp = R17 ; Multipurpose Interrupts
.def rFlag = R18 ; Flaggen
.equ bWrite = 0 ; Datenset in EEPROM schreiben
.equ bAdc = 1 ; 64 Messwerte sind aufsummiert
.def rAdc = R19 ; ADC-Summierungszaehler
.def rSetValL = R20 ; Sollwert, LSB
.def rSetValH = R21 ; Sollwert, MSB
; free: R22 to R29
; used: R27:R26 = X Zeiger ausserhalb Interrupts
; used: R29:R28 = Y Zeiger fuer EEPROM-Schreiben
; used: R31:R30 = Z Zeiger Vielzweck, fuer LPM
;
; **********************************
; S R A M
; **********************************
;
.dseg
.org SRAM_START
; (Nicht benutzt, nur fuer den Stapel)
;
; **********************************
; C O D E
; **********************************
;
.cseg
.org 000000
;
; **********************************
; R E S E T & I N T - V E C T O R S
; **********************************
rjmp Main ; Reset vector
rjmp Int0Isr ; EXT_INT0
reti ; PCI0
reti ; PCI1
reti ; WATCHDOG
reti ; ICP1
rjmp OC1AIsr ; OC1A
reti ; OC1B
reti ; OVF1
rjmp OC0AIsr ; OC0A
reti ; OC0B
reti ; OVF0
reti ; ACI
rjmp AdcIsr ; ADCC
rjmp EepIsr ; ERDY
reti ; USI_STR
reti ; USI_OVF
;
; **********************************
; I N T - S E R V I C E R O U T .
; **********************************
;
; INT0 Interrupt Service Routine
; Schalter-Aktionen loesen INT0 aus
; bei steigenden und fallenden Flanken
Int0Isr:
set ; Update-Flagge fuer Sollwert
reti
;
; OC0A Interrupt Service Routine
; bedient Schrittmotor
OC0AIsr: in rSreg,SREG ; rette SREG
cp rCurrValL,rSetValL ; LSB rIst = rSoll?
brne OC0AIsr1 ; LSB ungleich
cp rCurrValH,rSetValH
breq OC0AIsr8 ; gleich, tue nichts
cp rCurrValL,rSetValL ; LSB-Vergleichen
OC0AIsr1:
; rIst ungleich rSoll, Motorbewegung
cpc rCurrValH,rSetValH ; MSB testen
brcs OC0AIsr4 ; rIst kleiner rSoll
tst rCurrValL ; Pruefe auf Null
brne OC0AIsr2 ; LSB nicht Null
dec rCurrValH ; MSB eins abwaerts
OC0AIsr2:
dec rCurrValL ; Ein Schritt zurueck
sbi pDuoO,bDuoAY ; gelbe LED an
cp rCurrValL,rSetValL
breq OC0AIsr3 ; nicht gelb blinken
sbrc rCurrValL,3
cbi pDuoO,bDuoAY ; gelbe LED blinkt
OC0AIsr3:
cbi pDuoO,bDuoAR ; Kathode gelbe LED Low
rjmp OC0AIsr7 ; Schrittmotor verstellen
; rIst kleiner rSoll
OC0AIsr4:
inc rCurrValL ; Ein Schritt vorwaerts
brne OC0AIsr5 ; LSB nicht Null
inc rCurrValH ; MSB erhoehen
OC0AIsr5:
sbi pDuoO,bDuoAR ; rote LED an
cp rCurrValL,rSetValL
breq OC0AIsr6 ; nicht rot blinken
sbrc rCurrValL,3
cbi pDuoO,bDuoAR ; rote LED blinken
OC0AIsr6:
cbi pDuoO,bDuoAY ; Kathode rote LED Low
OC0AIsr7:
push ZH ; rette Z
push ZL
mov rimp,rCurrValL ; Ist-Wert kopieren
.if Halfstep == 1
ldi ZH,High(2*StepTab8) ; Z auf 8-Step-Tabelle
ldi ZL,Low(2*StepTab8)
andi rimp,0x07 ; die untersten drei Bit
.else
ldi ZH,High(2*StepTab4) ; Z auf 4-Step-Tabelle
ldi ZL,Low(2*StepTab4)
andi rimp,0x03 ; die untersten zwei Bit
.endif
add ZL,rimp ; zur Tabellenadresse addieren
ldi rimp,0
adc ZH,rimp
lpm rimp,Z ; Tabellenbyte lesen
in ZL,pStpO ; Port lesen
andi ZL,0x0F ; unterste drei Bit erhalten
or ZL,rimp ; Motor- und Bereit-Led-Bits setzen
out pStpO,ZL ; an Stepmotorausgang, Bereit-LED aus
pop ZL ; stelle Z wieder her
pop ZH
clr rimp ; Motor-Aus-Zaehler neu starten
out TCNT1H,rimp
out TCNT1L,rimp
OC0AIsr8:
out SREG,rSreg ; stelle SREG wieder her
reti
;
.if Halfstep == 1
; Schrittfolge-Tabelle Halbschrittmodus
StepTab8:
.db 0x18,0x38,0x28,0x68,0x48,0xC8,0x88,0x98
.else
; Schrittfolge-Tabelle Vollschrittmodus
StepTab4:
.db 0x18,0x28,0x48,0x88
.endif
;
; OC1A-ISR schaltet Motormagnete aus
;
OC1AIsr:
in rSreg,SREG ; SREG sichern
sbic pOkO,bOkO ; gruene LED schon an? Wenn nicht...
sbr rFlag,1<<bWrite ; Schreibe Position ins EEP
in rimp,pStpO ; Lese Motor-Port Output
andi rimp,0x07 ; Untere drei Bits erhalten
out pStpO,rimp ; Motor aus, gruene LED an
cbi pDuoO,bDuoAR ; rote/gelbe LED aus
cbi pDuoO,bDuoAY
out SREG,rSreg ; SREG wieder herstellen
reti
;
; ADC complete Interrupt
AdcIsr:
in rSreg,SREG ; rette Status
in rimp,ADCL ; Lese LSB Ergebnis
add rAdcL,rimp ; addiere zur Summe
in rimp,ADCH ; lese MSB Ergebnis
adc rAdcH,rimp
dec rAdc ; Zaehler abwaerts
brne AdcIsr1 ; noch nicht 64 Werte
sbr rFlag,1<<bAdc ; setze Flagge
rjmp AdcIsr2 ; nicht neu starten
AdcIsr1:
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp
AdcIsr2:
out SREG,rSreg ; stelle Status wieder her
reti
;
; EEPROM Interrupt
EepIsr:
in rSreg,SREG ; SREG retten
in rimp,EEARL ; Lese LSB Adresse
inc rimp ; naechste Adresse
out EEARL,rimp
ld rimp,Y+ ; Lese naechstes Byte
out EEDR,rimp
sbi EECR, EEMPE ; EEPROM-Schreiben starten
sbi EECR, EEPE
cpi YL,cStepSetE ; Letztes Byte?
brcs EepIsr1
cbi EECR,EERIE ; Keine Interrupts mehr
cbr rFlag,1<<bWrite ; Schreibflagge loeschen
EepIsr1:
out SREG,rSreg ; SREG wieder herstellen
reti
;
; **********************************
; M A I N P R O G R A M I N I T
; **********************************
;
Main:
ldi rmp,Low(RAMEND)
out SPL,rmp ; Init LSB stack pointer
;
; Debugschalter auswerten
.if TestAdc == 1
; Teste Berechnung ADC
ldi rmp,High(TestValue)
mov rAdcH,rmp
ldi rmp,Low(TestValue)
mov rAdcL,rmp
ldi rmp,TestChannel
out ADMUX,rmp
rcall AdcFlag
TestAdcLoop:
rjmp TestAdcLoop
.endif
.if TestMotor == 1 ; Teste Motorstellung
ldi rmp,High(TestCurr) ; aktuelle Stellung
mov rCurrValH,rmp
ldi rmp,Low(TestCurr)
mov rCurrValL,rmp
ldi rmp,High(TestNext)
mov rSetValH,rmp
ldi rmp,Low(TestNext)
mov rSetValL,rmp
TestMotorLoop:
rcall OC0AIsr
rjmp TestMotorLoop
.endif
;
; Neujustierung?
cbi pOkD,bOkD
sbi pOkO,bOkO ; Pull-up einschalten
sbic pOkI,bOkI ; Pin auf Null?
rjmp LeseEeprom ; Nein
ldi rmp,High(32768)
mov rSetValH,rmp
mov rCurrValH,rmp
mov rOpenH,rmp
mov rCloseH,rmp
ldi rmp,Low(32768)
mov rSetValL,rmp
mov rCurrValL,rmp
mov rOpenL,rmp
mov rCloseL,rmp
sbr rFlag,1<<bWrite
WaitRestart:
ldi ZH,High(16667) ; 100 ms warten
ldi ZL,Low(16667)
WaitInactive:
sbis pOkI,bOkI ; Ueberspringe wenn Pin high
rjmp WaitRestart ; Pin ist auf Null
sbiw ZL,1 ; Abwaerts zaehlen
brne WaitInactive ; Noch nicht 100 ms
rjmp NoEpromRead ; Fertig gewartet
; Lese EEPROM-Inhalt
LeseEeprom:
rcall ReadEep ; Lese den Datenset im EEPROM
NoEpromRead:
; Init Duo-LED
sbi pDuoD,bDuoAR ; Richtung rote Anode Ausgang
sbi pDuoD,bDuoAY ; Richtung gelbe Anode Ausgang
cbi pDuoO,bDuoAR ; rote Anode auf Low
cbi pDuoO,bDuoAY ; gelbe Anode auf Low
; Init Bereit-LED
sbi pOkD,bOkD ; Bereit-LED Richtung Ausgang
sbi pOkO,bOkO ; Bereit-LED aus
; Init Schalter
cbi pSwD,bSwD ; Schalter Richtung auf Input
sbi pSwO,bSwO ; Schalter Pull-Up An
; Init AD-Wandler
clr rmp ; Mit Kanal 0 beginnen, URef=UB
out ADMUX,rmp
ldi rAdc,64 ; 64 Messungen
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; Starte erste Wandlung mit Interrupts
; Init Schrittmotor
; Schrittmotor
; .equ pStpO = PORTA ; Schrittmotor-Ausgabeport
; .equ pStpD = DDRA ; Schrittmotor-Richtungsport
; .equ mStpD = 0xF0 ; Maske Schrittmotor-Richtung
in rmp,pStpO ; Output-Port lesen
andi rmp,0x0F ; Unterste Bits erhalten, oberste = Null
out pStpO,rmp ; in Output-Port schreiben
in rmp,pStpD ; Richtungsregister lesen
ori rmp,mStpD ; mit Richtungsmaske odern
out pStpD,rmp ; Richtung Ausgang
; Init TC1 als Motormagnet-Abschaltung bei inaktiv
ldi rmp,High(cMotOff) ; Zeit bis Abschaltung
out OCR1AH,rmp
ldi rmp,Low(cMotOff)
out OCR1AL,rmp
clr rmp ; Normal Mode
out TCCR1A,rmp
ldi rmp,(1<<CS12)|(1<<CS10) ; Prescaler=1024
out TCCR1B,rmp
ldi rmp,1<<OCIE1A ; Compare Match A Interrupt
out TIMSK1,rmp
; Init TC0 als Schrittmotor-Steuerung
ldi rmp,cCtcDef ; niedrige Anfangsgeschwindigkeit
out OCR0A,rmp ; CTC-Wert setzen
ldi rmp,1<<WGM01 ; No OC output, WGM01 fuer CTC
out TCCR0A,rmp
ldi rmp,(1<<CS01)|(1<<CS00) ; CTC, Presc=64
out TCCR0B,rmp
ldi rmp,1<<OCIE0A ; Compare Match A Interrupt
out TIMSK0,rmp
; Sleep, externe ints und int enable
ldi rmp,(1<<ISC00)|(1<<SE) ; Externer INT0, Schlafmodus
out MCUCR,rmp
ldi rmp,1<<INT0 ; Ext INT0 enable
out GIMSK,rmp
sei ; Enable interrupts
;
; **********************************
; P R O G R A M L O O P
; **********************************
;
Loop:
sleep
nop
sbrc rFlag,bAdc
rcall AdcFlag
sbrc rFlag,bWrite
rcall WriteEep
brtc Loop ; Kein Update Sollwert
clt
sbis pSwI,bSwI ; Ueberspringe bei Schalter offen
rjmp SetOpen
cli
mov rSetValL,rCloseL ; Sollwert = ZU
mov rSetValH,rCloseH
sei
rjmp Loop
SetOpen:
cli
mov rSetValL,rOpenL ; Sollwert Offen-Stellung
mov rSetValH,rOpenH
sei
rjmp loop
;
; ADC-Flagge gesetzt, 64 Messungen fertig
AdcFlag:
cbr rFlag,1<<bAdc ; Loesche Flagge
in rmp,ADMUX ; Lese Wandlerkanal
cpi rmp,1 ; Kanal ADC1?
breq AdcFlag1
brcs AdcFlag0
rjmp AdcFlag2
AdcFlag0:
; Kanal 0 auswerten
; ADC-Ergebnissumme MSB invertieren und mit vier malnehmen
; ADCH(MSB) ADCL(LSB)
; xxxx.xxxx.xx(xx.xxxx)
; MSB nach R0, die beiden oberen
; Bits vom LSB von rechts
; einschieben
; R1 R0
; 0000.00xx.xxxx.xxxx
mov R0,rAdcH ; MSB ADC-Ergebnis
com R0 ; Potentiometer-Umkehr
clr R1 ; Loeschen obere Bits
rol rAdcL
rol R0 ; in LSB einschieben
rol R1 ; in MSB schieben
.if HalfStep == 1
lsl R0 ; in LSB rotieren
rol R1 ; in MSB rotieren
.endif
; Ergebnis zu 32.768 addieren
ldi ZH,High(32768)
ldi ZL,Low(32768)
sub ZL,R0
sbc ZH,R1
mov rOpenH,ZH ; Wert in rOpen kopieren
mov rOpenL,ZL
ldi rmp,1 ; auf Kanal 1 weitermessen
out ADMUX,rmp
set ; T-Flagge update Sollwert
rjmp AdcFlag9
AdcFlag1:
; Kanal 1 auswerten
; ADC-Ergebnis mit vier malnehmen
; ADCH(MSB) ADCL(LSB)
; xxxx.xxxx.xx(xx.xxxx)
; MSB nach R0, die beiden oberen
; Bits vom LSB von rechts
; einschieben
; R1 R0
; 0000.00xx.xxxx.xxxx
mov R0,rAdcH ; MSB ADC-Ergebnis in LSB
com R0 ; Invertieren
clr R1 ; Loeschen obere Bits
rol rAdcL
rol R0 ; in LSB einschieben
rol R1 ; in MSB schieben
.if Halfstep == 1
lsl R0 ; in LSB einschieben
rol R1 ; in MSB schieben
.endif
; Wert von 32.768 abziehen
ldi ZH,High(32768)
ldi ZL,Low(32768)
add ZL,R0
adc ZH,R1
mov rCloseH,ZH ; Und in rClose ablegen
mov rCloseL,ZL
ldi rmp,2 ; mit Kanal 2 weitermachen
out ADMUX,rmp
set ; T-Flagge fuer Sollwert setzen
rjmp AdcFlag9
AdcFlag2:
; Kanal 2 auswerten
.if Halfstep == 1
ldi rmp,120 ; Multiplikator halb
ldi ZH,14 ; Minimum CTC-Wert
.else
ldi rmp,225 ; Multiplikator ganz
ldi ZH,30 ; Minimum CTC-Wert
.endif
clr ZL
mov R0,rAdcH
clr R1
AdcFlag21:
lsr rmp ; Multiplikator rechts in Carry
brcc AdcFlag22 ; Null, nicht addieren
add ZL,R0 ; Eins, Multiplikator addieren
adc ZH,R1
AdcFlag22:
; Multiplikator mal zwei
lsl R0
rol R1
tst rmp ; Alle Einsen multipliziert?
brne AdcFlag21 ; nein, weiter
out OCR0A,ZH ; in Compare A schreiben
ldi rmp,0 ; auf Kanal 0 weitermessen
out ADMUX,rmp
AdcFlag9:
clr rAdcH ; Loeschen der Summen
clr rAdcL
ldi rAdc,64 ; 64 Messungen neu starten
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; Messung starten
ret
;
; *************************************
; E E P R O M - S T E U E R U N G
; *************************************
;
; Schreibe aktuellen Datenset in das EEPROM
;
; Datenstruktur:
; .equ cStepSetS = 7 ; fuer Lesen/Schreiben EEPROM
; .def rMark1 = R7
; .def rCloseL = R8
; .def rCloseH = R9
; .def rOpenL = R10
; .def rOpenH = R11
; .def rCurrValL = R12
; .def rCurrValH = R13
; .def rMark2 = R14
; .equ cStepSetE = 15 ; Ende des Datensets
;
WriteEep:
sbic EECR, EEPE ; warte bis EEPROM bereit
rjmp WriteEep ; noch nicht bereit
cbr rFlag,1<<bWrite
ldi ZH,High(EepAdrs) ; Z auf EEPROM-Adresse
ldi ZL,Low(EepAdrs)
ldi YH,High(cStepSetS) ; Y auf Register
ldi YL,Low(cStepSetS)
out EEARH,ZH ; in EEPROM-Adressport
out EEARL,ZL
ld rmp,Y+ ; Lese erstes Byte
out EEDR,rmp ; in EEPROM Datenport
cli ; Interrupts disablen
sbi EECR, EEMPE ; EEPROM-Schreiben starten
sbi EECR, EEPE
sei ; Interrupts wieder enablen
sbi EECR,EERIE ; EEP-Interrupts einschalten
ret
;
; Lese EEPROM-Werte ein
; Datenstruktur:
; .equ cStepSetS = 7 ; fuer Lesen/Schreiben EEPROM
; .def rMark1 = R7
; .def rCloseL = R8
; .def rCloseH = R9
; .def rOpenL = R10
; .def rOpenH = R11
; .def rCurrValL = R12
; .def rCurrValH = R13
; .def rMark2 = R14
; .equ cStepSetE = 15 ; Ende des Datensets
ReadEep:
ldi ZH,High(EepAdrs) ; Z auf EEPROM-Werte
ldi ZL,Low(EepAdrs)
ldi XH,High(cStepSetS) ; X auf Step-Register
ldi XL,Low(cStepSetS)
ldi rmp,cStepSetE-cStepSetS ; Anzahl Bytes
mov R0,rmp
ReadEep1:
sbic EECR, EEPE ; warte bis EEPROM bereit
rjmp ReadEep1
ReadEep2:
out EEARH,ZH ; Setze Lese-Adresse EEPROM
out EEARL,ZL
sbi EECR, EERE ; Lese-Befehl EEPROM
in rmp, EEDR ; Lese Byte
st X+,rmp ; speichere in Register
adiw ZL,1 ; naechste Adresse
dec R0 ; alle Bytes?
brne ReadEep2 ; nein, weiter
mov rmp,rMark1 ; Pruefe Werte
eor rmp,rMark2 ; Exclusiv-Oder
cpi rmp,0xFF ; Korrekt?
breq ReadEep3 ; Ja, korrekte Kennungen
; Falsche Kennungen, Ignoriere EEPROM-Daten
ldi rmp,High(32768) ; Setze Default
mov rOpenH,rmp ; auf Mitte
mov rCloseH,rmp
mov rCurrValH,rmp
clr rOpenL
clr rCloseL
clr rCurrValL
ReadEep3:
ret
;
; EEPROM-Inhalte Default
;
; Datenstruktur:
; .equ cStepSetS = 7 ; fuer Lesen/Schreiben EEPROM
; .def rMark1 = R7
; .def rCloseL = R8
; .def rCloseH = R9
; .def rOpenL = R10
; .def rOpenH = R11
; .def rCurrValL = R12
; .def rCurrValH = R13
; .def rMark2 = R14
; .equ cStepSetE = 15 ; Ende des Datensets
.eseg
.org 0x0010 ; EEPROM-Segment ab 0x10
EepAdrs:
; Defaultwerte: Kennung (0xAA), ZU-Wert, Auf-Wert, IST-Wert,
; SOLL-Wert, Kennung (0x55)
.db 0xAA ; Kennung 1
.dw 32768 ; Close-Wert
.dw 32768 ; Open-Wert
.dw 32768 ; Aktuelle Position Mitte
.db 0x55 ; Kennung 2
;
; Ende Quellcode
;