Forum: Mikrocontroller und Digitale Elektronik Warum kann der Murks nicht einfach funzen?


von Zotteljedi (Gast)


Lesenswert?

Ich bin immer noch an meinem Thermometer für die serielle Schnittstelle,
mit DS18S20. Inzwischen wurde hier ja ein Assembler-Listing angegeben,
mit dem es auf einem anderen Controller gehen soll. Das wollte ich
heute entsprechend umwandeln.

Tja, ich habe jetzt eine tolle Entdeckung gemacht. Hier von ungefähr,
worum es geht:

...
Initialisierung von UART und Stack
...
Ausgabe von "MARK\r\n"
...
stop: rjmp stop
...
...
nop
nop
nop
rjmp stop

Wohlgemerkt: der untere Teil wird nie erreicht, weil ja weiter oben
eine leere Endlosschleife ist. Tja, wenn die nops unten drin sind, in
einer Codestelle die nie erreicht wird, wird "MARK\r\n" richtig
ausgegeben, wenn ich sie wegnehme, dann kommt MA, gefolgt von einem
Blank, gefolgt von einem o mit Dach drauf, gefolgt von einem
griechischen Buchstaben. Große Klasse!

Nein, ich verwende keinerlei Adressen, die fest codiert sind und nicht
mehr stimmen, wenn Code zwischendrin dazukommt. Langsam geht mir der
Mist gewaltig auf den Sack, ich probier jetzt noch den anderen ATMega8
aus, falls der jetzt verbaute einen Schlag abgekommen haben sollte,
aber dafür ist der Mist viel zu reproduzierbar.

Hat jemand von euch schonmal so'n Mist erlebt? Was soll denn bei so
ein bisschen involvierter Gülle schief gehen? Die Schaltung wird nicht
verändert, es kommen nur nops in never reached code dazu... ARGH! Alles
was über logischen Gattern kommt ist wohl bereits so komplex, daß
Murphy's Law für in Silizium geätzte Heimtücke in vollem Umfang
zutrifft.

von justme (Gast)


Lesenswert?

kann es sein das der sensor voll über einen interuppt läuft und deswegen
kein wirklicher code in der haupschleife ist??

von Zotteljedi (Gast)


Lesenswert?

Nein. Das wüsste ich ;-)

Die Hauptschleife ist ja deshalb leer, weil ich den Code minimieren
will, um erstmal das Ausgeben der Zeichenkette hinzukriegen - wenn das
nicht geht, kann ich mir den Rest ja gerade mal sparen.

von Fritz Ganter (Gast)


Lesenswert?

Du solltest nie in einer IR auf LCD ausgeben, es sei denn, sie wird
wirklich selten aufgerufen. Es dauert viel zu lange und die Gefahr ist
gross dass ein neuer Interrupt kommt bevor die IR zu Ende ist.

Normalerweise setzt man in der IR nur ein Flag, z.B.

stoptext=1;

und in der Hauptschleife dann:

if (stoptext)
 lcd_puts("....");

Wennst ein Oszi hast, dann schalt am Anfang in der IR ein Pin auf High,
am Schluss auf Low, dann siehst du wieviel die IR von der
Gesamtrechenzeit braucht.

von Zotteljedi (Gast)


Lesenswert?

Ok, ihr habt recht, ich sollte hier nicht fragen. Ich frage in einem
Forum, in dem die Antworten mit den Fragen zu tun haben. Trotzdem
danke.

von Fritz Ganter (Gast)


Lesenswert?

"Mama, die Kinder sagen ich bin so dick"
"Dann geh woanders spielen Kind, und da: iss noch eine Torte"

von justme (Gast)


Lesenswert?

wie du meinst, aber ich finde deine Problembeschreibung etwas
bescheiden. Du gibts ein nicht vollständiges Listing und erklärst warum
es nicht funktioniert... oder so halb. Alles in allem hast du ja nur
Ausgabe von "MARK\r\n"
...
stop: rjmp stop

gepostet... daß das keinen Sinn ergibt sollte dir doch auch klar sein.
Vielleicht solltest du mal erklären was der code mit deiner Frage zur
DS18S20 zu tun hat. erkennbar ist da nichts. In diesem Sinne

von Zotteljedi (Gast)


Lesenswert?

Könnte ja sein, daß andere das Problem "Aus heiterem Himmel klappt das
Senden über den UART nicht mehr" kennen. Aber in einem Text, in dem
von LCD nicht die Rede ist, und ausdrücklich gesagt wird, daß keine
Interrupts zum Zuge kommen, dann Tipps für LCDs zu geben... super.

http://www.zotteljedi.de/tmp/nops_aendern_funktion.asm

Die meisten Kommentare stammen noch aus dem Original, sind also
stellenweise nicht mehr zutreffend (insbesondere was Port D angeht).
Interessante Stellen: an Zeile 56 sollte meines Verständnisses nach
nichts dran vorbei kommen:

    56  stop: rjmp stop

aber die NOPs in den Zeilen

    79  nop
    80  nop
    81  nop

ändern die Funktionsweise.

Ich hoffe, daß alle Leute die sehen, daß der Stack zwei mal
initialisiert wird etc. pp., auch sehen, daß dieser Code nie erreicht
wird, bevor es hier weitere hilfreiche Tipps gibt.

Die Funktionen debug_mark und print-Blabla haben in anderen Programmen
schon einwandfrei funktioniert.

Aber einen Tipp, um den Gepflogenheiten des Forums in puncto
Zusammenhang entgegenzukommen, für alle Leute, die mit Transistoren und
Lochrasterplatinen arbeiten: wenn man Alufolie über den Auflauf legt,
dann verbrennt die Kruste nicht so schnell.

von justme (Gast)


Lesenswert?

guck mal in die senden funktion.

du initialisierts uartB und wartest auf ready von uartb
print_byte:
  sbis  ucsra!!!!   (das müßte doch dann auch b sein oder??), udre  ;
warten bis bereit
  rjmp  print_byte
  out  udr, r16  ; Byte senden
  ret

von justme (Gast)


Lesenswert?

du wartest auf ready von uarta meine ich... sorry

von justme (Gast)


Lesenswert?

sorry nochmal... hab wohl irgendwie blech erzählt.

von Zotteljedi (Gast)


Lesenswert?

Darauf hatte ich noch gar keinen Gedanken verschwendet, denn ich habe
auf http://www.mikrocontroller.net/tutorial/uart.htm gefunden:

[...]
        sbi UCSRB,TXEN                    ; TX aktivieren
[...]
serout:
        sbis UCSRA,UDRE                   ; Warten bis UDR für das
nächste
                                          ; Byte bereit ist
        rjmp serout
        out UDR, temp
        ret                               ; zurück zum Hauptprogramm

Ich ging implizit davon aus, daß es nur ein UART gibt und das
verschiedene Kontroll-Register dafür sind. Ich meine: ein Fehler im
Tutorial, das hätte doch längst jemand bemerkt? Ich schau gleich mal
ins Datenblatt vom ATMega8 rein.

Das würde natürlich erklären, warum Schrott ankommt, aber noch nicht,
warum die Menge des Codes das Timingverhalten ändert. Wenn man
allerdings schon bei undefined behaviour ist... hmm.

von justme (Gast)


Lesenswert?

hat nur einen... kommt bei dir gar nix an??
hab das mal auf m32 gebraten... kommt was an, aber defintiv nicht
"mark"... also "03" kommt bei mir auf dem terminal

von justme (Gast)


Lesenswert?

03 dez

insgesamt kommen 12 bytes an.
ich nehme mal an das dein m8 mit 4 mhz läuft, oder?
hatte auch mal so ein merkwürdiges ding, daß auf 16 mhz nichts kam aber
8 mhz ging. also die baudrate war bei beiden versionen eigentlich
richtig gesetz, aber trotzdem hat 16 mhz nicht funktioniert

von Fritz Ganter (Gast)


Lesenswert?

@Zoddeljedi

Wo sagst du dass du keine Interrupts verwendest?

Wenn du schon so einen Mist an Information lieferst, dann musst du auch
mit Mist als Antwort rechnen.

Schlag gefälligst einen anderen Ton an, wenn du Hilfe brauchst.

Vielleicht hab ich dein Posting nicht lange genug durch die Glaskugel
betrachtet, vor allem deinen tollen und vollständigen Code.

Dann fängt man schon mal an herumzuraten. Wieso schreibst du eigentlich
noch hier? Wolltest du nicht in ein anderes Forum gehen?

von Zotteljedi (Gast)


Lesenswert?

Wie gesagt, wenn die NOPs drin sind, dann kommt wie geplant
"MURKS\r\n" an, wenn sie nicht drin sind, dann krieg ich "MU"
noch, dann ein Leerzeichen, dann zwei Zeichen > 127, die sich in meinem
Terminal-Programm (Tera Term) als o mit Dach und einen griechischen
Buchstaben darstellen.

Paradoxerweise hat auch ein altes Programm, bei dem ich das Problem
bisher nicht beobachtet hatte, auch etwas gesponnen. Seit dem habe ich
aber an der Hardware nichts verändert, und softwaremäßig auf dem PC
nichts Relevantes. Ich werde wohl nicht drumherum kommen es auf den
Hallo-Welt-Fall zu reduzieren, und dann etwas Stresstest zu betreiben.

Es kommt mir nur so schrecklich albern vor, daß nichtausgeführte NOPs
einen Einfluß darauf haben, ob es fehlerfrei übertragen wird oder
nicht.

von Zotteljedi (Gast)


Lesenswert?

Natürlich MARK\r\n, ich glaube ich kämpfe schon zu lange damit, daß
ich schon gleich MURKS damit assoziiere ;-)

Und @Fritz:

> Wo sagst du dass du keine Interrupts verwendest?

Das können geübte Leser aus

>> kann es sein das der sensor voll über einen interuppt läuft und
deswegen
>> kein wirklicher code in der haupschleife ist??
> Nein. Das wüsste ich ;-)

ableiten. Richtig, im ersten Posting war es nicht drin. Aber man kann
davon ausgehen, daß ein Posting von 23:11 Uhr bereits Bezug auf eins
von 21:23 Uhr nimmt. Kann man doch? Kann man nicht?

Ich schreibe übrigens noch hier, weil man auf mein Posting geantwortet
hat und dieses Reply wiederum eine Antwort erwartet hatte. Ich halte es
für unfreundlich inmitten einer Diskussion wegzugehen, wenn man mit mir
spricht. Du doch auch? Hoffe ich zumindest. :-)

von justme (Gast)


Lesenswert?

sehr interessant... externer quarz kommt der mist... also 12 bytes
schrott... interne clock... was kommt?? "MARK"

das find ich jetzt aber seltsam. dachte das die externen genauer sein
sollen. Probier auch mal die intere clock aus. vielleicht ist es ja das
schon gewesen

von Zotteljedi (Gast)


Lesenswert?

> ich nehme mal an das dein m8 mit 4 mhz läuft, oder?

Richtig vermutet.

> hatte auch mal so ein merkwürdiges ding, daß auf 16 mhz nichts kam
> aber 8 mhz ging. also die baudrate war bei beiden versionen
> eigentlich richtig gesetz, aber trotzdem hat 16 mhz nicht
> funktioniert

Ich habe bisher auch nichts anderes als 4 MHz probiert (wie gesagt, die
Kommentare sind irreführend, weil der Code ja so heiß erwünscht war,
daß ich ihn noch nicht überarbeitet hatte), und die Codeteile die ich
hinzugefügt hatte, waren in anderen Programmen auf der gleichen
Hardware mit gleichen Parametern getestet und für funktionierend
befunden.

Das einzige das also dabei fehlschlagen könnte, ist der ganze
1-Wire-Krams der völlig irrelevant sein sollte, da er nicht zur
Ausführung kommt. Da hatte ich auch die Timing-Loops nur grob angepasst
und nicht vollends neu getestet, da hierzu es meistens hilfreich ist,
wenn das Programm wenigstens einen String zum sich Bemerkbarmachen
ausspucken kann. Blind debuggen macht auf den wenigsten Plattformen
Spaß, jedenfalls auf Assembler-Ebene :)

von Zotteljedi (Gast)


Lesenswert?

nochmal @Fritz:

Bei näherem Hinsehen hast Du natürlich recht, es ist manchmal hilfreich
alle Umstände anzugeben. Ich habe bisher immer nur die Parameter und
Umstände angegeben, die vom Normalfall abweichen (also hätte ich
angegeben, daß ich Interrupts verwende, wenn das der Fall gewesen
wäre), da sonst die Informationsmenge überhand nimmt. Im Usenet
schreien auch immer alle herum, wenn man sein Problem nicht auf das
Nötigste kürzt. Ich weiß, hier ist nicht das Usenet.

Falls es also noch was zur Sache tut, auch wenn es meiner Auffassung
nach "standard" ist, hier weitere Details:

ATMega8, Fuses nach Tutorial konfiguriert
läuft mit 4 MHz
DS18S20 hängt an PortB 0, ist über 4,7K nach +5 VDC gezogen
Kommunikation zum PC übernimmt MAX 232 N
selbiger ist mit 5 mal 22 uF beschaltet

Schaltung entspricht sonst weitestgehend dem Tutorial (was
Spannungserzeugung usw. angeht, inklusive der Verpopelung der
RS-232-Strippen)

von justme (Gast)


Lesenswert?

wie gesagt, mit der internen clock spuckt er den string korrekt aus...
externe nicht. das gibt mir jetzt irgendwie zu denken.

von Zotteljedi (Gast)


Lesenswert?

@justme

Ich glaube wir missverstehen uns. Es kommen nicht 12 Byte Schrott,
sondern "MU xx", sind bei mir 5 Byte, mit 3 Byte Schrott, CRLF wird
auch nicht angehängt, bei der richtigen Zeichenkette jedoch schon
(wie's im Source ja steht). Clock ist immer externer Quarz @4 MHz,
das einzige das zwischen Mist und nicht Mist entscheidet sind die drei
benannten NOPs im Code der nicht ausgeführt wird, weil davor die
Endlosschleife sitzt. Das ist ja der Grund meiner Verzweiflung.

von justme (Gast)


Lesenswert?

da die ausgabe vom string bei mir ohne probleme (auf stk500) läuft...
scheint es sich doch um ein hardware-problem zu handeln. ich könnte das
auch nochmal mit nem anderen controller testen, aber ich denke es wird
dort auch funktionieren

von Zotteljedi (Gast)


Lesenswert?

Das deckt sich insofern mit meiner Erwartung, als daß Code der schonmal
ging spinnt. Die nächste Frage ist, was einem ATMega8 schlimmes
zustoßen kann. Er liegt jetzt seit etwa 2 Monaten ungenutzt in der
Schaltung herum (Steckbrett von Conrad), ist weder irgendwelchen
thermischen noch mechanischen Belastungen ausgesetzt, hat nur eine
leichte Staubschicht angesetzt.

Ich habe jetzt den anderen ATMega8 gefunden, und werde mit dem
weiterprobieren.

(Totgeflasht kann ich ihn eigentlich auch noch nicht haben, aber ich
sollte nicht verschweigen, daß der schon etwa 600-800 mal abbekommen
hat, da er mangels gescheiten Simulators mein Haupttestobjekt
darstellt)

von justme (Gast)


Lesenswert?

ahhh... verdammt jetzt sehe ich es auch... hat aber mal wieder etwas
lange gedauert...
ich würde jetzt aber vermuten daß dieses ´merkwürdigkeit doch mit der
adressierung zusammanenhängt.

vielleicht steht der string sonst an einer "komsichen" stelle im ROM
irgendwie entsinne ich mich, daß das rom in doppel-wörtern organisiert
war. so ist es dann vielleicht erforderlich die nops einzufügen damit
die tabebelle auch in die speicherorganisation paßt.
soll heißen: lösch die nop´s und mach an die stelle mal was anderes was
exakt 3 wörter braucht

von Zotteljedi (Gast)


Lesenswert?

Das hatte ich bisher nur im dem Ende des Strings beobachtet, da hat mich
der Assembler mit einem Warning drauf aufmerksam gemacht. Wäre ja
affig, wenn er das mit dem Anfang des Strings nicht täte.

Dieser These zufolge würde es bei ungerader Anzahl von NOPs klappen,
und bei gerader nicht. Das lässt sich ja schnell testen...

[rumtest]

Ok, neue Erkenntnis. Wir sind uns noch alle einig, daß diese Stelle im
Code nie erreicht wird, und der Sprung dahinter daher auch irrelevant
ist?

3 NOP, Sprung -> geht
2 NOP, Sprung -> geht
1 NOP, Sprung -> geht nicht
1 NOP -> geht nicht
Sprung -> geht nicht
2 NOP -> geht

damit hätten wir alle möglichen Verschiebungen an Bytegrenzen
durchgespielt, würde ich sagen.

von Fritz Ganter (Gast)


Lesenswert?

Das merkwürdige ist halt, dass man normalerweise den internen
RC-Oszillator nicht als Zeitbasis für den UART nehmen kann, weil er
eben ungenau ist und keine Frequenzkonstanz hat.
Laut Datenblatt passt ein 4MHz Quarz auch für 9600 Baud.

Kannst einen anderen Quarz probieren? (Was allerdings noch immer nicht
das 3-NOP-Phänomen klärt).

von justme (Gast)


Lesenswert?

andere sache... ".db" sollte man doch immer am anfang machen... habe
das mal getestet... und siehe da. es geht auch ohne nops

von Zotteljedi (Gast)


Lesenswert?

Damit funktioniert es bei mir auch. Umso komischer, daß ich das Problem
früher nie hatte. Ich hatte die Debug-Funktionen in einer extra-Datei
die per .include dazugemanscht wurde, und es hat immer geklappt.

Ich bin jetzt nicht ganz firm wie das mit dem Einfügen von
Zeichenketten am Anfang aussieht - der Assembler bekommt ja auch keine
Information über einen Entry-Point. Muß ich irgendwie dafür sorgen, daß
die Zeichenkette übersprungen wird (sprich: fängt die Ausführung beim
ersten Byte an, oder sortiert der Assembler es doch für mich richtig in
Textsegment und Datensegment, was er ja eigentlich gar nicht können
dürfte, da er keine Informationen diesbezüglich erhält)?

Bei der Verwendung von Interrupts muß ja auch der Vektor für Reset mit
einem Sprung auf den Entry-Point versehen werden, oder ist das eine
ganz andere Baustelle?

von justme (Gast)


Lesenswert?

es geht auch mit 1 nop und hat anscheinend wirklich was mit der
speicherorganisation vom avr zu tun. also es scheint probleme zu geben
wenn die tabelle auf einer ungeraden speicheradresse beginnt.

speicher in doppelwörtern:

0x???? w1.w2 geht

in diesem fall war es dann wohl aber

0x???? ??.w1
0x???? w2.??

für den avr ist dann anscheinen so ein doppelwort eine zeile im
speicher. da der string genau 1 doppelwort lang ist und er auch 1 dw
ließt ist es für den avr korrekt, obwohl es nur mist ist was er liest.
vermutlich würde es auch funktionieren wenn man den string noch läger
macht.. also um 1 wort verlängern um ihn in die nächste speicherzelle
(a 2 wörter) zu zwingen

von justme (Gast)


Lesenswert?

am besten vor der stack initialiesierung anfangen mit

.cseq
.db....

alle .db´s und dann sollte es funktionieren

von Zotteljedi (Gast)


Lesenswert?

So, jetzt klappt es. Er gibt mir sogar halbwegs vernünftige Temperaturen
aus.

Nur ein Problem noch: wenn ich das Ding von yaap aus Resette, stimmt
das Ergebnis. Wenn ich Strom aus, Strom an mache, stimmt es nicht.

Sollte das nicht einen sauberen Reset bewirken? Oder legt er irgendwo
los, wenn er Strom bekommt? Naja, da komme ich noch dahinter. Erstmal
vielen Dank für die Hilfe, das mit dem .db am Anfang hat's gebracht.

von justme (Gast)


Lesenswert?

aber vergessen solltest du das problem nicht, weil wenn das programm
länger wird, dann funzt das bestimmt auch irgendwann nicht mehr, weil
die jmps in der reichweite beschränkt sind. glaube man kann nur 4 k
weit springen. keine ahnung ob das dann probleme macht, wenn z.B. das
programm fertig 6 k sind und die .db am anfang steht.

von justme (Gast)


Lesenswert?

mußt den start vielleicht verzögern damit die volle spannung am
termometer ansteht.. könnte sich ja ein wenig verzögern wegen
condensatoren.

von Peter D. (peda)


Lesenswert?

Da muß ich den anderen Recht gegen, mit dem Codeschnipsel ganz oben
brauchts wirklich ne Glaskugel um Dir zu helfen.

Deshalb solltest Du nicht so ungehalten reagieren, wenn diese nur im
Nebel rumstochern können. Du bist ja dran schuld, nicht sie.


Nach Murphys Gesetzt liegt der Fehler nämlich nie da, wo man ihn
vermutet, sondern immer dort, wo man sich absolut sicher ist.
Z.B. Code, der schon 100-mal funktioniert hat, ist ein guter Kandidat
dafür:


inc  ZL    ; Z-Pointer eins weiter

Das ist falsch !

Damit ist nur ZL eins weiter.
Richtig:

adiw zh:zl, 1



Peter

von Dirk (Gast)


Lesenswert?

Ich wollte noch sagen, dass die Geschichte mit der anfänglich richtigen
Zeichenkette ein "Frame-Error" ist. Wenn der Sender und Empfänger die
Kommunikation nicht über Hardware-Handshake machen, wird sich über kurz
oder lang die gesendete Bitfolge um ein Bit verschieben... Irgenwann um
zwei Bits, und so weiter. Probier' mal eine wirklich lange
Kommunikation; um sicher zu gehen, dass das Handshake richtig
funktioniert - solltest wenigstens ein Software-Handshake machen, oder
mit Prüfsumme arbeiten, wenn Du auf Hardware-Handshake verzichtest.

Viel Erfolg!
Dirk.

von Zotteljedi (Gast)


Lesenswert?

Inzwischen habe ich die Schaltung auf eine Platine gebraten (etwa 3 1/2
Stunden lang g), Kabel durch den Keller gezogen und den
Temperatur-Sensor im Garten angebracht. Da im Keller ein Rechner den
Router spielt und rund um die Uhr an ist, hat der jetzt gleich die
Auswertung aufs Auge gedrückt bekommen. Werde in den nächsten Tagen
noch ein Programm basteln, das daraus lustige Graphen zaubert, falls es
da nicht schon was brauchbares gibt. Bisher spuckt es auf TCP-Port 1273
von zotteljedi.ath.cx die aktuelle Temperatur im Garten aus.

Bin noch am Überlegen ob Celsius oder Kelvin, letzteres wäre irgendwie
hypscher, zumal man es leichter weiterverwerten kann (z.B. in unsigned
speichern).

Wie's über längere Zeit mit der Verbindung aussieht werde ich ja
sehen, aber bei 9600 Baud sollte ja nicht sooo viel in die Hose gehen,
wenn es einmal richtig läuft. Hab vorsichtshalber noch einen
Reset-Knopf drangelötet. :-)

von justme (Gast)


Lesenswert?

Framing Error?? es hatte doch gar nichts mit der seriellen übertragung
zu tun, oder wie erklärts du das es mit den nops gefunzt hat und ohne
nicht.

von Peter D. (peda)


Lesenswert?

"Framing Error??"

Wie wärs denn damit, die Beiträge erstmal zu lesen !!!

Also nochmal:

Die NOPs haben bewirkt, das die dahinter liegenden DB-Anweisungen
zufällig in einen Bereich verschoben wurden, wo der "inc  ZL" -
Fehler sich nicht auswirkt !!!

Nun alles klar ?


Peter

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.