Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * TrafficLightAssemlber.asm
- *
- * Created: 04.07.2014 12:23:03
- * Author: 245292
- */
- .include "m644PAdef.inc" ; device: ATmega 644PA
- #define F_CPU 8000000 ; CPU-Takt: 8 MHz
- #define DEBUG ; Für Simulator
- .cseg ; dies ist Code
- ; ----- Am Beginn des Codespeichers liegt die Vektortabelle -----
- ; Hier nur Sprungtabelle anlegen. Mindestens für den
- ; Reset-Interrupt (An Adresse 0):
- .org 0 ; Am Anfang des Code-Speicher
- jmp start ; Sprung bei reset
- .org OC1Aaddr ; Timer1 Overflow Interrupt
- jmp OCR1A_isr ; Timer1 Overflow Interrupt
- .org PCI0addr ; Pin Change Interrupt
- jmp PCINT0_isr ; Pin Change Interrupt
- ; ***** Hier werden die "Variablen" definiert
- .dseg ; dies sind Daten
- T1count: .byte 1 ; Zähler für Wartefunktion mit Timer1
- .cseg ; dies ist Code
- ; ----- Platz um .equ definitionen vorzunehmen
- #ifdef DEBUG
- .equ T1Counter = 10 ; Debug-Timer-Wert für xxs
- #else
- .equ T1Counter = 98 ; Timer-Wert für 0,1s
- #endif
- .equ nModusAn = 0x01 ; Nachtmodus der Ampel an
- .equ nModusAus = 0x00 ; Nachtmodus der Ampel aus
- .equ bedarf = 0x01 ; Bedarfs bei Deklarierung nicht vorhanden
- ; ----- Programm beginnt hinter der Vektortabelle: -----
- .org 2*INT_VECTORS_SIZE
- ; hier kommen die Interrupt Service Routinen hin, wenn benutzt
- /********************************************************/
- ; ISR Pin Change Interrupt : PCINT7
- PCINT0_isr:
- ldi R28, bedarf
- reti ; Return from Interrupt;
- ; ISR Pin Change Interrupt : PCINT6
- PCINT6_isr:
- ldi R27, nModusAus
- reti ; Return from Interrupt;
- ; ISR Pin Change Interrupt : PCINT5
- PCINT5_isr:
- ldi R27, nModusAn
- reti ; Return from Interrupt;
- ; ----- Initialisierung der PCINT0 -----
- InitPCINT0:
- push R17
- push R18
- ldi R17, 0x01
- ldi R18, 0xE0
- sts PCICR, R17
- sts PCMSK0, R18
- pop R18
- pop R17
- /*sbi PCICR, PCINT0
- sbi PCMSK0, PCINT7
- sbi PCMSK0, PCINT6
- sbi PCMSK0, PCINT5*/
- /********************************************************/
- ; ISR Timer1 Compare Interrupt A
- OCR1A_isr:
- push r16 ; Register auf den Stack retten
- in r16, SREG ; Statusregister zum Sichern nach R16
- push r16 ; und auf den Stack
- lds r16, T1count ; Zählwert lesen
- tst r16 ; schon Null?
- breq noDec ; ja: nichts weiter Abziehen
- dec r16 ; T1count--
- sts T1count, r16 ; und abspeichern
- noDec:
- pop r16 ; die Statusregister von Stack holen
- out SREG, r16 ; und wieder herstellen
- pop r16 ; Register restaurierten
- reti ; Return from Interrupt;
- ;
- ; ----- Initialisierung von Timer1 auf 0,1s Periode -----
- InitT1:
- ; beim 644PA sind Timer1-Register Memory.mapped
- push r17
- ldi r17, HIGH(T1Counter) ; Timer-Schwelle
- sts OCR1AH, r17 ; byte-weise
- ldi r17, LOW(T1Counter) ; nach OCR1A
- sts OCR1AL, r17
- clr r17 ; r17=0
- sts TCNT1H, r17 ; Counter=0
- sts TCNT1L, r17
- sts TCCR1A, r17 ; configure to CTC-Mode
- #ifdef DEBUG
- ldi r17, 0b0001010 ; CTC-mode, prescaler 8 für DEBUG
- #else
- ldi r17, 0b0001101 ; CTC-mode, prescaler 1024
- #endif
- sts TCCR1B, r17
- ; und den OC1A intrerrupt einschalten:
- lds r17, TIMSK1 ; Interruptmaske Timer1
- ori r17, 0b00000010 ; OCIE1A setzen
- sts TIMSK1, r17 ; und abspeichern
- pop r17
- ret
- ; ----- Warte-Zähler Setzen und Starten (nonblocking)
- startWait:
- sts T1count, r16 ; Nur Zähler setzen
- ret
- ; ----- Wait-funktion komplett
- ; Parameter: R16 enthält die Wartedauer in Zehntelsekunden
- wait:
- ; Timer resetten, Interrupt aktivieren
- sts T1count, r16
- ; ----- Rest der Komplett-Funktion als Abwarte-Funktion -----
- waitNow:
- ; polling auf Counter=0
- lds r16, T1count
- tst r16
- brne waitNow
- ret
- ;-------------------------------------------------------------------------------------;
- ;InterrruptRoutinen Ende
- /*
- * Diese Ampel durchläuft die Phasen in dieser Reihenfolge:
- * Grün Rot -> Gelb Rot -> Rot Rot -> Rot Grün -> Rot Rot -> RotGelb Rot -> Grün Rot
- * Bei 8 verfügbaren Bits werden die Bits 0-2 für die Autoampel genutzt während die
- * beiden Bits 3 & 4 als Füßgängerampel genutzt werden. Bit 5 & 6 fungieren als
- * Taster um den Nachtmodus an bzw auszuschalten, während der letzte Bit der Ampel mitteilt,
- * dass jemand die Straße überqueren will.
- */
- .equ nModus = 0x00 ; Ampel aus
- .equ state1 = 0x11 ; Autoampel Grün | Fußgängerampel Rot
- .equ state2 = 0x12 ; Autoampel Gelb | Fußgängerampel Rot
- .equ state3 = 0x14 ; Autoampel Rot | Fußgängerampel Rot
- .equ state4 = 0x0C ; Autoampel Rot | Fußgängerampel Grün
- .equ state5 = 0x16 ; Autoampel RotGelb | Fußgängerampel Rot
- .cseg ; dies ist code
- ; ***** Einsprungpunkt in das Hauptprogramm *****
- start:
- ; ----- Initialisierung der grundlegenden Funktionen -----
- ; Initialisieren des Stacks am oberen Ende des RAM
- ; 16 bit SP wird als SPH:SPL im IO-Space angesprochen
- ldi r16, LOW(RAMEND) ; low-Byte von RAMEND nach r16
- out SPL, r16 ; in low-byte des SP ausgeben
- ; der SP liegt im IO-Space
- ldi r16, HIGH(RAMEND) ; high-Byte von RAMEND nach r16
- out SPH, r16 ; in high-byte des SP ausgeben
- ; ab hier kann der Stack verwendet werden
- call InitT1 ; Timer 1 initialisieren
- ; ----- PCINT0 initialisieren -----
- call InitPCINT0
- sei ; global Interrupt enable
- ; ----- Clear alle benutzen Register -----
- clr R20
- clr R21
- clr R22
- clr R23
- clr R24
- clr R25
- clr R26
- clr R27 ; Status Nachtmodus an/aus
- clr R28 ; Bedarfsknopf
- ; ----- Definiere zugehörige Bits im PORT A als Ausgabe -----
- ldi R26, 0x1F
- out DDRA, R26
- ; ----- Lade alle Zustände in verschiedene Register -----
- ldi R16, 20
- ldi R20, nModus
- ldi R21, state1
- ldi R22, state2
- ldi R23, state3
- ldi R24, state4
- ldi R25, state5
- ldi R27, nModusAus ; Anfangen mit Nachtmodus ausgeschaltet
- ldi R28, bedarf ; Bedarf am Anfang nicht vorhanden
- ;-------------------------------------------------------------------------------------;
- ; ----- Routine um den korrekten Modus zu schalten -----
- NMabfrage:
- cpi R27, nModusAn
- breq nachtModus
- jmp tagModus
- /* Zwei Schleifen, die in ihrem jeweiligen Modus bleiben und nur umspringen, wenn
- der Bedarfsknopf gedrückt wird, oder der Nachtmodus an- bzw ausgeschaltet
- wird. Am Ende jeder Schleife wird überprüft, ob der Modus gewechselt werden muss */
- tagModus:
- out PORTA, R21
- cpi R28, 1
- breq ampelPhase
- jmp NMabfrage
- nachtModus:
- out PORTA, R20
- cpi R28, 1
- breq ampelPhase
- jmp NMabfrage
- ; ----- Routinen um entweder kurz oder lang zu warten -----
- waitLong:
- ldi R16, 30
- call wait
- ret
- waitShort:
- ldi R16, 3
- call wait
- ret
- ; ----- Die Ampelphase wird hier durchlaufen -----
- ampelPhase:
- out PORTA, R21 ; schalte Ampel auf Grün für die Autos und Rot für die Fußgänger
- call waitLong ; warte lang
- out PORTA, R22 ; schalte Ampel auf Gelb für die Autos und Rot für die Fußgänger
- call waitShort ; warte kurz
- out PORTA, R23 ; schalte Ampel auf Rot für die Autos und Rot für die Fußgänger
- call waitShort ; warte kurz
- out PORTA, R24 ; schalte Ampel auf Rot für die Autos und Grün für die Fußgänger
- call waitLong ; warte lang
- out PORTA, R23 ; schalte Ampel auf Rot für die Autos und Rot für die Fußgänger
- call waitShort ; warte kurz
- out PORTA, R25 ; schalte Ampel auf RotGelb für die Autos und Rot für die Fußgänger
- call waitShort ; warte kurz
- out PORTA, R21 ; schalte Ampel auf Grün für die Autos und Rot für die Fußgänger
- ; --- Ampelphase beendet, nun wird geschaut, ob der Nachtmodus an- bzw ausgeschaltet wurde
- jmp NMabfrage
Advertisement
Add Comment
Please, Sign In to add comment