1 | ;Steuerung eines Laser-Spiegel-Schrittmotors mittels AT-Mega8
|
2 | ;
|
3 | ;
|
4 |
|
5 |
|
6 | .include"m8def.inc" ;Hardwarekonstanten definieren
|
7 |
|
8 | ;----------------------------------------------------------------------------
|
9 | ;Anpassungen an die Hardware (Parameter und Konstanten):
|
10 |
|
11 | ;Tasten und Schalter (3 Stellungen) an PortB
|
12 | .equ tap=pinb ;Tastenport, Eingänge (PINx)
|
13 | .equ mset=7 ;Modeschalter Stellung SET (Einrichten)
|
14 | .equ mrun=6 ;Modeschalter Stellung RUN (Betrieb)
|
15 | .equ trst=5 ;Taster Reset (Löschen der gespeicherten Liste)
|
16 | .equ tup=4 ;Taster UP (Aufwärtsbewegung)
|
17 | .equ tdn=3 ;Taster DOWN (Abwärtsbewegung)
|
18 | .equ tent=2 ;Taster ENTER (Schrittübernahme)
|
19 | .equ tok=1 ;Taster OK (Rest der Liste wird gelöscht)
|
20 | .equ tla=0 ;Taster Laser an/aus
|
21 |
|
22 | ;Lichtschranke für Nullpunkt
|
23 | .equ nup=pinc ;Nullpunktsensor-Port PINx
|
24 | .equ nuse=1 ;Nullpunkt-Sensor (Lichtschranke)
|
25 |
|
26 | ;Laser-Stromversorgung
|
27 | .equ lap=portd ;Laser-Port (PORTx)
|
28 | .equ lapi=3 ;Laser-Pin (Bit x)
|
29 |
|
30 | ;Schrittmotor an PortD, Pins PD7, PD6, PD5, PD4
|
31 | .equ smp=portd ;Schrittmotor-Port (PORTx)
|
32 | .equ smm=0b11110000 ;Schrittmotor-Bitmaske
|
33 |
|
34 | ;Poti zur Zeiteingabe an PC0
|
35 | .equ adq=0 ;ADC-Quelle
|
36 |
|
37 | .equ timer0start=-156 ;Startwert Timer0 bei 1MHz, VT64 und 10ms (100Hz) ISR-Takt
|
38 | .equ schritte=96 ;Anzahl der Vollschritte des Schrittmotors
|
39 |
|
40 | ;----------------------------------------------------------------------------
|
41 | ;Register...
|
42 | .def null=r2 ;immer Null
|
43 | .def srsk=r3 ;Kopie SREG
|
44 | .def tsw=r4 ;Timer-Start (Reload)
|
45 | .def scan=r5 ;Scannwert Tastenport
|
46 | .def tz0=r6 ;Tasten-Prellzähler Bit0
|
47 | .def tz1=r7 ;Tasten-Prellzähler Bit1
|
48 | .def tas=r8 ;Tastenstatus (gültig)
|
49 |
|
50 | .def posi=r16 ;Position des Motors
|
51 | .def ztz=r17 ;Zeit-Zähler (CountDown)
|
52 | .def soll=r18 ;Zielposition des Spiegels
|
53 | .def tfl=r19 ;Flags für Tasten, die gedrückt wurden
|
54 | .def flags=r20 ;Steuerflags
|
55 | .equ las=0 ;Laser
|
56 |
|
57 | .def ztv=r22 ;Zeit-Vorteiler
|
58 | .def mode=r23 ;einige Flasgs zur Ablaufsteuerung
|
59 | .equ nus=0 ;Nullpunkt suchen
|
60 | .equ savz=1 ;Zeit speichern
|
61 |
|
62 | .def wl=r24 ;working-Register 1 (Low)
|
63 | .def wh=r25 ;working-Register 2 (High)
|
64 |
|
65 |
|
66 | .cseg ;Codesegment
|
67 | .org 0 ;Adresse 0
|
68 | rjmp reset ;Interrupt-Vektoren überspringen
|
69 | ;jetzt folgen die Interruptvektoren des Mega8 (Datenblatt ab S.44)
|
70 | reti ; rjmp EXT_INT0 ; IRQ0 Handler
|
71 | reti ; rjmp EXT_INT1 ; IRQ1 Handler
|
72 | reti ; rjmp TIM2_COMP ; Timer2 Compare Handler
|
73 | reti ; rjmp TIM2_OVF ; Timer2 Overflow Handler
|
74 | reti ; rjmp TIM1_CAPT ; Timer1 Capture Handler
|
75 | reti ; rjmp TIM1_COMPA ; Timer1 CompareA Handler
|
76 | reti ; rjmp TIM1_COMPB ; Timer1 CompareB Handler
|
77 | reti ; rjmp TIM1_OVF ; Timer1 Overflow Handler
|
78 | rjmp timer0 ; Timer0 Overflow Handler
|
79 | reti ; rjmp SPI_STC ; SPI Transfer Complete Handler
|
80 | reti ; rjmp USART_RXC ; USART RX Complete Handler
|
81 | reti ; rjmp USART_UDRE ; UDR Empty Handler
|
82 | reti ; rjmp USART_TXC ; USART TX Complete Handler
|
83 | reti ; rjmp ADCC ; ADC Conversion Complete Handler
|
84 | reti ; rjmp EE_RDY ; EEPROM Ready Handler
|
85 | reti ; rjmp ANA_COMP ; Analog Comparator Handler
|
86 | reti ; rjmp TWSI ; Two-wire Serial Interface Handler
|
87 | reti ; rjmp SPM_RDY ; Store Program Memory Ready Handler
|
88 |
|
89 | reset: ;Programmstart
|
90 | ldi zl,low(ramend) ;Stackpointer
|
91 | ldi zh,high(ramend) ;am
|
92 | out spl,zl ;RAM-Ende
|
93 | out sph,zh ;initialisieren
|
94 |
|
95 | clr scan ;definierte
|
96 | clr tz0 ;Startzustände
|
97 | clr tz1 ;für
|
98 | clr tas ;Tasten-
|
99 | clr tfl ;Entprellung
|
100 |
|
101 | ldi zl,3 ;Timer0-Vorteiler
|
102 | out tccr0,zl ;auf 64 einstellen
|
103 | ldi zl,timer0start ;Timer0-Startwert
|
104 | mov tsw,zl ;definieren
|
105 | out tcnt0,tsw ;Timer-Startwert setzen
|
106 | ldi zl,1<<toie0 ;Timer0-Überlauf-Int
|
107 | out timsk,zl ;aktivieren
|
108 | ldi zl,smm ;Schrittmotorbits als
|
109 | out smp-1,zl ;Ausgang (ddrx=portx-1)
|
110 | ldi zl,0 ;alle Bits löschen
|
111 | out smp,zl ;Motor erstmal aus
|
112 | out tap+1,zl ;Tastenport als Eingang (ddrx=pinx+1)
|
113 | cbi nup+1,nuse ;Nullpunkt-Portpin als Eingang (ddrx=pinx+1)
|
114 | sbi nup+2,nuse ;Pull-Up Nullpunkt-Portpin ein (portx=pinx+2)
|
115 | sbi lap,lapi ;Laser-Anschluss als Ausgang
|
116 | ldi zl,255 ;alle Bits setzen
|
117 | out tap+2,zl ;Pull-UP-R's einschalten (portx=pinx+2)
|
118 | ldi zl,(1<<adlar)+adq ;Analogwandler linksbündige Ausgabe und Signalquelle
|
119 | out admux,zl ;wie oben in "adq" definiert
|
120 | ldi zl,(1<<aden)|(1<<adsc)|(1<<adfr)+2 ;ADC freilaufend mit Vorteiler 1:4
|
121 | out adcsra,zl ;einschalten
|
122 | ldi mode,1<<nus ;beim Start auf Nullposition fahren
|
123 | ldi posi,255 ;Start der Nullpunktsuche
|
124 | sei ;Int aktivieren
|
125 |
|
126 | main:
|
127 | rjmp main ;Nix tun...
|
128 |
|
129 |
|
130 |
|
131 | timer0:
|
132 | ; in srsk,sreg ;SREG sichern
|
133 | out tcnt0,tsw ;Timer Reload
|
134 |
|
135 | Tastenabfrage: ;Entprellroutine geklaut bei Peter Dannegger...
|
136 | in scan,tap ;Tastenport einlesen (gedrückt=L)
|
137 | com scan ;invertieren (gedrückt=H)
|
138 | eor scan,tas ;nur Änderungen werden H
|
139 | and tz0,scan ;Prellzähler unveränderter Tasten löschen (Bit0)
|
140 | and tz1,scan ;Prellzähler unveränderter Tasten löschen (Bit1)
|
141 | com tz0 ;L-Bit zählen 0,2,->1, 1,3,->0
|
142 | eor tz1,tz0 ;H-Bit zählen 0,2,->tz1 toggeln
|
143 | and scan,tz0 ;Änderungen nur dann erhalten, wenn im Prellzähler
|
144 | and scan,tz1 ;beide Bits gesetzt sind (Zählerstand 3)
|
145 | eor tas,scan ;erhaltene Änderungen toggeln alten (gültigen) Tastenstatus
|
146 | and scan,tas ;nur (neu) gedrückte Tastenbits bleiben erhalten
|
147 | or tfl,scan ;und zugehörige Bits setzen (gelöscht wird nach Abarbeitung)
|
148 | ;in "tas" steht jetzt der gültige Tastenzustand,
|
149 | ;in "tfl" die Flags der neu gedrückten, noch nicht abgearbeiteten Tasten...
|
150 |
|
151 | sbrs tfl,tla ;Taste für Laserschalter gedrückt?
|
152 | rjmp savezeit ;nein...
|
153 | in wl,lap ;Laserport einlesen
|
154 | ldi wh,1<<lapi ;Laserpin
|
155 | eor wl,wh ;toggeln
|
156 | out lap,wl ;und wieder ausgeben
|
157 | cbr tfl,1<<tla ;Tastenflag löschen
|
158 |
|
159 | savezeit: ;Zweiter Job der "Enter-Taste"
|
160 | sbrs mode,savz ;muss Verweilzeit gespeichert werden? (allerhöchste Priorität)
|
161 | rjmp nullsuch ;nein...
|
162 | cbr mode,1<<savz ;ja, Flag wieder löschen
|
163 | in wl,adch ;ADC auslesen,
|
164 | inc wl ;Bereichskorrektur (Minimum=1, Maximum=256=0)
|
165 | ldi wh,1 ;obere EEP-Page (Verweilzeiten)
|
166 | out eearh,wh ;adressieren (untere Adresse bleibt so)
|
167 | out eedr,wl ;ADC-Wert in EEP
|
168 | sbi eecr,eemwe ;Schreibschutz aufheben
|
169 | sbi eecr,eewe ;Schreiben
|
170 | rjmp fertig ;fertig...
|
171 |
|
172 | nullsuch: ;Motor auf Nullpunkt fahren
|
173 | sbrs mode,nus ;Nullpunkt suchen? (mittlere Priorität)
|
174 | rjmp schalter ;nein...
|
175 | sbic nup,nuse ;Nullpunkt-Sensor erreicht? (Lichtschranke unterbrochen?)
|
176 | rjmp nullfund ;ja...
|
177 | dec posi ;nein, weiter runter fahren
|
178 | breq nullfund ;255 Schritte gesucht? - aufhören, da stimmt was nicht...
|
179 | rjmp stellmot ;Motor stellen...
|
180 | nullfund:
|
181 | andi posi,7 ;Positionszähler löschen, untere 3 Bit bleiben erhalten
|
182 | ori posi,64 ;Spielraum nach unten
|
183 | mov soll,posi ;Sollwert nachziehen
|
184 | ldi ztv,1 ;Verweilzeit auf Minimum
|
185 | mov ztz,ztv ;einstellen,
|
186 | ldi wl,255 ;letzte EEP-Adresse
|
187 | out eearl,wl ;(um mit der ersten zu beginnen)
|
188 | cbr mode,1<<nus ;Nullsuchflag löschen
|
189 | rjmp fertig ;fertig...
|
190 |
|
191 | schalter: ;Einrichten
|
192 | sbrs tfl,trst ;ja, Taste "Reset" gedrückt? (immer verfügbar)
|
193 | rjmp schalter01 ;nein...
|
194 | cbr tfl,1<<trst ;ja, Tastenflag löschen
|
195 | ldi posi,255 ;nur 255 Suchschritte
|
196 | out eearl,posi ;letzte EEP-Adresse, um mit 0 zu beginnen
|
197 | sbr mode,1<<nus ;Nullsuch-Flag setzen,
|
198 | rjmp nullsuch ;und gleich beginnen...
|
199 | schalter01:
|
200 | sbrs tas,mset ;Einrichtmodus aktiv?
|
201 | rjmp schalter1 ;nein, restliche Tasten nicht abfragen...
|
202 | sbrs tfl,tup ;Taste "Up" gedrückt?
|
203 | rjmp schalter02 ;nein...
|
204 | cbr tfl,1<<tup ;ja, Tastenflag löschen
|
205 | inc posi ;Position erhöhen
|
206 | cpi posi,schritte*2 ;Zählumfang auf doppelte Schrittzahl (Halbschritt)
|
207 | brne schalter01a ;begrenzen
|
208 | clr posi ;
|
209 | schalter01a:
|
210 | rjmp stellmot ;und Motor stellen...
|
211 | schalter02:
|
212 | sbrs tfl,tdn ;Taste "Down" gedrückt?
|
213 | rjmp schalter03 ;nein...
|
214 | cbr tfl,1<<tdn ;ja, Tastenflag löschen
|
215 | dec posi ;Position vermindern
|
216 | cpi posi,0 ;Zählumfang auf doppelte Schrittzahl (Halbschritt)
|
217 | brne schalter02a ;begrenzen
|
218 | ldi posi,schritte*2 ;
|
219 | schalter02a:
|
220 | rjmp stellmot ;und Motor stellen...
|
221 | schalter03:
|
222 | sbrs tfl,tent ;Taste "Enter" gedrückt?
|
223 | rjmp schalter04 ;nein...
|
224 | cbr tfl,1<<tent ;ja, Tastenflag löschen
|
225 | in wl,eearl ;EEP-Adresse holen
|
226 | inc wl ;und erhöhen
|
227 | cpi wl,255 ;letzte Zelle erreicht?
|
228 | breq enter1 ;ja, nicht im EEP speichern...
|
229 | out eearh,null ;untere EEP-Page (Positionen)
|
230 | out eearl,wl ;EEP-Adresse setzen
|
231 | out eedr,posi ;Position ins EEP
|
232 | sbi eecr,eemwe ;Schreibschutz aufheben
|
233 | sbi eecr,eewe ;schreiben
|
234 | sbr mode,1<<savz ;Flag zum Zeit Speichern setzen (wird nächste Runde gemacht)
|
235 | enter1: ;Sprungziel bei Überlauf (nicht speichern)
|
236 | rjmp fertig ;fertig...
|
237 | schalter04:
|
238 | sbrs tfl,tok ;Taste "Ok" gedrückt?
|
239 | rjmp schalter1 ;nein...
|
240 | cbr tfl,1<<tok ;ja, Tastenflag löschen
|
241 | in wl,eearl ;EEP-Adresse holen
|
242 | inc wl ;und erhöhen
|
243 | breq enter1 ;Überlauf...
|
244 | out eearh,null ;untere EEP-Page (Positionen)
|
245 | out eearl,wl ;EEP-Adresse setzen
|
246 | ldi wl,255 ;Leerbyte (nur eins zur Ende-Kennung)
|
247 | out eedr,wl ;ins EEP
|
248 | sbi eecr,eemwe ;Schreibschutz aufheben
|
249 | sbi eecr,eewe ;schreiben
|
250 | rjmp fertig ;
|
251 |
|
252 | schalter1: ;RUN
|
253 | sbrs tas,mrun ;Runmodus aktiv?
|
254 | rjmp keinschalter ;nein...
|
255 | cp posi,soll ;Zielpunkt erreicht?
|
256 | breq warten ;ja, Zeit abwarten...
|
257 | brmi motplus ;nein, Position noch zu klein...
|
258 | dec posi ;nein, Pos. zu groß, verkleinern
|
259 | cpi posi,0 ;Zählumfang auf doppelte Schrittzahl (Halbschritt)
|
260 | brne stellmot ;begrenzen
|
261 | ldi posi,schritte*2 ;
|
262 | rjmp stellmot ;und Motorschritt ausführen...
|
263 | motplus:
|
264 | inc posi ;Position vergrößern
|
265 | cpi posi,schritte*2 ;Zählumfang auf doppelte Schrittzahl (Halbschritt)
|
266 | brne stellmot ;begrenzen
|
267 | clr posi ;
|
268 | stellmot:
|
269 | ldi zl,low(bimu*2) ;Zeiger auf
|
270 | ldi zh,high(bimu*2) ;Motor-Bitmuster
|
271 | mov wl,posi ;Kopie von Position zwecks
|
272 | andi wl,7 ;Ausblendung der oberen Bits
|
273 | add zl,wl ;Offset dazu,
|
274 | adc zh,null ;Übertrag auch
|
275 | lpm wl,z ;Bitmuster holen
|
276 | andi wl,smm ;eventuell ungültige Bits ausblenden
|
277 | in wh,smp ;Schrittmotor-Port einlesen
|
278 | andi wh,255-smm ;Schrittmotor-Bits löschen
|
279 | or wh,wl ;neue Schrittmotor-Bits dazu
|
280 | out smp,wh ;und an Port ausgeben
|
281 | rjmp fertig ;fertig...
|
282 | warten:
|
283 | dec ztv ;Vorteiler (100) runter (1s je Runde)
|
284 | brne fertig ;kein Übertrag...
|
285 | ldi ztv,100 ;Vorteiler auf Startwert
|
286 | dec ztz ;Sekunde runter
|
287 | brne fertig ;nicht abgelaufen...
|
288 | ;Wartezeit abgelaufen...
|
289 | nextpos:
|
290 | in wl,eearl ;EEP-Adresse holen
|
291 | inc wl ;erhöhen (nächste Position)
|
292 | vonvorn:
|
293 | out eearl,wl ;EEP-Adresse zurückschreiben
|
294 | out eearh,null ;untere Page (Positionen)
|
295 | sbi eecr,eere ;EEP lesen
|
296 | in soll,eedr ;als neuen Sollwert
|
297 | ldi wh,1 ;EEP-Adresse obere Page
|
298 | out eearh,wh ;(Verweildauer)
|
299 | sbi eecr,eere ;EEP lesen
|
300 | in ztz,eedr ;als neue Verweilzeit
|
301 | cpi soll,$ff ;Wert gültig? (<>$ff)
|
302 | brne fertig ;ja, fertig...
|
303 |
|
304 | tst wl ;nein, war das Adresse 0?
|
305 | breq fertig ;ja, dann ist EEP noch leer...
|
306 |
|
307 | mov soll,posi ;nein, Wert verwerfen
|
308 | clr ztz ;Zeit auch
|
309 | clr wl ;EEP-Adr.
|
310 | clr wh ;von vorn
|
311 | rjmp vonvorn ;beginnen...
|
312 |
|
313 | keinschalter: ;es ist kein Schalter betätigt (Mittelstellung)
|
314 | ;Platz für Steuerung via RS232 per PC (optionale Erweiterung)
|
315 | fertig:
|
316 | ; out sreg,srsk ;SREG wiederherstellen
|
317 | reti ;fertig...
|
318 |
|
319 |
|
320 | bimu: ;Bitmuster für Schrittmotor
|
321 | .db 0b10000000,0b11000000 ;
|
322 | .db 0b01000000,0b01100000 ;
|
323 | .db 0b00100000,0b00110000 ;
|
324 | .db 0b00010000,0b10010000 ;
|