mikrocontroller.net

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


Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
 
.include "tn2313def.inc"
.def     Trafficlight = R16     ; Define R16 als Traficlight
.def     Timer1 = R17
.def     Timer2 = R18           ; Define R17 als Timer1
.def     Temp1 = R19            ; Tempregister
.def     Null = R20             ; Tempregister (sonst null)
.EQU     RAM_Ampel=0x0060       ; Define Speicer für Ampel
.equ     TIMERWERT = 3906       ; Compwert für Timmer_Counter1
.ESEG                           ; EEPROM Speichern
.db      0x0d                   ; 14 Werte ins SRAM übertragen
.db      0x06,0x21,0x06,0x11,0x01,0x0b, 0x01,0x0c,0x06,0x0a,0x01,0x19,0x01
                                ; AmpelTag schaltung ( 1..6 Werte und Zeiten)
         .CSEG
.org     0x0000                 ; Start
         rjmp ERAMlesen         ; Kopier ERAM ins SRAM
         reti
         reti
         reti
         rjmp TIM1_COMPA 
         reti
         reti
         reti
         reti
         reti
         reti
         reti
         reti
         reti
         reti
         reti

ERAMlesen:
; ldi Temp1, high(ramend)       ; letze Adr im SRAM
; out sph,temp1                 ; Stapel einrichten
         ldi temp1,low(ramend)
         out spl, temp1
         ldi Trafficlight, 0x3f ; Setze Maske Ausgangsports
         out DDRD, Trafficlight ; Setze Ausgangsports
         sbic EECR,0
         rjmp ERAMlesen
         LDI ZH, HIGH(0x0000)
         LDI ZL, Low(0x0000)
         LDI XH, high(0x0060)   ; Zeiger auf SRAM
         LDI XL, Low(0x0060)  

         OUT EEARL,ZL
         SBI EECR,0 
         IN Timer1,EEDR
ERAMlesenLoop1:                 ; Werte aus ERAM holen und im SRAM Speichern
         adiW ZL,1
         OUT EEARL,ZL
         SBI EECR,0
         IN Temp1,EEDR
         ST X+, Temp1
         DEC Timer1
         BRNE ERAMlesenLoop1
;---------------
         ldi Temp1, Low(Timerwert) ; Timer vorbelegen
         out OCR1AL,Temp1
         ldi Temp1, High(Timerwert)
         out OCR1AH,Temp1
         ldi Temp1,0x0c         ; Prescaller 
         out TCCR1B,Temp1
         ldi temp1,0x50         ; Interupt Comp
         out TIMSK,Temp1   
         sei
AmpelInit:
         rcall AmpelTag
         rcall AmpelTagLoop1
         rjmp DoNothing
AmpelTag:
         LDI XH, high(RAM_Ampel); Zeiger auf RAM_Ampel
         LDI XL, Low(RAM_Ampel)
         LD Timer1, X+          ; Anzahl der Werte holen
         ret
AmpelTagloop1:
         LD Trafficlight, X+    ; Ampelwert holen
         out PORTD, Trafficlight
         LD Timer2, X+          ; Zeitspanne holen
         DEC Timer1             ; Zähler der noch zu holenden Werte
         ret
;------------------
TIM1_COMPA:
         in Temp1,Sreg          ; SREG retten
         push Temp1
         Dec Timer2             ; Zeitzähler verringern
         cpse Timer2,Null
         rjmp TIM1_COMPA_Exit   ; wenn Timer2 <>0
         mov Temp1,timer1       ; merken
         cpse Timer1,Null
         rcall AmpelTagLoop1    ; wenn Timer2=0 und Timer1 <>0
         cpse Temp1,Null
         rjmp TIM1_COMPA_Exit
         rcall AmpelTag         ; wenn Timer2=Timer1=0
         rcall AmpelTagLoop1

TIM1_COMPA_Exit:
         pop Temp1              ; SREG setzen
         out SREG,Temp1
         reti

DoNothing:
         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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi @ Läubi

>>Außerdem erscheint "ERAMlesen" etwas wirr. Was genau willst du da
machen?
ERAMlesen:
         sbic EECR,0            ; OK laut Datenblatt sbic EECR,EEPE 
         rjmp ERAMlesen
         LDI ZH, HIGH(0x0000)   ; Zeiger für ERAM für Tiny reicht ZL
         LDI ZL, Low(0x0000)
         LDI XH, high(0x0060)   ; Zeiger auf SRAM
         LDI XL, Low(0x0060)  

         OUT EEARL,ZL           ; Setzen der Speicheradr.
         SBI EECR,0             ; hat glaube ich was mit INT zu tun? 
                                ; Datenblatt : SBI EECR, EEPE
         IN Timer1,EEDR         ; Timer1 enthält die Anzahl der Werte die 
                                ; übertragen werden sollen
ERAMlesenLoop1:                 ; Werte aus ERAM lesen und SRAM speichern
         adiW ZL,1              ; ERAM Zeiger +1
         OUT EEARL,ZL           ; Speicheradr setzen
         SBI EECR,0         
         IN Temp1,EEDR          ; Wert lesen in Temp merken
         ST X+, Temp1           ; im SRAM speichern und zur nächsten Adr
         DEC Timer1             ; Anzahl der zu übertr. Werte -1
         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.

Autor: Falk Brunner (falk)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat gefunkt!
MFG
Ralf

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.