Guest User

Untitled

a guest
Jul 10th, 2014
357
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * TrafficLightAssemlber.asm
  3.  *
  4.  *  Created: 04.07.2014 12:23:03
  5.  *   Author: 245292
  6.  */
  7.  
  8.  .include "m644PAdef.inc"   ; device: ATmega 644PA
  9. #define F_CPU 8000000       ; CPU-Takt: 8 MHz
  10. #define DEBUG               ; Für Simulator
  11.     .cseg           ; dies ist Code
  12. ; ----- Am Beginn des Codespeichers liegt die Vektortabelle -----
  13. ;       Hier nur Sprungtabelle anlegen. Mindestens für den
  14. ;       Reset-Interrupt (An Adresse 0):
  15.     .org    0       ; Am Anfang des Code-Speicher
  16.     jmp start       ; Sprung bei reset
  17.     .org OC1Aaddr   ; Timer1 Overflow Interrupt
  18.     jmp OCR1A_isr   ; Timer1 Overflow Interrupt
  19.     .org PCI0addr   ; Pin Change Interrupt
  20.     jmp PCINT0_isr  ; Pin Change Interrupt
  21. ; ***** Hier werden die "Variablen" definiert
  22.     .dseg           ; dies sind Daten
  23. T1count:    .byte 1 ; Zähler für Wartefunktion mit Timer1
  24.     .cseg           ; dies ist Code
  25. ; ----- Platz um .equ definitionen vorzunehmen
  26. #ifdef DEBUG
  27. .equ    T1Counter = 10          ; Debug-Timer-Wert für xxs
  28. #else
  29. .equ    T1Counter = 98          ; Timer-Wert für 0,1s
  30. #endif
  31. .equ nModusAn = 0x01    ; Nachtmodus der Ampel an
  32. .equ nModusAus = 0x00   ; Nachtmodus der Ampel aus
  33. .equ bedarf = 0x01      ; Bedarfs bei Deklarierung nicht vorhanden
  34. ; ----- Programm beginnt hinter der Vektortabelle: -----
  35.     .org 2*INT_VECTORS_SIZE
  36. ; hier kommen die Interrupt Service Routinen hin, wenn benutzt
  37. /********************************************************/
  38. ;   ISR Pin Change Interrupt : PCINT7
  39. PCINT0_isr:
  40.     ldi R28, bedarf
  41.     reti            ; Return from Interrupt;
  42.  
  43. ;   ISR Pin Change Interrupt : PCINT6
  44. PCINT6_isr:
  45.     ldi R27, nModusAus
  46.     reti            ; Return from Interrupt;
  47.  
  48. ;   ISR Pin Change Interrupt : PCINT5
  49. PCINT5_isr:
  50.     ldi R27, nModusAn
  51.     reti            ; Return from Interrupt;
  52.  
  53. ; ----- Initialisierung der PCINT0 -----
  54. InitPCINT0:
  55.  
  56.     push R17
  57.     push R18
  58.     ldi R17, 0x01
  59.     ldi R18, 0xE0
  60.     sts PCICR, R17
  61.     sts PCMSK0, R18
  62.     pop R18
  63.     pop R17
  64.    
  65.     /*sbi PCICR, PCINT0
  66.     sbi PCMSK0, PCINT7
  67.     sbi PCMSK0, PCINT6
  68.     sbi PCMSK0, PCINT5*/
  69.  
  70.  
  71. /********************************************************/
  72. ;   ISR Timer1 Compare Interrupt A
  73. OCR1A_isr: 
  74.     push r16                ; Register auf den Stack retten
  75.     in   r16, SREG          ; Statusregister zum Sichern nach R16
  76.     push r16                ; und auf den Stack
  77.     lds r16, T1count        ; Zählwert lesen
  78.     tst r16                 ; schon Null?
  79.     breq noDec              ; ja: nichts weiter Abziehen
  80.     dec r16                 ; T1count--
  81.     sts T1count, r16        ; und abspeichern
  82. noDec:
  83.     pop r16                 ; die Statusregister von Stack holen
  84.     out SREG, r16           ; und wieder herstellen
  85.     pop r16                 ; Register restaurierten
  86.     reti                    ; Return from Interrupt;
  87. ;
  88.  
  89.  
  90. ; ----- Initialisierung von Timer1 auf 0,1s Periode -----
  91. InitT1:
  92.     ; beim 644PA sind Timer1-Register Memory.mapped
  93.     push r17
  94.     ldi r17, HIGH(T1Counter)    ; Timer-Schwelle
  95.     sts OCR1AH, r17             ; byte-weise
  96.     ldi r17, LOW(T1Counter)     ; nach OCR1A
  97.     sts OCR1AL, r17
  98.     clr r17                 ; r17=0
  99.     sts TCNT1H, r17         ; Counter=0
  100.     sts TCNT1L, r17
  101.     sts TCCR1A, r17         ; configure to CTC-Mode
  102. #ifdef DEBUG
  103.     ldi r17, 0b0001010      ; CTC-mode, prescaler 8 für DEBUG
  104. #else
  105.     ldi r17, 0b0001101      ; CTC-mode, prescaler 1024
  106. #endif
  107.     sts TCCR1B, r17            
  108.     ; und den OC1A intrerrupt einschalten:
  109.     lds r17, TIMSK1         ; Interruptmaske Timer1
  110.     ori r17, 0b00000010     ; OCIE1A setzen
  111.     sts TIMSK1, r17         ; und abspeichern
  112.     pop r17
  113.     ret
  114.  
  115. ; ----- Warte-Zähler Setzen und Starten (nonblocking)
  116. startWait:
  117.     sts T1count, r16        ; Nur Zähler setzen
  118.     ret
  119. ; ----- Wait-funktion komplett
  120. ; Parameter: R16 enthält die Wartedauer in Zehntelsekunden
  121. wait:
  122. ; Timer resetten, Interrupt aktivieren
  123.     sts T1count, r16       
  124. ; ----- Rest der Komplett-Funktion als Abwarte-Funktion -----
  125. waitNow:
  126. ; polling auf Counter=0
  127.     lds r16, T1count
  128.     tst r16
  129.     brne waitNow
  130.     ret
  131.  
  132. ;-------------------------------------------------------------------------------------;
  133. ;InterrruptRoutinen Ende
  134.  
  135.  
  136.  /*
  137.   * Diese Ampel durchläuft die Phasen in dieser Reihenfolge:
  138.   *     Grün Rot -> Gelb Rot -> Rot Rot -> Rot Grün -> Rot Rot -> RotGelb Rot -> Grün Rot
  139.   *     Bei 8 verfügbaren Bits werden die Bits 0-2 für die Autoampel genutzt während die
  140.   *     beiden Bits 3 & 4 als Füßgängerampel genutzt werden. Bit 5 & 6 fungieren als
  141.   *     Taster um den Nachtmodus an bzw auszuschalten, während der letzte Bit der Ampel mitteilt,
  142.   *     dass jemand die Straße überqueren will.
  143.   */
  144.  
  145.  .equ nModus = 0x00     ; Ampel aus
  146.  .equ state1 = 0x11     ; Autoampel Grün   | Fußgängerampel Rot
  147.  .equ state2 = 0x12     ; Autoampel Gelb    | Fußgängerampel Rot
  148.  .equ state3 = 0x14     ; Autoampel Rot     | Fußgängerampel Rot
  149.  .equ state4 = 0x0C     ; Autoampel Rot     | Fußgängerampel Grün
  150.  .equ state5 = 0x16     ; Autoampel RotGelb | Fußgängerampel Rot
  151.  
  152. .cseg                   ; dies ist code
  153.  
  154. ; ***** Einsprungpunkt in das Hauptprogramm *****
  155. start:
  156. ; ----- Initialisierung der grundlegenden Funktionen -----
  157.     ; Initialisieren des Stacks am oberen Ende des RAM
  158.     ; 16 bit SP wird als SPH:SPL im IO-Space angesprochen
  159.     ldi r16, LOW(RAMEND)    ; low-Byte von RAMEND nach r16
  160.     out SPL, r16    ; in low-byte des SP ausgeben
  161.                     ; der SP liegt im IO-Space
  162.     ldi r16, HIGH(RAMEND)   ; high-Byte von RAMEND nach r16
  163.     out SPH, r16        ; in high-byte des SP ausgeben
  164.     ; ab hier kann der Stack verwendet werden
  165.  
  166.     call InitT1         ; Timer 1 initialisieren
  167. ; -----  PCINT0 initialisieren -----
  168.  
  169.     call InitPCINT0
  170.  
  171.     sei                 ; global Interrupt enable
  172.  
  173.  
  174. ; ----- Clear alle benutzen Register -----
  175.  
  176.     clr R20
  177.     clr R21
  178.     clr R22
  179.     clr R23
  180.     clr R24
  181.     clr R25
  182.     clr R26
  183.     clr R27     ; Status Nachtmodus an/aus
  184.     clr R28     ; Bedarfsknopf
  185.  
  186. ; ----- Definiere zugehörige Bits im PORT A als Ausgabe -----
  187.     ldi R26, 0x1F
  188.     out DDRA, R26
  189. ; ----- Lade alle Zustände in verschiedene Register -----
  190.     ldi R16, 20
  191.     ldi R20, nModus
  192.     ldi R21, state1
  193.     ldi R22, state2
  194.     ldi R23, state3
  195.     ldi R24, state4
  196.     ldi R25, state5
  197.     ldi R27, nModusAus  ; Anfangen mit Nachtmodus ausgeschaltet
  198.     ldi R28, bedarf     ; Bedarf am Anfang nicht vorhanden
  199. ;-------------------------------------------------------------------------------------;
  200.  
  201. ; ----- Routine um den korrekten Modus zu schalten -----
  202.  
  203. NMabfrage:
  204.     cpi R27, nModusAn  
  205.     breq nachtModus
  206.     jmp tagModus
  207.  
  208.  
  209. /*  Zwei Schleifen, die in ihrem jeweiligen Modus bleiben und nur umspringen, wenn
  210.     der Bedarfsknopf gedrückt wird, oder der Nachtmodus an- bzw ausgeschaltet
  211.     wird. Am Ende jeder Schleife wird überprüft, ob der Modus gewechselt werden muss */
  212.  
  213. tagModus:
  214.     out PORTA, R21
  215.     cpi R28, 1
  216.     breq ampelPhase
  217.     jmp NMabfrage
  218.  
  219. nachtModus:
  220.     out PORTA, R20
  221.     cpi R28, 1
  222.     breq ampelPhase
  223.     jmp NMabfrage
  224.  
  225. ; ----- Routinen um entweder kurz oder lang zu warten -----
  226.  
  227. waitLong:
  228.     ldi R16, 30
  229.     call wait
  230.     ret
  231.  
  232. waitShort:
  233.     ldi R16, 3
  234.     call wait
  235.     ret
  236.  
  237. ; ----- Die Ampelphase wird hier durchlaufen -----
  238.    
  239. ampelPhase:
  240.        
  241.     out PORTA, R21  ; schalte Ampel auf Grün für die Autos und Rot für die Fußgänger
  242.     call waitLong   ; warte lang
  243.        
  244.     out PORTA, R22  ; schalte Ampel auf Gelb für die Autos und Rot für die Fußgänger
  245.     call waitShort  ; warte kurz
  246.  
  247.     out PORTA, R23  ; schalte Ampel auf Rot für die Autos und Rot für die Fußgänger
  248.     call waitShort  ; warte kurz
  249.  
  250.     out PORTA, R24  ; schalte Ampel auf Rot für die Autos und Grün für die Fußgänger
  251.     call waitLong   ; warte lang
  252.  
  253.     out PORTA, R23  ; schalte Ampel auf Rot für die Autos und Rot für die Fußgänger
  254.     call waitShort  ; warte kurz
  255.  
  256.     out PORTA, R25  ; schalte Ampel auf RotGelb für die Autos und Rot für die Fußgänger
  257.     call waitShort  ; warte kurz
  258.  
  259.     out PORTA, R21  ; schalte Ampel auf Grün für die Autos und Rot für die Fußgänger
  260.  
  261. ; --- Ampelphase beendet, nun wird geschaut, ob der Nachtmodus an- bzw ausgeschaltet wurde
  262.     jmp NMabfrage
Advertisement
Add Comment
Please, Sign In to add comment