1 | ;******** ledtest2.asm ********
|
2 | ; Testprogramm für AVR-Demoboard mit AT90S1200
|
3 | ; Durchzählen der LEDs per Timer0
|
4 | ;
|
5 | ; Autor: J. Zimmermann Status: getestet
|
6 | ; Datum: 08.06.1998 Version: 1.0
|
7 | ;
|
8 | ; Ing.-Büro Josef Zimmermann
|
9 | ; Copyleft nach GNU GPL
|
10 | ;
|
11 | ; Konfiguration der Harware: Atmel Evaluationboard
|
12 | ; Verbindung per Flachbandkabel von LEDs mit PortB
|
13 | ;
|
14 | ; Für AVR-ASM V1.21 oder höher
|
15 | ; Bitte den sleep-Befehl nicht im Simulator verwenden!
|
16 | ;
|
17 | ; Die Art und Weise in der die Hardware-Register initialisiert werden ist nicht ganz
|
18 | ; sauber. Besser wäre es zunächst das Register zu lesen, den Wert über Bit-Befehle zu
|
19 | ; ändern und dann zurück zu schreiben. Spätestens bei der Portierung auf einen anderen
|
20 | ; Controller der AVR-Familie kann es sonst zu Problemen kommen. Darüber hinaus muß bei
|
21 | ; der Portierung der Stackpointer initialisiert werden, was sich beim 90S1200
|
22 | ; erübrigt, wegen des Hardwarestacks.
|
23 | ;
|
24 | ;********************************************
|
25 | ; Etwas Theorie zum Timer
|
26 | ; Es soll ein Timer_tic von 50ms erzeugt werden. Dieser steuert per Interrupt das
|
27 | ; hochzählen des Ausgangsports. Das Demo-Board ist mit einem 4MHz-Quarz bestückt.
|
28 | ; Ein Interrupt wird beim Timer0 überlauf ausgelöst. Damit ergibt sich:
|
29 | ;
|
30 | ; TCNT0 = 256 - (T_tic / ( T_clk * Kprescale))
|
31 | ; TCNT0 = 61 für T_tic = 50ms T_clk = 1/4 us und Kprescale = 1024
|
32 | ;
|
33 | ; als Randbedingung für den Prescaler ist folgendes zu beachten:
|
34 | ;
|
35 | ; Kprescale > (T_tic / (T_clk * 256))
|
36 | ;
|
37 | ; Wir T_tic größer als T_clk * 1024 * 256 kann man den Takt über einen Softwarezähler
|
38 | ; weiter herunterteilen. Die Altenative wäre ein exter Takt (passender Frequenz) zum
|
39 | ; takten des Timer/Counters.
|
40 |
|
41 |
|
42 | .include "1200def.inc"
|
43 | .device AT90S1200
|
44 |
|
45 | .def Temp =r16 ;temporary register
|
46 | .def L_Temp =r17
|
47 |
|
48 |
|
49 | ;***** Reset- und Interrupt-Vektoren
|
50 |
|
51 | RESET: rjmp ihMain ;000 Reset Einsprung
|
52 | rjmp ihIrq0 ;001 IRQ0
|
53 | rjmp ihTimer0_ovf ;002 Timer/Counter0 overflow
|
54 | rjmp ihAna_cmp ;003 Analog Comparator
|
55 |
|
56 |
|
57 | ;*** Initialisierung PortB, Timer0, Interrupte und IDLE-Mode
|
58 | ihMain:
|
59 | ser Temp ;Temp = 0xff
|
60 | out DDRB,Temp ;PORTB = alle Pins outputs
|
61 | out PORTB, Temp ;PORTB = 0xff -> alle LEDs aus, Low aktiv!
|
62 |
|
63 | ldi L_Temp, 0x3d ;TCNT0 := 61dez. = 0x3d Timerregister mit Wert laden
|
64 | out TCNT0, L_Temp
|
65 |
|
66 | ldi L_Temp, 0x05 ;TCCR0 := 00000101b = 0x05 Prescalefaktor 1024
|
67 | out TCCR0, L_Temp
|
68 |
|
69 | ldi L_Temp, 0x02 ;TIMSK := 00000010b = 0x02 Enable Timer0 overflow INT
|
70 | out TIMSK, L_Temp
|
71 |
|
72 | sei ;SREG Global Interrup enable
|
73 |
|
74 | ldi L_Temp, 0x20 ;MCUCR := 00100000b = 0x20 IDLE MODE per "sleep"
|
75 | out MCUCR, L_Temp
|
76 |
|
77 | ;*** Das eigentliches Hauptprogramm tut nichts, außer schlafen!
|
78 | ; Achtung!!! "sleep" nicht auf dem Simulator verwenden!
|
79 | forever: ;
|
80 | sleep ;CPU sagt gute Nacht bis der Timer klingelt. IDLE MODE!
|
81 | rjmp forever ;Und das ganze noch mal von vorne
|
82 |
|
83 |
|
84 |
|
85 | ;**** Timer overflow Interrupt
|
86 | ; Die TOV0-Flag (im Register TIFR) wird automatisch mit Aufruf des Interruptvectors
|
87 | ; zurückgesetzt. Die I-Flag (im Status-Register) wird mit RETI zurückgesetzt.
|
88 |
|
89 | ihTimer0_ovf:
|
90 | ldi L_Temp, 0x3d ;TCNT0 := 0x31 Timerregister laden
|
91 | out TCNT0, L_Temp
|
92 | out PORTB,Temp ;PORTB := Temp
|
93 | dec Temp ;Temp := Temp - 1
|
94 | reti
|
95 |
|
96 |
|
97 | ;****** Ist etwas schiefgegangen? ****
|
98 | ; Diese Routinen dürfen eigentlich nicht angesprungen werden, da diese Interrupts
|
99 | ; nicht frei gegeben sind. (Hilfreich beim debuggen) Die Routine endet in einer
|
100 | ; Endlosschleife, weil kein RETI ausgeführt wird und damit der Global Interrupt
|
101 | ; (I-Bit im Status Register) disabled bleibt!
|
102 | ; Es wird ein Fehler-Code auf die LEDs ausgegeben und das Programm hängt fest.
|
103 |
|
104 | ihIRQ0:
|
105 | ldi Temp, 0xfe ;Wert für LED0 ein
|
106 | rjmp INT_ERR ;
|
107 |
|
108 | ihAna_cmp:
|
109 | ldi Temp, 0xfd ;Wert für LED1 ein
|
110 | rjmp INT_ERR
|
111 |
|
112 | INT_ERR:
|
113 | out PORTB, Temp ;Error Wert an LEDs anzeigen
|
114 | rjmp INT_ERR
|
115 |
|
116 |
|
117 | VERSION: .DB "LEDTEST2.ASM FUER AVR 90S1200 Version 1.0 "
|