Hallo,
ich habe hier ein Problem mit dem empfangen von Daten über Uart, die mir
ein VB oder Terminal Programm liefert. Sobald das Startbyte kommt geht
er in die Schleife rein um command zu füllen. Wenn dan mein
Endbefehlsbyte kommt geht der MC entweder aus (Display wird schwarz und
sendet keine Uart Daten mehr,
oder er startet einfach neu) komischerweise hat es gestern nach
mehrmaligen neukompelieren und starten einwandfrei funktionier... Wo
kann der Fehler sein? Vorallem lief es gestern und das einzige was ich
verändert habe war der Teil nach der while Schleife..
MfG Philip P.
1
ci=0;
2
c=uart_getc();
3
4
if(c!=UART_NO_DATA&&c==250)
5
//Startbedingung für alle Eingehenden Daten, wenn 250 gesendet wird und Daten vorhanden
6
7
8
{
9
//uart_putc( c );
10
while(c!=254)
11
// Lese solange, bis von der anderen Seite 254 als Endbedingung kommt!
12
13
{
14
if(c!=UART_NO_DATA){
15
command[ci++]=c;
16
c=uart_getc();
17
uart_putc(c);// überprüfen am terminal
18
}
19
20
}
21
22
inti;
23
for(i=0;i>9;i++)//Addiert Byte 0 - 9 zur Checksumme
Hallo,
habe den Vergleich mal an anfang des Programm gesetzt:
Wenn ich die Berechnung ausklammere und über Uart die 250 sende, friert
das Display ein. Bei 254, geht er aus der Schleife raus und arbeitet
normal weiter. Sobald die Rechnung in der for Schleife ist startet er
einfach neu. Was mach ich falsch?
command ist als unsigned char array deklariert
Philipp P. schrieb:> command ist als unsigned char array deklariert
Mit welcher Größe?
Wie sieht make_u16() aus?
Mit deinen ausgewählten Codeschnipseln ist kein sinnvolles Debugging
möglich. Poste das ganze Programm.
Walter schrieb:> checksum wird nicht initialisiert und> das Programm stürzt in make_u16 ab
jede Variable hat irgendeinen wert. Egal ob initialisiert oder nicht.
Wenn es nicht gerade ein Zeiger ist, ist das wohl kein Grund für ein
Absturz.
Hallo,
danke schonmal für die Antworten, im Anhang das derzeitige Programm.
Ich hab versucht das wichtigste zu kommentieren.
Manche kleine Fehler sehe ich noch nicht direkt.
MfG Philipp P.
Ziemlich sicher irgend eine Memory corruption.
1)
Du weist z.B. messwerte[20] (21. Eintrag) etwas zu, ob wohl messwerte[]
(im include file(!?!?)) nur mit max. 20 Einträgen definiert wurde.
Den Sinn von include files solltest du nochmal nachlesen...
2)
1
command[ci++] = c;
2
(...)
3
command[ci+1] = '\0';
hier wird auch zu keiner Zeit geprüft, ob der index ci(+1) die Grenzen
von command[] sprengt.
3)
1
sprintf(buffer1, "Zeit: %02x:%02x:%02x", time_h, time_m, time_s); //Zeit am LCD Ausgeben
wie groß ist buffer1[]?
wie viele bytes willst du da mit sprintf reinschreiben?
-> Memory corruption
Hallo,
messwerte[20] hab ich auf 21 geändert ;)
Das andere Array ist buffer[10] -> hat bis jetzt immer funktioniert.
Und das mit command[ci+1] = '\0'; wird auch entfernt weil ich es nicht
brauche. Die command[21] werden auch nicht voll weil ich maximal 13Bytes
hintereinander sende.
MfG Philipp
Ok stimmt sry, buffer[10] ist ein wenig zu klein für 14 Zeichen am Lcd.
Das habe ich jetzt auch vergrößert. Er hängt sich trozdem auf oder
startet neu -.-
MfG Philipp
Peter II schrieb:> jede Variable hat irgendeinen wert. Egal ob initialisiert oder nicht.> Wenn es nicht gerade ein Zeiger ist, ist das wohl kein Grund für ein> Absturz.
habe ich nicht behauptet, aber es ist ein Fehler der sich noch bemerkbar
machen wird
Hallo,
@ Walter ja, den Fehler in der for Schleife habe ich entfernt
Hab jetzt die ganze Vergleichsroutine nochmal raus genommen bis auf:
Nach der Eingabe von 250 friert das Display ein. Dann nach 254 wirds
dunkel und er verabschiedet sich.... Mit debuggen habe ich mich noch
nicht auseinander gesetzt.
1
ci=0;
2
c=uart_getc();
3
4
if(c!=UART_NO_DATA&&c==250){//Startbedingung für alle Eingehenden Daten, wenn 250 gesendet wird und Daten vorhanden
5
6
7
while(c!=254){// Lese solange, bis von der anderen Seite 254 als Endbedingung kommt!
Joe F. schrieb:> Überlege mal, was passiert wenn c == UART_NO_DATA ist.> Dann läuft die while Schleife ewig.
fast, wenn c == UART_NO_DATA kommt er gar nicht ins if rein,
er kommt nur rein wenn c == 250 und dann hängt er sich in der Schleife
auf
Walter schrieb:> fast, wenn c == UART_NO_DATA kommt er gar nicht ins if rein,> er kommt nur rein wenn c == 250 und dann hängt er sich in der Schleife> auf
Ja genau das soll er doch machen, bis mit dem Befehlsbyte mit Wert 254
die Schleife verlassen wird. Sobald die Schleife verlassen wird macht
der MC was er will.
Joe F. schrieb:> In der while Schleife wird 254 allerdings nicht mehr empfangen,> wenn c> voher mal UART_NO_DATA wurde...>> Du wolltest vermutlich eher sowas machen: while( c != 254 )> {> c = uart_getc();> if( c != UART_NO_DATA )> {> command[ci++] = c;> uart_putc(c); // überprüfen am terminal> }> }
So habe ich gerade versucht, allerdings gibt er wieder den Geist auf
wenn ich 254 sende.
Baue ich aber delays ein, läuft alles so wie es soll.
1
if(c!=UART_NO_DATA&&c==250){//Startbedingung für alle Eingehenden Daten,
Ja, super Lösung.
Es sind immer noch alle Fehler drin, auf die man dich hinweist, aber du
ignorierst das einfach.
Die Delays sorgen lediglich dafür, dass es unwahrscheinlicher wird, dass
sich dein Programm in der while Schleife aufhängt, da c weniger
wahrscheinlich den Wert UART_NO_DATA annimmt.
Ist mir echt zu doof jetzt. Good luck.
Sry, wollte dich nicht verärgern und das soll auch keine Lösung sein!
Ich habs nochmal umgeschrieben ein, zweimal funktioniert es und dann
hängt er sich wieder auf beim Schleifen austritt -.-
Tja, also deine Arraygrößen stimmen jetzt, und die while() Schleife
dürfte nicht mehr hängen.
In c steht nach der Schleife natürlich immer 254, insofern macht die
nachfolgende switch/case struktur (noch) keinen Sinn, aber das Programm
sollte zumindest stabil in der for(;;) Schleife sein.
Ich denke, es wird Zeit, dass du deinen Debugger kennenlernst, um
herauszufinden, an welcher Zeile des Programmes der Absturz genau
passiert.
Evtl. ist es auch gar nicht die Software, sondern du erzeugst durch
irgend einen Output einen starken Strommpuls auf der
Versorgungsspannung, und der Controller resettet deswegen...
Danke nochmal für die Hilfestellung:) Ja, das mit dem Stromimpuls dacht
ich mir auch schon, aber das einzige was am MC angeschlossen ist, sind 3
I2C Chips das Display und der UART.
Dann werde ich mir die Tage mal einen AVR Dragon bestellen...
MfG Philipp P.
Kann es sein das UART_NO_DATA zu spät, oder nicht dirkt den Wert zurück
gibt ob neue Daten vorhanden sind? So bleibt er in der while Schleife
und erfüllt die if Bedingung und treibt ci in die Höhe und läuft dann
über?
1
ci=0;
2
c=uart_getc();
3
if(c!=UART_NO_DATA&&c==250){//Startbedingung für alle Eingehenden Daten,
4
//wenn 250 gesendet wird und Daten vorhanden
5
6
7
while(c!=254){
8
// Lese solange, bis von der anderen
9
//Seite 254 als Endbedingung kommt!
10
c=uart_getc();
11
if(c!=UART_NO_DATA&&ci<21){
12
command[ci++]=c;
13
uart_putc(c);// überprüfen am terminal
14
15
}
16
17
}
18
19
command[ci]='\0';
20
}
So geht er in die Schleife und wieder raus, sendet aber nichts über
Uart.
Philipp P. schrieb:> Kann es sein das UART_NO_DATA zu spät, oder nicht dirkt den Wert zurück> gibt ob neue Daten vorhanden sind?
Das ist eine sehr abenteuerliche Theorie...
Der Fehler liegt mit Sicherheit an ganz anderer Stelle.
Um ein Problem einzugrenzen geht man üblicherweise folgendermaßen vor:
Grenze Stück für Stück ein, wo das Problem liegt.
Dazu kommentierst du z.B. mal allen Code aus, der mit dem Display
kommuniziert, allen I2C code, und testest lediglich den UART code.
Wenn da kein Problem ist, kommentierst du den UART code aus, und testest
den Display Code. Wenn der noch funktioniert, dann testest du die I2C
Teile.
Damit du uns nicht immer mit vollkommen sinnfrei formatiertem Code
(Einrückungen) das Lesen schwer machst, habe ich dir als Service deinen
Code mal durch einen Formatter gejagt, und die Zeilen des sehr
unsinnigen include files direkt in die .c Datei integriert.
So habe vorhind mir ci mal ausgeben lassen NACHDEM die Schleife
verlassen wurde. Er zählt ci kontinuirlich hoch, mit delays langsamer.
Mit ci<21 verhindere ich, das er in der if abfrage weiter hoch zählt und
sich dann aufhängt.
Nun frage ich nur UART_NO_DATA ab und die bleibt immer 0. Die Abfrage
schaltet mir eine LED an und aus die am PCF hängt. Normal müsste die LED
doch angehen wenn uart_getc keine neuen Daten bekommt?
Danke fürs formatieren ;)
ci<21
ist übrigens nicht ausreichend, denn das array ist 21 Einträge groß
(0..20), d.h. hier:
command[ci] = '\0';
kracht's dann potentiell.
Philipp P. schrieb:> Nun frage ich nur UART_NO_DATA ab und die bleibt immer 0. Die Abfrage> schaltet mir eine LED an und aus die am PCF hängt. Normal müsste die LED> doch angehen wenn uart_getc keine neuen Daten bekommt?
2 mögliche Gründe:
du nutzt eine andere/alte library version, die bei uart_getc() blockt,
oder der code für die LED funktioniert nicht.
Philipp P. schrieb:> Danke fürs formatieren ;)
Ja, gerne. Du bist allerdings auch echt krass. Jetzt bekommst du
formatierten Code, und schreibst deine Änderungen wieder mit genau der
gleichen schluderigen Art wie zuvor da rein. Ich werde deinen Code nicht
nochmal formatieren...
Oh ja, vergrößer ich. Wenn ich die Abfrage mit (!( c & UART_NO_DATA))
negiere, leuchtet die LED... Hab mir gerade nochmal die aktuelle Lib
runtergelden, alte gelöscht und neue rein gemacht. Muss ich in der Lib
noch etwas eintragen?
Und jetzt ist auch klar wo die Memory Corruption herkam.
UART_NO_DATA wurde in der while Schleife nie geprüft, und zusammen mit
der fehlenden Begrenzung für ci wurde munter Speicher überschrieben.
Den Test, ob ein Zeichen gültig ist, würde ich übrigens nicht mit
Tatsache so funktionierts und UART_NO_DATA schaltet um und ci zählt
immer um 1 pro empfangenem Byte hoch. Ganz großes Kino^^
Vielen Vielen Dank
Ich meine iwo im Forum gelesen zu haben das c ein unsigned char sein
muss,
da sonst uart_getc() nicht richtig funktioniert..
1
if(!(c&UART_NO_DATA)){//Startbedingung für alle Eingehenden Daten,
Philipp P. schrieb:> Ich meine iwo im Forum gelesen zu haben das c ein unsigned char sein> muss,> da sonst uart_getc() nicht richtig funktioniert..
Bei Peter Fleurys UART-Lib ist doch extra ein Codebeispiel dabei, das
die korrekte Verwendung zeigt.
Und mit ein bisschen Verständnis für die Lib (und das Verständnis
sollte man sich aneignen), ist das auch klar, dass das ein uint16 sein
muss
Na denn.
MWS schrieb:> der Herr fährt auch zweispurig, ohne es das jeweils> andere Forum wissen zu lassen
Kann er ja machen, ich habe auch mehrere Rechtsanwälte ;-)
@Philipp P.
Trauriger finde ich, dass bei dir eine ziemlich ausgeprägte
Lernverweigerung zu erkennen ist.
Code formatieren heisst jetzt "ich schiebe einfach alles ganz nach
links", und ci auf Array-Größe testen fliegt wieder raus. Geht ja
jetzt...
MWS schrieb:> Joe F. schrieb:>> Ja, gerne. Du bist allerdings auch echt krass.>> Nicht nur krass, der Herr fährt auch zweispurig, ohne es das jeweils> andere Forum wissen zu lassen:> http://www.roboternetz.de/community/threads/66539-...> Ist einfach mieser Stil, mehrere Foren zu beschäftigen, anstatt die> Birne anzustrengen und bei einem zu bleiben.
Ja, ich habe vorhind noch in einem anderem Forum gefragt und werde dort
auch gerne berichten das mir hier sehr gut geholfen wurde.
Und ja ich habe meine Birne angestrengt nur wenn ich nicht weiter weiß
und den Fehler nicht finde wende ich mich an ein Forum.
Ich denke es ist jedem selbst überlassen zu helfen und wenn meine sich
meine Programmierkünste verbessert haben bin ich auch bereit anderen zu
helfen...
C ist Neuland für mich. Trotz fast täglichem lesen und einarbeiten macht
man da halt Fehler und ist für jede Hilfe Dankbar....
MfG Philipp
Philipp P. schrieb:> Und ja ich habe meine Birne angestrengt nur wenn ich nicht weiter weiß> und den Fehler nicht finde wende ich mich an ein Forum.> Ich denke es ist jedem selbst überlassen zu helfen und wenn meine sich> meine Programmierkünste verbessert haben bin ich auch bereit anderen zu> helfen...
Richtige Einstellung.
Tip: Bestelle dir trotzdem den Debugger, der wird dir das Leben um
einiges erleichtern.
Joe F. schrieb:> Kann er ja machen, ich habe auch mehrere Rechtsanwälte ;-)
Die bezahlst Du auch (sinnvollerweise), freiwillige Helfer werden nicht
bezahlt, deren Lohn ist bestenfalls ein gewisses Erfolgserlebnis. Das
nimmt denen aber derjenige, der ohne es allen mitzuteilen, gleich
mehrere Foren beschäftigt.
> @Philipp P.> Trauriger finde ich, dass bei dir eine ziemlich ausgeprägte> Lernverweigerung zu erkennen ist.> Code formatieren heisst jetzt "ich schiebe einfach alles ganz nach> links", und ci auf Array-Größe testen fliegt wieder raus. Geht ja> jetzt...
Das konnte ich schon oft beobachten: diejenigen, die gleich einen ganzen
Schwung Foren beschäftigten, also versuchten rücksichtslos eigenes Hirn
durch copy/paste zu ersetzen, zeigten sich meist auch in jeglicher
anderer Hinsicht rücksichtslos und verständnisbefreit.
Philipp P. schrieb:> und den Fehler nicht finde wende ich mich an ein Forum.
Du hast Dich nicht an ein, sondern mehrere gewandt.
> Ich denke es ist jedem selbst überlassen zu helfen und wenn meine sich> meine Programmierkünste verbessert haben bin ich auch bereit anderen zu> helfen...
Das wäre richtig, wenn Du die Fairness besessen hättest, es dem jeweilig
anderen Forum zu sagen. Denn dann kann jeder überlegen, ob er Dir helfen
will, oder lieber wartet, ob woanders bereis ein Ergebnis rauskommt.
Joe F. schrieb:> @Philipp P.> Trauriger finde ich, dass bei dir eine ziemlich ausgeprägte> Lernverweigerung zu erkennen ist.> Code formatieren heisst jetzt "ich schiebe einfach alles ganz nach> links", und ci auf Array-Größe testen fliegt wieder raus. Geht ja> jetzt...
Um die formatierung kümmere ich mich morgen noch ;)
ci wird jetzt hoffentlich richtig abgefragt.
Philipp P. schrieb:> Um die formatierung kümmere ich mich morgen noch ;)
Falscher Ansatz.
Um Formatierungen kümmert man sich gleich. Denn Formatierungen helfen
dir, unsinnigen Code zu erkennen. Genau die Sorte Codefehler, die du
oben hattest. Denn wie soll sich denn der Abfrage Wert in der while
Bedingung ändern, wenn gar keine Funktion aufgerufen wird, die ihn
ändern könnte, weil der entsprechende Aufruf gar nicht erfolgt? Eine
saubere Einrückung zeigt dir das.
Das hier
1
while(c!=254&&ci<20){
formulierst du besser so
1
while(c!=254&&ci<sizeof(command)-1){
denn dann bist du die lästige Abhängigkeit dieser ominösen 20 von der
Grösse des Arrays los, bzw. der Compiler kümmert sich darum, dass die
Werte zusammenstimmen, wenn du die Größe des Arrays veränderst.
Deine ganze Abfragerei der erhaltenen Werte lässt sich auch so
zusammenfassen
1
if(c>=0x32&&c<=0x39)
2
pcf_set(c-0x32);
3
4
if(c>=0x40&&c<=0x47)
5
pcf_clear(c-0x40);
Deine switch-case Lösung ist an sich nicht falsch, aber gegenüber dem 4
Zeiler da oben recht geschwätzig und beim Tippen bzw. Copy/Paste auch
recht fehleranfällig, da man beim Copy/Paste gerne mal vergisst,
irgendeine der kritischen Zahlenwerte anzupassen.
Das ist das eine. Das andere ist, dass es da einen Zusammenhang gibt,
zwischen dem gesendeten Kommando und dem zu schaltenden pcf. Der 4
Zeiler zeigt diesen numerischen Zusammenhang viel besser als dein
switch/case Konstrukt, bei dem man erst mal Zahlenwerte vergleichen muss
um den Zusammenhang zu erkennen. Derartige Zusammenhänge sind auch oft
einfache Regeln, die man sich gut merken kann. Anstatt 14 Wertpärchen
braucht sich der Programmierer nur 2 einfache Regeln merken, wenn er den
Datenfluss durch das Programm verfolgt.
Philipp P. schrieb:> Um die formatierung kümmere ich mich morgen noch ;)
Solch einen unformatierten Code hier hinzurotzen ist nur ein Zeichen
mangelnden Respekts vor den Leuten, die bereit sind, Dir unentgeltlich
zu helfen. Und den Programmcode, den jemand für Dich formatiert hat,
erneut zu verunstalten, ist eine ganz massive Beleidigung.
Die korrekte Formatierung von Programmcode dient nicht dazu, das ganze
nach Abschluss der Implementierung hübsch zu machen, sondern ist ein
ganz wichtiges Instrument, Fehler frühzeitig zu erkennen.
Um Codeformatierung zu erlernen, solltest mal etwas in Python
programmieren.
Karl Heinz schrieb:> formulierst du besser so> while( c != 254 && ci < sizeof( command ) > - 1 ) {
Ich würde auch die magische 254 da weghaben wollen und stattdessen ein
Makro verwenden:
Markus F. schrieb:> ???>> Jetzt hast Du's verhunzt.
lol... Ich hatte zuerst den Originaltext zitiert und dann angepasst.
Dabei gab's einen Zeilenumbruch. Das reine Zitat sah so aus:
Karl Heinz schrieb:> formulierst du besser so while( c != 254 && ci < sizeof( command )> - 1 ) {
Das '>' ist versehentlich drin geblieben.
Joe F. schrieb:> Man müsste zusätzlich aber auch noch dafür sorgen, dass in "c" zum> passenden Zeitpunkt etwas anderes drin steht als 254...
Was meinst du damit? Die 254 kann ruhig in dem Array stehen bleiben.
Ich habe meine wirren Code stellen mal durch einen source code formatter
geschickt, ich hoffe jetzt siehts besser aus.
Karl Heinz schrieb:> Deine ganze Abfragerei der erhaltenen Werte lässt sich auch so> zusammenfassen> if( c >= 0x32 && c <= 0x39 )> pcf_set( c - 0x32 );>> if( c >= 0x40 && c <= 0x47 )> pcf_clear( c - 0x40 );
Das is der Knaller da wär ich nie drauf gekommen das es so einfach zu
formulieren ist ;)
Danke für die Hilfestellungen und Tipps.
MfG
Joe F. schrieb:> Überlege einfach mal, welchen Inhalt die Variable "c" nach dem> Verlassen> der while Schleife hat...
Wenn er die Schleife durch 254 verlässt steht in c die 254 solange bis
er wieder die uart_getc() aufruft. Jedenfalls gibt er mir so c nach der
Schleife aus.
MfG Philipp
Joe F. schrieb:> So ist es. Findste gut so?
Wo drauf möchtest du hinaus? Bis zum nächsten Aufruf kann das c doch
ruhig 254 bleiben? In dem command Array sollte es nicht stören oder wird
c vorher nochmal abgefragt? Ich könnte es nach der Schleife 0 setzen?