Forum: Mikrocontroller und Digitale Elektronik Tiny2313 Ampelschaltung spinnt nach einem Druchlauf


von Ralf (Gast)


Lesenswert?

Hallo,
erstmal Danke für dieses Forum. Ich habe gerade erst mit der 
ARV-Programmierung angefangen und möchte meine Modeleisenbahn damit 
erweitern. Mein erstes Übungsobjet eine Ampelsteuerung scheint aber 
schon recht schwierig zu werden. Ich benutze einen Atmel Tiny2313 mit 
dem PollinAVR . Ich habe zwei Ampeln (LEDs) an den PORTD angeschlossen. 
(Ampel_1: Rot, gelb, grün: PD0, PD1, PD2) (Ampel_2: PD3, PD4, PD5). Das 
Progamm habe ich mir mit Hilfe von AVR-Studio erstellt:
1
 
2
.include "tn2313def.inc"
3
.def     Trafficlight = R16     ; Define R16 als Traficlight
4
.def     Timer1 = R17
5
.def     Timer2 = R18           ; Define R17 als Timer1
6
.def     Temp1 = R19            ; Tempregister
7
.def     Null = R20             ; Tempregister (sonst null)
8
.EQU     RAM_Ampel=0x0060       ; Define Speicer für Ampel
9
.equ     TIMERWERT = 3906       ; Compwert für Timmer_Counter1
10
.ESEG                           ; EEPROM Speichern
11
.db      0x0d                   ; 14 Werte ins SRAM übertragen
12
.db      0x06,0x21,0x06,0x11,0x01,0x0b, 0x01,0x0c,0x06,0x0a,0x01,0x19,0x01
13
                                ; AmpelTag schaltung ( 1..6 Werte und Zeiten)
14
         .CSEG
15
.org     0x0000                 ; Start
16
         rjmp ERAMlesen         ; Kopier ERAM ins SRAM
17
         reti
18
         reti
19
         reti
20
         rjmp TIM1_COMPA 
21
         reti
22
         reti
23
         reti
24
         reti
25
         reti
26
         reti
27
         reti
28
         reti
29
         reti
30
         reti
31
         reti
32
33
ERAMlesen:
34
; ldi Temp1, high(ramend)       ; letze Adr im SRAM
35
; out sph,temp1                 ; Stapel einrichten
36
         ldi temp1,low(ramend)
37
         out spl, temp1
38
         ldi Trafficlight, 0x3f ; Setze Maske Ausgangsports
39
         out DDRD, Trafficlight ; Setze Ausgangsports
40
         sbic EECR,0
41
         rjmp ERAMlesen
42
         LDI ZH, HIGH(0x0000)
43
         LDI ZL, Low(0x0000)
44
         LDI XH, high(0x0060)   ; Zeiger auf SRAM
45
         LDI XL, Low(0x0060)  
46
47
         OUT EEARL,ZL
48
         SBI EECR,0 
49
         IN Timer1,EEDR
50
ERAMlesenLoop1:                 ; Werte aus ERAM holen und im SRAM Speichern
51
         adiW ZL,1
52
         OUT EEARL,ZL
53
         SBI EECR,0
54
         IN Temp1,EEDR
55
         ST X+, Temp1
56
         DEC Timer1
57
         BRNE ERAMlesenLoop1
58
;---------------
59
         ldi Temp1, Low(Timerwert) ; Timer vorbelegen
60
         out OCR1AL,Temp1
61
         ldi Temp1, High(Timerwert)
62
         out OCR1AH,Temp1
63
         ldi Temp1,0x0c         ; Prescaller 
64
         out TCCR1B,Temp1
65
         ldi temp1,0x50         ; Interupt Comp
66
         out TIMSK,Temp1   
67
         sei
68
AmpelInit:
69
         rcall AmpelTag
70
         rcall AmpelTagLoop1
71
         rjmp DoNothing
72
AmpelTag:
73
         LDI XH, high(RAM_Ampel); Zeiger auf RAM_Ampel
74
         LDI XL, Low(RAM_Ampel)
75
         LD Timer1, X+          ; Anzahl der Werte holen
76
         ret
77
AmpelTagloop1:
78
         LD Trafficlight, X+    ; Ampelwert holen
79
         out PORTD, Trafficlight
80
         LD Timer2, X+          ; Zeitspanne holen
81
         DEC Timer1             ; Zähler der noch zu holenden Werte
82
         ret
83
;------------------
84
TIM1_COMPA:
85
         in Temp1,Sreg          ; SREG retten
86
         push Temp1
87
         Dec Timer2             ; Zeitzähler verringern
88
         cpse Timer2,Null
89
         rjmp TIM1_COMPA_Exit   ; wenn Timer2 <>0
90
         mov Temp1,timer1       ; merken
91
         cpse Timer1,Null
92
         rcall AmpelTagLoop1    ; wenn Timer2=0 und Timer1 <>0
93
         cpse Temp1,Null
94
         rjmp TIM1_COMPA_Exit
95
         rcall AmpelTag         ; wenn Timer2=Timer1=0
96
         rcall AmpelTagLoop1
97
98
TIM1_COMPA_Exit:
99
         pop Temp1              ; SREG setzen
100
         out SREG,Temp1
101
         reti
102
103
DoNothing:
104
         rjmp DoNothing

In der Simulation funkt alles wunderbar!

Also habe ich das Prog via PonyProg auf meinen Tiny geschrieben und 
getestet: Klappt nur einmal wunderbar danach macht er nur MIST. Also ein 
kompletter Druchlauf funktioniert und dann macht es scheinbar was er 
will... nach einem Reset klappt der Durchlauf wieder einmal.

Ich komme einfach nicht mehr weiter, evtl. kann mir jem helfen?

Schönen Sonntag
Gruß Ralf

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Was heißt mist?
Ach ja für Interupts gibt es in der .def Datei (nach dem kompilieren 
unter dem Punkt included files) extra defines:

.org ICP1addr z.b. für den InputCapture des Timer 1, dann kannst du dir 
die ganze Regi orgie sparen.

.org INT_VECTORS_SIZE sezt dann dein Programm "dahinter"

Außerdem erscheint "ERAMlesen" etwas wirr. Was genau willst du da 
machen?

von Spess53 (Gast)


Lesenswert?

Hi

Ich finde keine Stelle, an der überprüft wird, wann der Durchlauf zu 
Ende ist. Irgendwann zeigt X auf undefinierten RAM.

Sieh dir mal an, wo du mit 'rjmp ERAMlesen' hin springst. Die 
EEPROM-Leseroutine solltest du so wie im Datenblatt machen.

Deine Konstanten kannst du auch im Flash speichern und dort auslesen. da 
ersparst du dir das ganze umkopieren.

MfG Spess

von Ralf (Gast)


Lesenswert?

Hi.
Danke das mit dem .org OC1Aaddr ist ne gute Idee.

das ERAMlesen, habe ich mir von einem anderem Code abgeschaut, (ehrlich 
nicht ganz verstanden, aber es klappt ganz gut.)
zuerst wird ein Wert gelesen (0x0d) --> es sollen 13 Werte gelesen 
werden)
dann wird eine Schleife zum Lesen aus ERAM und Speichern im SRAM 
durchgeführt, dabei wird jeder Wert einzeln übertragen, ich dachte mir 
dadurch bin ich später mal flexibler. Das ist aber scheinbar auch nicht 
das Problem, denn die übertragenen Werte werden später richtig benutzt.
0x06,0x21,0x06,0x11,0x01,.... sind meine Ampelphase:
wobei der 1. Wert (wie beim ERAM kopieren die Anzahl der Werte gibt, 
nach der die Ampelphase von vor beginnt.)
6 das sechs Ausgaben nötig sind, mit jeweils einer Zeitangabe, also 12 
Werte.

0x06   ,0x21            ,0x06      ,0x11            ,0x01     ,....
6Werte | A1:rot, A2 grün| 6x Timer | A1:rot A2:gelb | 1x Timer ...

soweit so gut, wie gesagt beim 1.Durchlauf funktioniert die Ausgabe an 
den Pins von PORTD richtig. jedoch beim 2.Durchlauf zeigt die Ausgabe 
immer unterschiedliche Werte.

Ich habe es auch schon mit einem Mega16 getestet mit dem selben 
Ergebnis. :-( Ich denke das Problem muss beim neuInit liegen, wobei in 
der Simulation alles klasse klappt. -> Habe ich evtl. einen Interupt 
falsch gesetzt? oder muss ich die nicht benutzten Pins vom Tiny auf 
Masse legen, damit sie nicht umkippen? <-dann wundert es mich aber warum 
der 1.Druchlauf klappt.

Ist mein Progi sonst soweit verständlich? Ich bin erst eine Woche dabei 
und habe evtl. eine leicht seltsame Logik im Ablauf.

Gruß
Ralf

von Ralf (Gast)


Lesenswert?

Hallo @  Spess53
...
mov Temp1,timer1   ; in timer1 stehen die Anzahl der zulesenden 
Doppelwerte
...
cpse Temp1,Null        ; Wenn der Timer 0 ist (kein weiterer Wert mehr 
zu
                         lesen ist beginnt die AmtelTag ...
rjmp TIM1_COMPA_Exit
rcall AmpelTag
rcall AmpelTagLoop1

>> Irgendwann zeigt X auf undefinierten RAM.
hast du das eep geladen?

Gruß
Ralf

von Ralf (Gast)


Lesenswert?

Hi @ Läubi

>>Außerdem erscheint "ERAMlesen" etwas wirr. Was genau willst du da
machen?
1
ERAMlesen:
2
         sbic EECR,0            ; OK laut Datenblatt sbic EECR,EEPE 
3
         rjmp ERAMlesen
4
         LDI ZH, HIGH(0x0000)   ; Zeiger für ERAM für Tiny reicht ZL
5
         LDI ZL, Low(0x0000)
6
         LDI XH, high(0x0060)   ; Zeiger auf SRAM
7
         LDI XL, Low(0x0060)  
8
9
         OUT EEARL,ZL           ; Setzen der Speicheradr.
10
         SBI EECR,0             ; hat glaube ich was mit INT zu tun? 
11
                                ; Datenblatt : SBI EECR, EEPE
12
         IN Timer1,EEDR         ; Timer1 enthält die Anzahl der Werte die 
13
                                ; übertragen werden sollen
14
ERAMlesenLoop1:                 ; Werte aus ERAM lesen und SRAM speichern
15
         adiW ZL,1              ; ERAM Zeiger +1
16
         OUT EEARL,ZL           ; Speicheradr setzen
17
         SBI EECR,0         
18
         IN Temp1,EEDR          ; Wert lesen in Temp merken
19
         ST X+, Temp1           ; im SRAM speichern und zur nächsten Adr
20
         DEC Timer1             ; Anzahl der zu übertr. Werte -1
21
         BRNE ERAMlesenLoop1    ; Wenn nicht Null nächten Wert lesen

Ich hoffe jetzt wird es leichter meinem Code zu folgen. Ich binn leider 
immer etwas faul wenn's um die Doku geht.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Soo, hier mal eine aufgeräumte und debuggte Version.

- Kopieren der Daten vom EEPROM ins RAM fehlerhaft, das erste Byte, 
welches die Anzahl der Datensätze definiert, wurde nicht kopiert
- Nicht mit kodierten Adressen arbeiten, das geht fix schief. Labels 
verwenden!
- erst ALLES initialisieren, dann erst die Interrupts freigeben. *GANZ 
WICHTIG!*
- Kuddelmuddel im Interrupt aufgeräumt, war auch fehlerhafte Logik
- Formatierung ist wichtig, um den Durchblick zu behalten!

MfG
Falk

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Uuups, noch ein kleiner Bug. Update siehe Anhang.

Ach ja, ein weiterer Fehler im Original

- Beim Schreibzugriff auf 16 Bit Register muss man erst das HIGH und 
dann das Low Byte schreiben!

MFg
Falk

von Ralf (Gast)


Lesenswert?

Danke @Falk

Ich habe mir grad den Code von Dir angesehen, Vielen Dank, ich denke da 
muss ich wohl noch etwas lernen, na, ja aber für die erste Woche reicht 
es mir. Die Abfolge stimmte jetzt leider nicht mehr ganz, konnte ich 
aber beheben.

Ich denke, die Logik habe ich verstanden, bei mir war es etwas 
kompliziert, da ich mit dem Statusregister nicht ganz "grün" war, und 
ich es zuerst ohne Interupt programmiert hatte.
Im ARV-Simulator klappt es, so wie es soll, ich werden es morgen auf dem 
Tiny testen und mich dann melden.

Danke am Alle die mir geholfen haben!

Gruß
Ralf

von Ralf (Gast)


Lesenswert?

Hat gefunkt!
MFG
Ralf

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.