Hallo, um eine Frage gleich vorweg zu nehmen: Leider kann/darf ich das Programm nicht veröffentlichen, da ich es für meinen Arbeitgeber ist. Dennoch wäre ich um Hilfe dankbar. Prozessor: Atmega8 Compiler: GCC Programmiersprache: C Randaten: Atmega Flash-Speicher ist nach dem compilieren zu 80-<90% voll (also noch Luft) Atmega SRAM nach dem compilieren zu 12% voll. Auch während der Programmlaufzeit ändert sich der SRAM-Vebrauch nur geringfügig* *geprüft nach folgender Methode: http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc Sonst finde ich im Programm auch keine verschachtelten Funktionen. Arrays verwende ich im Programm nicht, außer einem im EEPROM. Diesen Programmteil/das Modul benutze ich aber in anderen Programmen fehlerfrei. Folgendes Problem: Zum Debuggen verwende ich ein LCD. Um auch hier die Frage vorweg zu nehmen: Strings sind per PROGMEM im Flash ausgelagert. Je mehr Zeilen bzw. Inhalt ich auf dem LCD ausgebe, desto mehr der Programmverbrauch im Flash (wegen PROGMEM). Ab einem gewissen Programmgröße (jedoch kleiner max. und SRAM bleibt unverändert), bekomme ich auf dem LCD nur wirre Zeichen angezeigt von den Strings und das Progarmm läuft nicht richtig. Kommentiere ich etwas andere Programmteile aus (nicht die LCD Ausgabe) und verringere damit die Programmgröße, funktioniert die Ausgabe einwandfrei und das Programm auch. Aber ich habe schon sukzessive verschiedene Stellen auskommentiert, um herauszufinden, ob es an irgendeiner bestimmten hakt, aber nein. Es ist scheinbar rein von der Größe abhängig. Das gleiche ist übrigens auch, wenn ich das LCD weglasse, dafür mehr Programmmodule mit hinzu nehme, um den Speicher so hoch zutreiben. Aber einem gewissen Punkt, läuft das Programm nicht zuverlässig und wie es soll. Das LCD macht das Problem eigentlich nur direkt „sichtbar“, wenn die Daten/Strings eben „wirr“ angezeigt werden. Nun stellt sich für mich die Frage, wo ich anfangen soll nach Fehler zu suchen oder wo Fehler sein könnten. Speicher ist nach dem compilieren zu keiner Zeit größer 90% und der SRAM wie oben geschrieben ca. 12%. Auch bei der Programmlaufzeit stelle ich keine großen SRAM Verbräuche fest. Danke an alle, die es lesen und sich Gedanken machen. VG Daniel
Bei diesen Effekten würde ich normalerweise zuerst am Probleme mit dem Stack denken, der am Ende des RAM sitzt. Dazu müsste das RAM aber fast voll sein oder der Stackbedarf sehr hoch (lokale Variablen in Funktionen). Zweite Möglichkeit: Murks bei Pointer-Operationen. Dritte Möglickeit: der Flash-Speicher hat Fehler. Anderen Atmega8 versuchen.
Erst einmal danke für die Antwort. ad 1) Dürfte ja durch die im roboternetz ausgeführte Variante von mir abgeprüft sein. Lokale Variablen habe ich nicht übermäßig, dass es ins Auge fallen würde. Globale volatile deklarierte sind es ein paar, da im Programm viele Interrupts vorkommen: - Timer1 OVF - Timer 1 CompA - Timer 1 CompB - Int0 - ICP ad 2) Pointer verwende ich im Programm explizit nicht, es sei denn, Sie sind durch vorhandene Bibliotheken eingebunden und werden implizit durch den Compiler angewandt. ad 3) Leider bereits auch schon versucht (habe die Schaltung hier 5x aufgebaut gelötet).
Daniel Mader schrieb: > Erst einmal danke für die Antwort. > > ad 1) > Dürfte ja durch die im roboternetz ausgeführte Variante von mir > abgeprüft sein. > Lokale Variablen habe ich nicht übermäßig, dass es ins Auge fallen > würde. Globale volatile deklarierte sind es ein paar, da im Programm > viele Interrupts vorkommen: > - Timer1 OVF > - Timer 1 CompA > - Timer 1 CompB > - Int0 > - ICP Beschreibst du jetzt allen ernstes in Prosa dein Programm, anstatt es zu posten? Zeig deinen Code.
cyblord ---- schrieb: > Beschreibst du jetzt allen ernstes in Prosa dein Programm, anstatt es zu > posten? Zeig deinen Code. einfach erst mal lesen? > Leider kann/darf ich das Programm > nicht veröffentlichen
schwer etwas zu sagen wenn von dem code so wenig bekannt ist, aber mal eine Idee. Vieleicht ist ja gar nicht der Speicher das Problem, sondern irgend welche Timings, die ab einer gewissen menge von eingebundenen Modulen nicht mehr eingehalten werden können.
Peter II schrieb: > cyblord ---- schrieb: >> Beschreibst du jetzt allen ernstes in Prosa dein Programm, anstatt es zu >> posten? Zeig deinen Code. > > einfach erst mal lesen? > >> Leider kann/darf ich das Programm >> nicht veröffentlichen Jo, aber ohne Code kann hier niemand helfen. So einfach ist das. Wie soll so ein diffuses problem, was sowohl aus einer winzigen Kleinigkeit resultieren könnte, als auch aus dem gesamten Konzept heraus, ohne Code gefunden werden? Alle wahrscheinlichen Ursachen (Stacküberlauf, wilde Pointer usw.) werden ja kategorisch ausgeschlossen.
:
Bearbeitet durch User
cyblord ---- schrieb: > Peter II schrieb:cyblord ---- schrieb:Beschreibst du jetzt allen ernstes > in Prosa dein Programm, anstatt es zu posten? Zeig deinen Code.einfach > erst mal lesen?Leider kann/darf ich das Programm nicht veröffentlichenJo > dann kann auch niemand helfen. So einfach ist das. NIEMAND nicht. Aber vllt. JEMAND ;-)
Titel für ein hermetisches Drama: Denkbare Möglichkeiten
Daniel Mader schrieb: > Kommentiere ich etwas andere Programmteile aus (nicht die LCD Ausgabe) > und verringere damit die Programmgröße, funktioniert die Ausgabe > einwandfrei und das Programm auch. Schreib diese Teile als Funktion und rufe sie mal auf und mal nicht. D.h. sie bleiben im Flash als toter Code.
wenn es wirklich nachvollziehbar ist, sollte man es doch auch debuggen können. Einfach schrittweise durchgehen und schauen was in den Variablen steht.
cyblord ---- schrieb: > Alle wahrscheinlichen Ursachen (Stacküberlauf, wilde Pointer usw.) > werden ja kategorisch ausgeschlossen. Es ist eben ein fehlerfreies Programm und mich wundert, dass noch niemand die Abblockkondensatoren moniert hat oder die Anschlußleitung zum LCD, die bestimmt länger als 2cm ist :-) Im Ernst: eine Woche lang liegen lassen, um noch einmal in Ruhe alles durchzutesten oder komplett neu schreiben, was bei klarer Zielsetzung und einem ATmega8 kein großes Problem sein sollte.
Daniel Mader schrieb: > Folgendes Problem: > Zum Debuggen verwende ich ein LCD. Um auch hier die Frage vorweg zu > nehmen: Strings sind per PROGMEM im Flash ausgelagert. Je mehr Zeilen > bzw. Inhalt ich auf dem LCD ausgebe, desto mehr der Programmverbrauch im > Flash (wegen PROGMEM). Ab einem gewissen Programmgröße (jedoch kleiner > max. und SRAM bleibt unverändert), bekomme ich auf dem LCD nur wirre > Zeichen angezeigt von den Strings Handelt es sich um einen µC mit mehr als 64kByte Flash? Dann ist das mit hoher Wahrscheinlichkeit die Ursache des Problems. Sobald eine Zeichenkette oder eine im flash abgelegte Tabelle oberhalb der 64k-Grenze zu liegen kommen, passiert Mist. Soweit ich weiß, ist das aber in neueren Versionen des avrgcc behoben, da braucht man dann auch dieses PROGMEM-Zeuchs nicht mehr. Überflüssig zu erwähnen, daß es in Assembler nie ein Problem dargestellt hat...
Durch Deine Interrupts und Dein sehr großes Programm verursachst Du Stack-Überläufe. Das läßt sich ggf. verhindern, indem Du auf Strings und Arrays verzichtest. - Lade die Zeichen einzeln aus dem EEPROM wenn Du sie ausgibst- - Überprüfe die Zykluszeiten Deiner Interrups und vermeide Interrups, wo immer es geht. - Sei sparsam mit Variablen. Statt 6 oder 8 zu deklarieren, die alle nur 1 Mal gebraucht werden, kann man bisweilen mit weniger auskommen, indem man kleinere Zwischenergebnisse berechnet und die selben Variablen mehrfach verwendet.
c-hater schrieb: > Handelt es sich um einen µC mit mehr als 64kByte Flash? Daniel Mader schrieb: > Prozessor: Atmega8 In diesem Sinne... Oliver
Oliver S. schrieb: > c-hater schrieb: >> Handelt es sich um einen µC mit mehr als 64kByte Flash? > > Daniel Mader schrieb: >> Prozessor: Atmega8 > > In diesem Sinne... Jo, schau doch mal, wers schreibt. Der hater-boy. Was erwartest du da?
Hi Die Aussage "Programm spinnt" find ich gut. Alle wissen, ein Programm macht genau das was der Programmierer programmiert hat. Nicht mehr und nicht weniger... eben genau das. Soviel zum Thema. Aber vielleicht hab ich auch was nützliches beizutragen. Es ist die Rede von "wenigen" globalen Variablen, aber von vielen lokalen. Na ja, auch lokale Variablen belasten den SRAm, also auch den Bereich Stack. Und wenn verschachtelte Aufrufe den Stack des öfteren bemühen, ist es leicht möglich, irgendwann ein paar Zeiger mal zu verbiegen. Ob das ein gepushtes Register ist, ein zerschossener Stack oder eine unsinnig überschriebene lokalvariable ist da völlig wurscht. Ach ja, und wil's der Proggrammierer ausschließt, heißt es, das Programm spinnt..... Gruß oldmax
tex schrieb: > Durch Deine Interrupts und Dein sehr großes Programm verursachst Du > Stack-Überläufe. > Das läßt sich ggf. verhindern, indem Du auf Strings und Arrays > verzichtest. > - Lade die Zeichen einzeln aus dem EEPROM wenn Du sie ausgibst- > - Überprüfe die Zykluszeiten Deiner Interrups und vermeide Interrups, wo > immer es geht. > - Sei sparsam mit Variablen. Statt 6 oder 8 zu deklarieren, die alle nur > 1 Mal gebraucht werden, kann man bisweilen mit weniger auskommen, indem > man kleinere Zwischenergebnisse berechnet und die selben Variablen > mehrfach verwendet. Ja, überlappende Interrupts könnte noch was sein!
tex schrieb: > Durch Deine Interrupts und Dein sehr großes Programm verursachst Du > Stack-Überläufe. Unwarscheinlich. Der AVR kann keine nestet Interrupts. Und den Flash kann man zu 100% ausnutzen, da läuft nichts über. Flash kann ja nicht zur Laufzeit dynamisch allokiert werden.
Das einzige was man sagen kann So ein Vorgehen ... > und verringere damit die Programmgröße, funktioniert die > Ausgabe einwandfrei und das Programm auch. Aber ich habe > schon sukzessive verschiedene Stellen auskommentiert, um > herauszufinden, ob es an irgendeiner bestimmten hakt, > aber nein. Es ist scheinbar rein von der Größe abhängig. ... ist sehr wahrscheinlich nicht zielführend. Es ist sicher nicht die Programmgröße im Flash, die für das Problem verantwortlich ist, sondern da steckt noch irgendwo ein Bug drinnen. Indem du Programmteile auskommentierst, veränderst du die Programmausführung, wodurch sich der Bug mal zeigt und mal nicht zeigt. Da du aber den Code nicht zeigen kannst/willst, kann dir aber das 4-Augen Prinzip auch nicht weiterhelfen. Entweder du springst über deinen Schatten und zeigst das Programm oder hier kann dir keiner konkret weiter helfen. Dann musst du dir in deiner Firma eben jemanden suchen, der mit dir das Programm Zeile für Zeile durchgeht und nach Auffälligkeiten sucht. Du selbst, und das ist keineswegs negativ gemeint, bist höchst wahrscheinlich zu betriebsblind um es zu sehen.
:
Bearbeitet durch User
Immer mehr Teile weglassen (auskommentieren). Wenn das Programm dann plötzlich wieder geht, dann ist des letzte auskommentierte Teil am Fehler beteiligt. Ansonsten: mit Kupferpyramiden gegen Erdstrahlen sichern.
Ich tippe auf compiler-prob oder unsaubere programmierung. Alle warnings anschalten (-Wall), alle Optimierungen aus (-O0) und die compiler/linker logs genau durchlesen und alle warnings verstehen und die durch sauberes Coding vermeidbaren durch Codeänderung beseitigen. MfG, PS: Posten der Compilerlogs verletzten keine Copyrights des Arbeitsgebers.
PittyJ schrieb: > Immer mehr Teile weglassen (auskommentieren). Wenn das Programm dann > plötzlich wieder geht, dann ist des letzte auskommentierte Teil am > Fehler beteiligt. so einfach ist das leider nicht. Bei einem Überschreiber im Speicher, kann das auskommentieren von variabel das Problem schon verschwinden lassen ohne das der Fehler an dieser Stelle ist.
Peter Dannegger schrieb: > Der AVR kann keine nestet Interrupts. Das kann er wohl (sei im Interrupt). Zum Problem: Sollte ein Bootloader vorhanden sein, ist der nutzbare Flash natürlich auch kleiner. Das hört sich für mich noch am logischten an, wenn man grobe Programmierfehler ausschließt.
avr schrieb: > Peter Dannegger schrieb: >> Der AVR kann keine nestet Interrupts. > > Das kann er wohl (sei im Interrupt). Je nun, wer das macht, ist entweder selber schuld, oder er fragt solche Fragen wie der TO erst gar nicht. Oliver
Wie verlässlich sind denn Deine "Füllstände"? Poste doch mal das Mapfile, da ist kein Code drin...
avr schrieb: > Das kann er wohl (sei im Interrupt). Das ist ne Krücke, aber kein nested Interrupt. Man kann sich dabei schön selber ins Knie schießen (unendliche Rekursion). Bei nested Interrupts kann ein Interrupt nur von einem mit höherer Priorität unterbrochen werden. Z.B. beim 8051 mit 4 Prioritätslevel können nur max 3 Interrupts gleichzeitig einen niederen unterbrechen.
Daniel Mader schrieb: > um eine Frage gleich vorweg zu nehmen: Leider kann/darf ich das Programm > nicht veröffentlichen, da ich es für meinen Arbeitgeber ist. Ist meines Erachtens kein Argument. Wenn Du kategorisch verweigern willst, den Code zu zeigen, dann ist ein öffentliches Forum der falsche Ort um nach Hilfe zu suchen. Wie weiter oben schon gesagt: Schnapp Dir einen Kollegen von Deiner Firma und geh das mit ihm zusammen durch. Alternativ: Gibt der Compiler Warnungen aus (mit -Wall -Wextra)? Dann behebe diese auf sinnvolle Art und Weise. Verwendest Du ein Tool zur statischen Codeanalyse? Wenn nein, dann mach das mal. Ist erstaunlich was man da so finden kann ;-)
Peter Dannegger schrieb: > avr schrieb: >> Das kann er wohl (sei im Interrupt). > > Das ist ne Krücke, aber kein nested Interrupt. Und JA und DOCH. > Man kann sich dabei schön > selber ins Knie schießen (unendliche Rekursion). Stimmt. > Bei nested Interrupts kann ein Interrupt nur von einem mit höherer > Priorität unterbrochen werden. Nested ist nested. Das ist zwar eine schönes Feature, aber keine Bedingung für nested interrupts. gruß cyblord
Hi Eigentlich ist es ja egal, ob das Programm läuft oder nicht... ist ja nicht von mir und alles was ich kaufe und nicht funktioniert wird reklamiert. Zugegeben, immer nur so ne Montagsproduktion macht keien Spaß, aber man kann ja das Produkt wechseln. Was ich damit sagen will, eigentlich ist's ja schon vielfältig gesagt, ein unveränderbarer Teil des Controllers wird ja wohl nicht die Ursache sein, also ist der änderbare Teil, (SRAM) maßgeblich dranbeteiligt. Auch Register sind veränderbar, sonst könnt der Controller ja gar nix machen. Nun kommt die Frage: Anfangs läuft das Programm und irgendwann steigt es aus, liefert Müll. Na, immer noch bei Flash-Grenzen? Wenn der TO lesen kann, dann hat er bestimmt mitbekommen, das gefühlte 70% den Stack verdächtigen. Auch ohne das Programm zu kennen. Auch ich seh da das Problem und an der Aussage, das ja nur lokale Variablen in größerer Zahl benutzt werden. Vielleicht ist es nicht angekommen, daher noch einmal der Hinweis: Eine Variable ist eine veränderbare Speicherzelle, entweder ein Register oder ein Stück SRAM. ( Ich weiß, Register sind auch SRAM) Und die werden bei lokal angelegten variablen auch auf dem Stack angelegt. Ein rekursi´ver Aufruf mit lokalen VAriablen füllt sehr wohl relativ schnell den Stack. Das muss noch nicht einmal von einem Interrupt kommen. Also, noch viel Spaß beim heiteren Rätselraten. Gruß oldmax
Ein Programm sollte immer mit einer Debugfunktionalitaet geschrieben werden, denn Debugging ist Teil der Entwicklung. Nicht irgednwas, das dummerweise in schlechten Fallen noch eingebaut werden muss. Also lieber einen naechst groesseren Controller mit einem UART mehr einbauen. Dasselbe gilt auch fuer Hardware. Der Rest wurde alles gesagt. Die fehlerhafte Funktionalitaet eingrenzen. Was kann man alles weglassen bis der Fehler nicht mehr auftritt.
oldmax schrieb: > Auch ich > seh da das Problem und an der Aussage, das ja nur lokale Variablen in > größerer Zahl benutzt werden. Danke für alle, die den Blick in die Glaskugel gewagt haben. Obige Aussage habe ich aber eher umgekehrt getroffen. Es sind überschaubar lokale Variablen, aber etwas mehr global volatile deklarierte.
Globale Variablen belegen über die Laufzeit hinweg konstant die gleiche Menge an Speicher. Den Stack damit zu zerschießen wird schwierig ;-)
:
Bearbeitet durch User
Daniel Mader schrieb: > Es sind > überschaubar lokale Variablen, aber etwas mehr global volatile > deklarierte. Zusammenfassend lässt sich sagen, daß alles richtig ist, niemand eine Fehler gemacht hat, kein Programmierfehler vroliegt, und auch sonst alles in Ordnung ist. Nur blöd, daß das Programm trotzdem nicht läuft. Woher weisst du, ob deine Speicherprüfroutine richtig funktioniert, wenn der Rest des Programms Amok läuft? Denn alle Hinweise deuten auf einen unbeansichtigt überschriebenen Speicherbereich hin. Entweder ein Stacküberlauf, Array out of bounds, oder ein fehlgeleiteter Pointer. Oliver
Oliver S. schrieb: > Woher weisst du, ob deine Speicherprüfroutine richtig funktioniert, wenn > der Rest des Programms Amok läuft? Irgend eine Macke wird das Programm schon haben, sonst würde da ja nicht so ein Murks raus kommen. Da bleibt einem doch ohnehin nichts anderes überig, als das Programm Schritt für Schritt abzuarbeiten, entweder simuliert, per Debugging oder emulieren (wegen der IRQs). Würde da der Einsatz eines STK500/600 nicht was bringen? (Hab damit leider keine Erfahrung).
Hi >Danke für alle, die den Blick in die Glaskugel gewagt haben. >Obige Aussage habe ich aber eher umgekehrt getroffen. Es sind >überschaubar lokale Variablen, aber etwas mehr global volatile >deklarierte. Sorry, hab ich anders gelesen, aber trotzdem, die global deklarierten kennst du. Lokal, ist im Prinzip auch klar, es sei denn du hast rekursive Aufrufe...... Und dann sind das schon nicht mehr "überschaubare". Aber egal, du weißt, es ist ok, wir nicht. Gruß oldmax
Den Trick mit der Speicherbelegung aus dem Roboternetz kann man übrigens auch noch weiter treiben. Den SRAM am Anfang mit 0xAAs füllen und dann eine kleine Routine schreiben, die wahlweise die SRAM-Belegung einfach auf dem Display darstellt (siehe Bild). Bei einem Grafik-Display geht das direkt, beim Text-Display sollte zumindest sichtbar sein, wo noch 0xAAs stehen. Auf dem Bild kann man schön erkennen, wie groß mein Sicherheitsabstand zwischen Head (oben) und Stack (unten) noch ist. Und man kann sehr gut vor und nach dem Aufruf einer Funktion prüfen, ob sich der Abstand verringert hat. Die Methode funktioniert natürlich auch für den Flash. Im zweiten Bild der Blick in eine kaputte Zeichensatztabelle. Nur als Anregung. Edit: Und bevor die Frage aufkommt, warum das so leer/mit lauter Nullen gefüllt ist ist: Es ist ein ATmega32 und auf dem LCD ist gerade der SRAM-Bereich oberhalb 1kB. [Edit:] Ich glaube, einige Tasten sind schon nachmittagsmüde
:
Bearbeitet durch User
Mir hat mal folgende Methode geholfen: Ich habe zwei globale Variablen zum Test eingebaut, und sie mit einem bestimmten Wert intialisiert. Vor und nach dem Aufruf verdächtiger Funktionen habe ich diese Variablen über den seriellen Port ausgegeben:
1 | int test1=12345; |
2 | ... andere variablen |
3 | int test2=11111; |
4 | |
5 | int main() { |
6 | initserial(); |
7 | int i; |
8 | while(1) { |
9 | printf("i=%i, 1=%i, 2=%i",i,test1,test2); |
10 | verdaechtige_funktion(parameter); |
11 | printf("i=%i, 1=%i, 2=%i",i,test1,test2); |
12 | i++; |
13 | } |
14 | } |
Dazu habe ich eine bewährte Library eingebunden, die den seriellen Port an stdout bindet. Irgendwann nach einer scheinbar zufälligen Anzahl von Schleifendurchläufen wurde eine der beiden Test-Variablen unerwartet verändert. Also lag die Vermutung nahe, dass irgendein unregeläßiges Ereignis den Fehler auslöst. In meinem Fall war ein externer Interrupt. Die Interruptroutine war zwar Ok, aber die Vorgänge, die NACH dem Interrupt aus der Hauptschleife heraus ausgeführt wurden, brachten den Speicher durcheinander. Nachdem ich nun wusste, welche Funktion innerhalb der Hauptschleife der Übeltäter war, konnte ich entsprechende printf Ausgaben in eben diese Funktion einbauen. Die eigentliche Ursache war dann schnell gefunden (es wurden Daten von einem externen Chip in ein Array geladen, das zu klein war). Versuche es mal mit dieser Methode. Falls Du keine serielle Library hast, der du vertraust, dann nimm das:
1 | #include <stdint.h> |
2 | #include <stdio.h> |
3 | #include <avr/io.h> |
4 | #include <util/setbaud.h> |
5 | |
6 | // The serial bitrate and CPU clock frequency is usually set in the Makefile |
7 | // #define BAUD 115200 |
8 | // #define F_CPU 20000000 |
9 | |
10 | static int serial_write(char, FILE *); |
11 | static FILE serialPort = FDEV_SETUP_STREAM(serial_write, null, _FDEV_SETUP_WRITE); |
12 | |
13 | // Write a character to the serial port |
14 | static int serial_write(char c, FILE *f) { |
15 | // wait until transmitter is ready |
16 | loop_until_bit_is_set(UCSRA, UDRE); |
17 | UDR = c; |
18 | return 0; |
19 | } |
20 | |
21 | // Initialize the serial port |
22 | void initserial(void) { |
23 | // set baudrate |
24 | UBRRH = UBRRH_VALUE; |
25 | UBRRL = UBRRL_VALUE; |
26 | #if USE_2X |
27 | UCSRA |= (1 << U2X); |
28 | #else |
29 | UCSRA &= ~(1 << U2X); |
30 | #endif |
31 | // framing format 8N1 |
32 | #ifdef URSEL |
33 | UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); |
34 | #else |
35 | UCSRC = (1<<UCSZ1) | (1<<UCSZ0); |
36 | #endif |
37 | // enable transmitter |
38 | UCSRB = (1<<TXEN); |
39 | // Bind stdout to the serial port |
40 | stdout = &serialPort; |
41 | } |
Dieser Code kommt ohne Interrupts und Pufferspeicher aus. Die Warscheinlichkeit, dass die Textausgabe versagt, weil der Speicher durcheinander geraten ist, wird so minimiert. Du must beim Programmstart einmal die Funktion initserial() aufrufen. Danach kannst Du mit sämtlichen Ausgabe-Funktionen der standard Library arbeiten (printf, puts, putc und so weiter).
printf() auf einen AVR? Wuerd ich mir nie antun. Viel zu klotzig. Das einfachste und kleinste zum debuggen ist wahrscheinlich ein einzelner Pin, den man als ausgang definiert und hoch-runter zieht. Die naechst bessere loesung ist ein zweiter Pin, auf den man die Aenderung signalisiert. zB auf dessen steigende Flanke sind auf dem ersten pin die daten gueltig. Falls das laeuft kann man den UART in betrieb nehmen. Beim UART muss man beachten, dass man nur soviele Daten rausschicken kann wie die Baudrate schnell ist.
> Beim UART muss man beachten, dass man nur soviele Daten > rausschicken kann wie die Baudrate schnell ist. Wie meinst du das? Darf man bei 9600 Baud nur 9600 Zeichen senden? Und was passiert danach?
9600 Baud bedeutet 9600 Bit, inkl. Start, Stop, Parity. Dh sind dann max 960 Bytes/sek. Wenn man mehr auf das UART schreibt kommt nur noch Muell.
Hi Stockki schrieb: > 9600 Baud bedeutet 9600 Bit, inkl. Start, Stop, Parity. Dh sind dann > max 960 Bytes/sek. Wenn man mehr auf das UART schreibt kommt nur noch > Muell. Nun bin auch ich sprachlos... Leute, lest doch bitte erst mal das was ihr da schreibt. Es soll hier Teilnehmer geben, die glauben das dann auch und verkünden es weiter. Und wenn das zufällig eine Lehrkraft mit dem Ehrgeiz seinen Schülern Mikrocontrollern beizubringen ist, multipliziert sich das Ganze Wissen und wir können uns in Zukunft von den Ausflügen Richtung Weltall verabschieden. Gruß oldmax
Stockki schrieb: > 9600 Baud bedeutet 9600 Bit, inkl. Start, Stop, Parity. Dh sind dann > max 960 Bytes/sek. Wenn man mehr auf das UART schreibt kommt nur noch > Muell. Wie soll man denn "mehr auf den UART schreiben"? Der UART wird mit einer festen Taktrate (=Baudrate) betrieben und tackert so alle Daten raus die er bekommt. Bekommt er schneller Daten, als er senden kann, so läuft irgendwann der Sendepuffer voll. Auf die eigentliche Übertragung hat das natürlich keinen Einfluss und somit kommt da auch kein "Muell" an. > printf() auf einen AVR? Wuerd ich mir nie antun. Viel zu klotzig. Ahah > Falls das laeuft kann man den UART in betrieb nehmen. Genau, und da ist printf dann eine gute Möglichkeit schnell und einfach kurze Texte und Variableninhalte rauszuschicken. Ohne umständliches formatieren mit itoa und zusammenbauen der Daten. > Beim UART muss man > beachten, dass man nur soviele Daten rausschicken kann wie die Baudrate > schnell ist. Was bei Debug Ausgaben ja auch echt ein Problem ist. Da hat man ja auch Megabyteweise Daten pro Sekunde.... gruß cyblord
> Stockki schrieb: >> 9600 Baud bedeutet 9600 Bit, inkl. Start, Stop, Parity. Dh sind dann >> max 960 Bytes/sek. Wenn man mehr auf das UART schreibt kommt nur noch >> Muell. cyblord ---- schrieb: > Wie soll man denn "mehr auf den UART schreiben"? Der UART wird mit einer > festen Taktrate (=Baudrate) betrieben und tackert so alle Daten raus die > er bekommt. Bekommt er schneller Daten, als er senden kann, so läuft > irgendwann der Sendepuffer voll. Auf die eigentliche Übertragung hat das > natürlich keinen Einfluss und somit kommt da auch kein "Muell" an. Ach, mit genügend Phantasie beim "Programmieren" bekommt man das sicherlich hin - hier laufen eine ganze Reihe solcher Spezialisten rum ;). Ein Sendepuffer ist ja nicht immer vorhanden, viele werfen die Daten einfach so in die Register. Und vorher nachschauen, ob das letzte Byte schon komplett raus ist, ist ja auch nicht soo wichtig...
:
Bearbeitet durch User
oldmax schrieb: > Hi > > Stockki schrieb: >> 9600 Baud bedeutet 9600 Bit, inkl. Start, Stop, Parity. Dh sind dann >> max 960 Bytes/sek. > > Nun bin auch ich sprachlos... > Leute, lest doch bitte erst mal das was ihr da schreibt. Es soll hier > Teilnehmer geben, die glauben das dann auch und verkünden es weiter. Und > wenn das zufällig eine Lehrkraft mit dem Ehrgeiz seinen Schülern > Mikrocontrollern beizubringen ist, multipliziert sich das Ganze Wissen > und wir können uns in Zukunft von den Ausflügen Richtung Weltall > verabschieden. > Gruß oldmax Nun, der erste Teil ist ja richtig. Wenn etwas kritikwürdig wäre, dann das hier: >> Wenn man mehr auf das UART schreibt kommt nur noch >> Muell. Bei korrekter Programmierung schafft man es auf Seite des µC nicht, mehr Bytes pro Sekunde zu schreiben, da kommt dann auch kein Müll. Der entsteht nur wenn: der Code Murks ist, die Übertragungsraten von Sender und Empfänger nicht stimmen, oder der Empfänger beschäftigt ist und die Bytes nicht schnell genug abholt. Ob dieser kleine Fehler es verdient hat, mit dem Geschwurbel über den Untergang des Abendlandes beantwortet zu werden, darf bezweifelt werden. Außerdem, wenn Du schon im belehrenden Tonfall loslegst, dann schreib' halt hin, was Deiner Meinung nach richtig wäre, damit Zillionen anderer Schüler nicht irre gehen.
Hi MWS schrieb: > Nun, der erste Teil ist ja richtig. Wenn etwas kritikwürdig wäre, dann > das hier: >>> Wenn man mehr auf das UART schreibt kommt nur noch >>> Muell. > > Bei korrekter Programmierung schafft man es auf Seite des µC nicht, mehr > Bytes pro Sekunde zu schreiben, da kommt dann auch kein Müll. Es mag sein, das der erste Teil der Aussage richtig ist und dennoch ist die Antwort schlichtweg falsch. Auch deine Antwort hinkt gewaltig. Wie bitteschön sieht denn eine unkorrekte Programmierung aus, die einen mit 9600 Byte betriebenen UART in die Lage versetzt, mehr als 960 Bytes in der Sekunde zu senden? Sicherlich ist es durchaus machbar, mehr als 960 Bytes in einer Sekunde in einem Sendepuffer abzulegen. Na und, dann dauert die Übertragung eben mehr als eine Sekunde. Wenn der Puffer groß genug und nach einer Sendung entsprechen Zeit bis zur nächsten Datenflut ist, kommt da auch nix durcheinander. Mir braucht ihr über Datentransfer keine Belehrung zukommen lassen, ich weiß wie's funktioniert, aber der TO hat ein Problem mit ganz anderen Ursachen. Nun kommt hier noch tief fundierte die Diskussion über UART hinzu. Bravo Gruß oldmax
oldmax schrieb: > Wie bitteschön sieht denn eine unkorrekte Programmierung aus In's UDR schreiben, ohne zu überprüfen ob's leer ist. > die einen mit > 9600 Byte betriebenen UART in die Lage versetzt, mehr als 960 Bytes in > der Sekunde zu senden? Diese Vermutung hat niemand in den Raum gestellt, außer Dir jetzt vielleicht. Denn so lautete das ursprünglich: Stockki schrieb: > Wenn man mehr auf das UART schreibt kommt nur noch > Muell. Das trifft bei falschem Code, s.o. zu, welche Form "Muell" wurde nicht näher definiert. oldmax schrieb: > Mir braucht ihr über Datentransfer keine Belehrung zukommen lassen, ich > weiß wie's funktioniert Den Eindruck hatte ich nicht. Hättest Du's gewusst, wäre es Dir ein Leichtes gewesen, den Fehler in einem Satz zu berichtigen, statt in drei Sätzen und mit vielen Worten das vermeintliche Nichtwissen des Schreibers im Rundumschlag zu kritisieren. oldmax schrieb: > wir können uns in Zukunft von den Ausflügen Richtung Weltall > verabschieden. M.E. bist Du da der Einzige, der auf der Erde sitzenbleibt. :D oldmax schrieb: > Nun kommt hier noch tief fundierte die Diskussion über UART > hinzu. Bravo Ist doch egal, Threads hier haben durchaus den Reiz, dass die mal abdriften, deswegen sind sie nicht weniger interessant. Das Ansinnen des TEs per Glaskugel in Ferndiagnose eine Lösung seines Problems zu erhalten, ist eh' nicht machbar. Eine Diskussion über UART ändert daran nichts und kann deshalb auch nicht schaden.
Hi alle, ihr seid mir zuvor gekommen. Ich musste mich erstmal im stillen kämmerlein abregen. Mein primitiver Beispiel-Code sendet Zeichen so:
1 | static int serial_write(char c, FILE *f) { |
2 | // wait until transmitter is ready |
3 | loop_until_bit_is_set(UCSRA, UDRE); |
4 | UDR = c; |
5 | return 0; |
6 | } |
Ich habe also bereit vor Wolfis Kommentar gezeigt, wie man es richtig macht. Abgesehen davon sind die entsprechenden Erlärungen im Datenblatt meiner Meinugn nach nicht zu übersehen.
Stefan us schrieb: > Abgesehen davon sind die entsprechenden Erlärungen im Datenblatt > meiner Meinugn nach nicht zu übersehen. Hehe, der war gut. Wie viele der hier im Forum fragenden haben jemals ein Datenblatt über das Pinout hinaus gelesen? --- OK, ich weiß das ist OT und gemein, aber das musste raus...
:
Bearbeitet durch User
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.