Zählervergleich geht schief

Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte

Elektronik Forum Nicht eingeloggt       Einloggen       Registrieren




[Registrieren]      --     [FAQ]      --     [ Einen Link auf Ihrer Homepage zum Forum]      --     [ Themen kostenlos per RSS in ihre Homepage einbauen]      --     [Einloggen]

Suchen


Serverzeit: 07 10 2024  03:24:50      TV   VCR Aufnahme   TFT   CRT-Monitor   Netzteile   LED-FAQ   Osziloskop-Schirmbilder            


Elektronik- und Elektroforum Forum Index   >>   Microcontroller        Microcontroller : Hardware - Software - Ideen - Projekte

Gehe zu Seite ( 1 | 2 Nächste Seite )      


Autor
Zählervergleich geht schief

    







BID = 446864

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)
 

  


Hallo Leute, vor ca 2 Jahren habe ich ne Ansteuerung für einen modifizierten (darum soll es jetzt nicht gehen) Bildschirm gebaut, und war der Meinung dass es erfolgreich war, schließlich funktionierte es wie gewünscht, bis der Bildschirm seinen Geist aufgab.
Nachdem ich die Schaltung nun mit einem anderen Bildschirm in Betrieb nehmen wollte stellte ich nach einigem Messen fest, dass ich im Programm erstens zwei Pins vertauscht habe (bereits korrigiert und getestet) und ein Pin nicht macht was er soll.
Und bei Letzterem komm ich einfach nicht weiter. Nachdem ich durch meine spärliche Kommentierung durchgestiegen bin, das Programm nun wieder verstanden , und ordentlich auskommentiert habe nun also meine Frage zu diesem Code-Abschnitt:


Code :

;-------Warteschleife----------------------------------------- 


;die Warteschleife beendet wenn nötig den Vsync-Impuls

;und leitet bei entsprechendem Zählerstand die anstehende

;Aussteuerungskombination ein

Wait:

ldi temp2H, high(5) ;-

ldi temp2L, low(5) ;-

cpse countL, temp2L ;-
rjmp Weiter ;-
cpse countH, temp2H ;5 Zeilen um?

rjmp Weiter ;Nein

cbi PinA, 0 ;Ja!-> Vsync aus

Weiter:

ldi temp2H, high(480) ;-

ldi temp2L, low(480) ;-

cpse countH, temp2H ;-

rjmp loop ;-

cpse countL, temp2L ;"Bild" fertig?

rjmp loop ;Nein-> auf HSync-Interrupt warten gehen

clr countH ;Ja!-> Zeilen-Zähler zurückstellen (high)

clr countL ;Zeilen-Zähler zurückstellen (low)

ret ;Zurück in die Hauptroutine, und nächste Kombination ausgeben

loop:

rjmp loop ;warten auf den Interrupt


Die erste Zähler-Abfrage scheint nie "true" auszugeben, denn Vsync (PinA0) wird nie "low"
Die zweite Zählerabfrage ("Bild fertig") funktioniert aber, denn der Rest des Programmes läuft tadellos ab.
Das kapier ich nicht, schließlich sind die Abfragen (bis auf die Zahlen) identisch.
Findet jemand den Bock?
Der Controller ist ein tiny26 und die Taktfrequenz beträgt 2MHz.
Das komplette Programm ist im Anhang


_________________
Es irrt der Mensch solang er strebt

[ Diese Nachricht wurde geändert von: Morgoth am 30 Jul 2007 21:02 ]

BID = 446869

Jornbyte

Moderator



Beiträge: 7151

 

  

Ich finde einfach kein "inc countL /countH" in der kurzen Schleife.
Für das gesammte Proggi fehlt mir heute der Nerv...

_________________
mfg Jornbyte

Es handelt sich bei dem Tipp nicht um eine Rechtsverbindliche Auskunft und
wer Tippfehler findet, kann sie behalten.

BID = 446871

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)

Klar ist da kein "inc", denn gezählt wird woanders, hier wird nur verglichen...
Das Zählen findet in diesem Programmabschnitt statt:


Code :

;-------Horizontal-Interrupt----------------------------------  


;der Horizontal Interrupt betätigt die H-syncronisation und

;setzt den Zähler für die Warteschleife hoch und entrümpelt

;den Stack

HInt:

ldi temp, 0x03 ;

out TCNT1, temp ;Interrupt-Counter korrigieren/"zurücksetzen"

cbi PortA, 1 ;Hsync aus

ldi temp2H, 0 ;

ldi temp2L, 1 ;

add countL, temp2L ;Zeilen-Zähler eins hochsetzen (low)

adc countH, temp2H ;Carry-Flag weitertragen sofern vorhanden

sbi PortA, 1 ;Hsync wieder an

pop r10 ;Stack entrümpeln (unerwünschte Sprungmarke abtragen)

pop r10 ;Stack entrümpeln (unerwünschte Sprungmarke abtragen)

sei ;Interrupt wieder einschalten

rjmp Wait ;In die "Warteschleife", Zähler auslesen


Zugegeben, man kann auch einfacher zählen...

_________________
Es irrt der Mensch solang er strebt

BID = 446872

Jornbyte

Moderator



Beiträge: 7151

Nun ja, beim Interrupt biste mutig. Ab pop r10 (was im ersten Durchlauf ja noch gehen mag) versaust du dir die Register.
Überdenke das nochmal.

_________________
mfg Jornbyte

Es handelt sich bei dem Tipp nicht um eine Rechtsverbindliche Auskunft und
wer Tippfehler findet, kann sie behalten.

BID = 446874

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)

Das ist Absicht, da sind Sprungmarken gespeichert, die ich nicht haben will, und zwar jedesmal 2 Stück (eine davon ist vom Interrupt selbst). Wenn ich die nicht runterschaufele (R10 ist da quasi mein Mülleimer), dann geht das "ret" in dem anderen Abschnitt nicht dorthin wo es soll, und meine Routine bricht zusammen.
Wie gesagt alle andern Pins machen was sie sollen, und 5 davon könnten das niemals machen, ohne dass das Programm an sich funktioniert.

_________________
Es irrt der Mensch solang er strebt

BID = 446878

Jornbyte

Moderator



Beiträge: 7151

Das Programm, so kurz es auch sein mag, ist im Desing fehlerbehaftet.
Mach einen sauberen Int mit reti. Lasse das mal durch den Debugger laufen. Dauert seine Zeit, mit Haltepunkten gehtst aber schneller.

_________________
mfg Jornbyte

Es handelt sich bei dem Tipp nicht um eine Rechtsverbindliche Auskunft und
wer Tippfehler findet, kann sie behalten.

BID = 446887

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)

Ja, das kann sein...
Werde mir das morgen mal vorknöpfen.
Dann muss ich eben für die Bildschirmausgaben auch noch einen Zähler bauen, damit er richtig landet.
Ich muss halt aufpassen, dass ich mit den "lebenswichtigen" Dingen immer unter 64 Taktzyklen bleibe.

PS: das war mein zweites Assembler-Programm...

Danke für die Tipps!

_________________
Es irrt der Mensch solang er strebt

BID = 446898

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Moin,

Ja, die Sachen sind mir auch aufgefallen:

* während einer ISR kann zwar eine IRQ-Flagge gesetzt werden, aber normalerweise keine erneute ISR aufgerufen werden; es sei denn in der ISR wird die I-Flagge gesetzt (z.b. mit sei).
Das reti setzt die Interruptflagge wieder und somit können erneut ISRs ausgeführt werden.
-> Beende die ISR ordentlich mit reti und entferne cli und sei wieder. Dazu muss natürlich das Programm abgeändert werden.
* Wenn man sich entscheidet, IRQs zuzulassen (also irgendwo die I-Flagge setzt), dann sollte man alle Interruptvektoren auch am Start (angefangen bei 0x0000 PC) auflisten, und jene, die nicht benötigt werden einfach mit reti füllen. Das kostet zwar ein bischen Platzt, aber das Progamm wird nicht unkontrollierbar, wenn, aus welchen Gründen auch immer, ein IRQ auftritt und an den entsprechende Interruptvektor gehoppst wird.
* (Schönheit und Verständnis: besser, man vermeidet 0b100 (also Dualzahlen) gänzlich, man kann nämlich, da sie definiert wurden, auch direkt die Bitbezeichner wie PORTB3, TWIE oder RXEN benutzen, indem man an die entsprechende Bitposition eine 1 oder 0 schiebt (wobei 0 nur dann Sinn macht, um explizit mitzuteilen, dass ein Bit 0 sein soll, normalerweise sind alle Bits 0 wenn sie nicht auf 1 gesetzt werden...... ihr wisst, was ich nicht meine ...):

ldi r16, 1<<RXEN
Somit weiß man sofort, was gemeint ist )

Sonst habe ich auch wenig Lust, das komplette Programm zu verstehen , aber Respekt nochmal von mir, für das zweite ASM-Programm ist das schon sehr sehr gut .
(vorallem, weil du heute weiter bist, und alles, was ich oben geschrieben habe, selbst weißt ...)

_________________

BID = 446969

BjörnB

Stammposter

Beiträge: 242
Wohnort: Dortmund

Hallo,

mir ist aufgefallen, dass Du von der Routine VRoutine aus die Routine Wait mit rcall aufrufst (Rücksprungadresse wird auf den Stack gelegt), von der Routine HInt aus aber zur Routine Wait mit rjmp springst (Rücksprungadresse wird nicht auf den Stack gelegt). Da Wait mit ret abschließt, erfolgt im letzten Fall ein Rücksprung an eine unklare Speicherstelle.

Ich würde dir empfehlen, Funktionsaufrufe grundsätzlich mit rcall/call zu machen und nicht manuell den Stack zu verändern, außer, um Register durch push/pop zu sichern. Bei letzterem immer darauf achten, dass push und pop zahlenmäßig ausgeglichen sind und am Anfang und Ende einer Routine spiegelbildlich sind. Bei Routineaufrufen bitte auch nicht vergessen, das Statusregister mit zu sichern.

Wie mein Vorredner schon sagte, wird das ganze noch sauberer, wenn man auch bei Leer-Interrupts grundsätzlich ein reti an die entsprechenden Speicherstelle am Programmanfang setzt.

Zwar mag Dein Programm in diesem speziellen Fall funktionieren, doch sobald man vielleicht einige Erweiterungen einfügt, kann manches schief gehen, wenn das ursprüngliche Programm unsauberen Code enthält. In sich abgeschlossene Routinen mit klarer Definition lassen sich darüber hinaus dann auch direkt in neuen Programmen weiterverwenden, so dass man nicht jedes Mal das Rad neu zu erfinden braucht.

Schöne Grüße,
Björn

BID = 447184

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)

Danke für die zahlreiche Tipp, ich werde sie versuchen alle zu beherzigen (wobei ich keinen Grund sehe, nen Port nicht im "Klartext" umzustellen, wenn das erstens übersichtlicher ist, und zweitens schneller geht, weil ja mehrere Pins umgestellt werden)

Um euch mal ein paar Illusionen zu nehmen: Nach meinem zweiten Programm habe ich zwar noch einige µCs programmiert, aber aus den Umständen der letzten 2 Jahre heraus nicht mit selbst-geschriebenen Programmen... Erst im Moment komme ich wieder dazu Sachen selbst zu entwickeln.

_________________
Es irrt der Mensch solang er strebt

BID = 447194

BjörnB

Stammposter

Beiträge: 242
Wohnort: Dortmund

Hallo,

ich verwende sowohl Dualzahlen als auch Bitbezeichner, denn mal ist das Eine, mal das Andere praktischer. Beim Ansprechen externer Ports (z.B. 8 LEDs) ist die Verwendung von Dualzahlen vorteilhaft. Wenn ich Register (z.B. der USART) beschreibe, greife ich eher zu der von DonComi dargestellten Shiftoperation und verwende die in der Include-Datei des Mikrocontrollers definierten Bitbezeichner. So ist auf den ersten Blick ersichtlich, welche Optionen gesetzt wurden z.B. UCSRB = (1<<RXCIE)|(1<<RXEN) anstatt UCSRB = 0b10010000.

Ich wünsche noch viel Erfolg mit Deinem Projekt.

Schönen Gruß,
Björn

BID = 447349

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Moin,

wenn ich, egal ob C oder Assembler, externe Pins zuweisen möchte, dann so:

irgendein Header:

#define LED_NETZ PORTB4
#define LED_STATUS PORTB7
/
.equ LED_NETZ = PORTB4
.equ LED_STATUS = PORTB7
...

im Programm:

PORTB |= 1<<LED_NETZ; //LED geht an
PORTB &=~(1<<LED_NETZ); //LED geht aus, alle anderen Bits bleiben, wie sie waren
PORTB |= 1<<LED_NETZ|1<<LED_STATUS; //Beide LEDn anschalten

...

bzw. in AVR-ASM:
in wr, PORTB
ori wr, 1<<LED_NETZ|1<<LED_STATUS ;beie LEDn anschalten
out PORTB, wr

oder, wenns es eine LED oder allgemein was anderes ist:
sbi PORTB, LED_NETZ / cbi ...


Um das alles noch "universeller" zu machen, kann man auch noch den PORT definieren und fortan nur noch den Aliasnamen benutzen. Das macht bspw. Sinn bei LCD-Routinen, wo die Belegung ändert und man am Kode selbst nichts mehr ändern braucht.

OK, aber manchmal mache ich auch Klartext, z.b., wenn ein kompletter Port Ausgang ist:
ldi wr, 0xFF
out DDRx, wr

Da mache ich dann eben ohne den Shiftoperator, weil das viel zu lang wäre

_________________

BID = 447850

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)

So, habe das Programm mal umgebaut, ist jetzt alles ein bissel mehr gerade aus, und kein hin-und-her-Gehopse mehr.
Mit reti hab ich jetzt trotzdem nicht gearbeitet, weil das hier nicht nötig ist, da der Interrupt ja nicht die Ausnahme, sondern die Regel ist.
Leider kann ich es nicht simulieren weil "simulavr" keinen tiny26 simulieren kann.
Also werde ich es wohl morgen einfach brennen und ausprobieren müssen...

Ich glaube aber fast nicht, dass sich was an meinem Problem ändert, denn an der entscheidenden Stelle hat sich eigentlich nix getan.


_________________
Es irrt der Mensch solang er strebt

BID = 447963

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)

So, mit dem angehängten Code ist das Zählerproblem endlich erledigt. Allerdings gibt er jetzt wohl die Bilder zu schnell aus,
Jedenfalls kommen an den Farbpins und den Audiopins, wo normal bisher 12Hz rauskamen, und rauskommen sollten, jetzt 30Hz raus.

Immerhin fühlt sich der Monitor jetzt schonmal angesprochen, und das Programm ist übersichtlicher geworden.

edit: macht euch mal vorerst keine Mühe.
Mir ist gerade ein Denkfehler bewusst geworden...
Das Puls-Pausen-Verhältnis von Vsync ist so groß, dass ich die Frequenz nicht messen kann... aber auf meinem Oszi für arme sieht das stark nach deutlich mehr als 60Hz aus, daher nehme ich stark an, dass die auch viel zu hoch ist... folglich ist da doch noch ein kleiner Bug im Zähler


_________________
Es irrt der Mensch solang er strebt


[ Diese Nachricht wurde geändert von: Morgoth am  4 Aug 2007 16:56 ]

BID = 447981

Morgoth

Schreibmaschine



Beiträge: 2930
Wohnort: Rockenhausen (Pfalz)

Es waren die "inc"s,
Ich war der Annahme unterlegen,dass diese das Carry-Flag setzen können...
Nachdem ich nun das Z-Flag auslese funktioniert alles tadellos.
Bis auf den Monitor, der meint er müsste auch ohne Signal trotzdem schonmal alle Farben anzeigen. Da muss ich wohl Intern noch die Helligkeit runterregeln. (das liegt an dem umgebauten Monitor, ein anderer macht das nicht)

_________________
Es irrt der Mensch solang er strebt


      Nächste Seite
Gehe zu Seite ( 1 | 2 Nächste Seite )
Zurück zur Seite 1 im Unterforum          Vorheriges Thema Nächstes Thema 


Zum Ersatzteileshop


Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum       Datenschutz       Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland       

gerechnet auf die letzten 30 Tage haben wir 20 Beiträge im Durchschnitt pro Tag       heute wurden bisher 4 Beiträge verfasst
© x sparkkelsputz        Besucher : 182137450   Heute : 335    Gestern : 5489    Online : 504        7.10.2024    3:24
2 Besucher in den letzten 60 Sekunden        alle 30.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
xcvb ycvb
0.0702128410339