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.
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 ;-)
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.
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.
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.
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
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.
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
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
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?
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...
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...