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.
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 ;-) 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.
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.
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.
"Mama, die Kinder sagen ich bin so dick" "Dann geh woanders spielen Kind, und da: iss noch eine Torte"
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
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.
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
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.
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
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
@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?
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.
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. :-)
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
> 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 :)
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)
wie gesagt, mit der internen clock spuckt er den string korrekt aus... externe nicht. das gibt mir jetzt irgendwie zu denken.
@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.
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
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)
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
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.
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).
andere sache... ".db" sollte man doch immer am anfang machen... habe das mal getestet... und siehe da. es geht auch ohne nops
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?
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
am besten vor der stack initialiesierung anfangen mit .cseq .db.... alle .db´s und dann sollte es funktionieren
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.
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.
mußt den start vielleicht verzögern damit die volle spannung am termometer ansteht.. könnte sich ja ein wenig verzögern wegen condensatoren.
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
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.
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. :-)
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.
"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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.