Grüß euch alle,
bei einem (nur bei diesem Codeausschnitt) habe ich ein Laufzeitproblem.
Der Code befindet sich im Anhang.
In meinen zwischenspeicher_array, welches maximal 4 Zeichen groß ist
(nicht sichtbar im Codeschnitt) wird aus einen Empfangspuffer einer UART
eine Zahl von 0-255 gespeichert.
Wird aber (wenn das überhaupt passiert) eine Zahl im dreistelligen
Bereich, wie 100 auf einmal als PWM Signal signal in mein
zwischenspeicher_array gespeichert, stürzt der µC ab.
Die Position der ersten Ziffer ist im Puffer "2", die zweite Ziffer "3",
die dritte Ziffer "4".
Der Buchstabe P ist das Zeichen an Position "1".
bei den Löschen (also das Array komplett leeren) habe ich ein Problem,
weil das Array den zuvorherigen Speicherwert annimmt. Veilleicht liegt
es daran.
Hab das Array erst mit
zwischenzustand_array[ZWISCHENZUSTAND_ARRAY_SIZE]={0}; versucht zu
löschen.
Das Problem war noch da.
Dann hatte ich versucht mit zwischenzustand_array[0]='\0' das array zu
löschen, indem ich ein Stringende zeichen vortäusche, was aber das
Problem nicht behoben hat.
Könnte mir jemand bitte einen Anreiz geben?
Tho Wes schrieb:> Peter II schrieb:>> wie ist ZWISCHENZUSTAND_ARRAY_SIZE definiert?>> Mit einen #define ZWISCHENZUSTAND_ARRAY_SIZE 4
gut, dann ist der Fehler in den code den wir nicht sehen.
danke dir peter, das reicht schon für eine gute Antwort aus.
Aber wie lösche ich eigentlich (also inhalte löschen) ein Array in C,
das dann komplett neu befüllt werden soll, liege ich da wenigstens
richtig?
Mfg,
tommyProg
Siebzehn Zu Fuenfzehn schrieb:> a[0]=0;> a[1]=0;> a[2]=0;> a[3]=0;> Alles andere ist muehsamer, dauert laenger
Auf jeden Fall ist es wartungsintensiver wenn sich am Array was ändert.
Ohne es hier grad überprüfen zu können:
Mich würde es wundern wenn der Compiler bei einem hinreichend kleinem
Array die Schleife, die sich irgendwo in memset befinden wird, nicht eh
durch explizites Setzen jedes Bytes ersetzt.
Tho Wes schrieb:> Aber wie lösche ich eigentlich (also inhalte löschen) ein Array in C,
In der Regel garnicht.
Wenn man einen Datenstream empfängt, erfolgt dies nach einem Protokoll,
damit man das Ende eines Frames erkennen kann.
Bei Textdaten fügt man in der Regel ein 0-Byte an und übergibt den
String dann zur Auswertung.
Bei Binärdaten übergibt man zusätzlich die Länge des Datenfeldes, da
dieses ja auch 0-Bytes enthalten kann.
Es gibt also nirgends den Zustand, daß vorher etwas gelöscht werden muß.
Der ganze Ansatz, erst mal die einlaiufenden Zeichen in einem weiteren
char-Array zwischenzuspeichern, bis ein nicht-digit daher kommt, und das
ganze dann atoi vorzuwerfen, ist schon Quatsch.
Eine Zahl wird um die jeweils nächste Stelle erweitert, indem man die
Zahl mal 10 nimmt und dann die nächste Ziffer addiert. Genau mit diesem
Mechanismus hängt man zb an die Zahl 86 die nächste Ziffer 5 an: 86 * 10
macht 860. da dann noch die 5 addiert, ergibt 865
Sobald du das Kommando erkannt hast:
setzt die eine entsprechende int-Variable auf 0
für jedes weitere erkannte Zeichen, welches zur Ziffer gehört, wird dann
die Zahl entsprechend um diese Ziffer erweitert
1
intZahl=0;
2
3
n=2;
4
while(isdigit(uart_empfangsbuffer[n]))
5
Zahl=Zahl*10+(uart_empfangsbuffer[n]-'0');
6
7
// ev. noch Prüfungen machen, ob zb die erwartete Zahl innerhalb
8
// von vordefinierten Limits liegt
9
10
// und dann setzen
11
12
OCR2=Zahl;
kein Mensch muss da Character umkopieren. Kostet nur Zeit und man läuft
Gefahr Arrays zu überlaufen.
Man könnte auch atoi direkt auf den Empfangsbuffer ansetzen
1
intZahl=atoi(&uart_empfangsbuffer[2]);
2
OCR2=Zahl;
denn atoi macht ja grundsätzlich auch nichts anderes. In der
eigenständigen Schleifenversion hat man den Vorteil, dass man auf
eventuelle Fehler noch besser reagieren könnte, während man bei atoi
erst mal am Ergebnis nicht ablesen kann, ob da zb überhaupt eine 'Zahl'
im String enthalten war. Dafrü kann atoi selbstverständlich mit einem
'-' umgehen, was man der Schleifenversion erst noch beibringen müsste,
wenn das relevant ist.
Dafür kann man die Schleifenversion in einer etwas 'auseinander
genommenen' Version auch wunderbar in einer Statemachine unterbringen.
1
...
2
3
while(1)
4
{
5
charc=nextCharacterfromUartifoneexists
6
7
switch(state)
8
{
9
caseExpectCommand:
10
if(c='P')
11
{
12
state=ExpectPWMNumber;
13
PWMValue=0;
14
}
15
16
break;
17
18
caseExpectPWMNumber:
19
if(isdigit(c))
20
PWMValue=10*PWMValue+(c-'0');
21
22
else
23
{
24
OCR2=PWMValue;
25
state=ExpectCommand;
26
}
27
break;
28
...
29
}
Du hast da wieder zielsicher die komplizierteste Lösung rausgesucht.
Bitte einen Namen eingeben (nicht "Gast") oder ein schrieb im Beitrag
#3869491:
> Peter II schrieb:>> warum sollte das Quatsch sein?>> Weil es halt Quatsch ist. Lies ein C-Buch.
habe ich, dort steht drin das damit das ganze Array mit 0 initialisiert
wird.
Bitte einen Namen eingeben (nicht "Gast") oder ein schrieb im Beitrag
#3869522:
> Peter II schrieb:>> dort steht drin das damit das ganze Array mit 0 initialisiert>> wird.>> Ganz sicher nicht.
doch ganz sicher. Eventuell sollte du mal nachlesen. Dort wo etwas über
Initialisierung von Array steht.
Peter II schrieb:> Bitte einen Namen eingeben (nicht "Gast") oder ein schrieb im Beitrag> #3869522:>> Peter II schrieb:>>> dort steht drin das damit das ganze Array mit 0 initialisiert>>> wird.>>>> Ganz sicher nicht.>> doch ganz sicher.
Vorsicht. Wortwahl.
Das kann keine Initialisierung sein, weil hier keine Definition eines
Arrays vorliegt. Das ist eine ganz normale Zuweisung.
Peter II schrieb:> doch ganz sicher.
Nein. Du verwechselst eine Initialisierung mit einer Zuweisung.
Hier handelt es sich um eine Zuweisung. Und die ist, wenn überhaupt
gültig, außerhalb des Arrays.
Karl Heinz schrieb:> Vorsicht. Wortwahl.>> Das kann keine Initialisierung sein, weil hier keine Definition eines> Arrays vorliegt. Das ist eine ganz normale Zuweisung.
oh, sorry mein fehler.
Ich hatte
[c]
uint8_t zwischenzustand_array [ZWISCHENZUSTAND_ARRAY_SIZE] = { 0 }
[\c]
für mich gelesen.
Peter Dannegger schrieb:> In der Regel garnicht.>> Wenn man einen Datenstream empfängt, erfolgt dies nach einem Protokoll,> damit man das Ende eines Frames erkennen kann.> Bei Textdaten fügt man in der Regel ein 0-Byte an und übergibt den> String dann zur Auswertung.> Bei Binärdaten übergibt man zusätzlich die Länge des Datenfeldes, da> dieses ja auch 0-Bytes enthalten kann.> Es gibt also nirgends den Zustand, daß vorher etwas gelöscht werden muß.
Oh ok.
Dieses Schema muss ich auch befolgen. Zuerst habe ich ein 0-Byte
(startbyte), den String habe ich auch.
Aus diesen String muss ich aber gewisse Zeichen rauslesen, und diese
Zeichen sind mein Wert für das PWM signal.
Mfg,
tommyProg
Bitte einen Namen eingeben (nicht "Gast") oder ein schrieb im Beitrag
#3869501:
> Was ist überhaupt "löschen"?
In meinem Fall würde ich sagen, die Inhalte des Arrays komplett durch
00ler verschieben, und anschließend das stringende Zeichen auf die 0te
Position ganz links setzen.
Das würde ich jetzt übrigens auch ausprobieren, vielleicht liegt es am
Stringende Zeichen.
Übrigens, ich hatte das Programm schon fertig, in einen
Zustandsautomaten, dort lief es einwandfrei, und ich musst weder was
ändern, noch ein Stringende zeichen hinzufügen.
Nur ist es mit ca. 15 Zuständen nicht besonders komfortabel lesbar.
Mfg (und noch am ausprobieren)
tommyProg
So, also ich habe nun ein Stringende Zeichen bei den passenden Stellen
ergänzt, und nun funktionieren wenigstens die Werte von 1-99 einwandfrei
und überschreiben sich nichtmehr.
Code im Anhang.
Die 4te Position habe ich allerdings noch nicht belegt.
Nun, höchstwahrscheinlich ist genau da der Fehler.
Ich muss ihn sagen, dass, wenn die 5te Position keine Zahl ist, schreibe
ein Stringende Zeichen auf die 3te Position meines Arrays (4.stelle).
Danke Karl übrigens für die Idee, den unteren Code
mit
1
while(1)
2
{
3
charc=nextCharacterfromUartifoneexists
4
5
switch(state)
6
{
7
caseExpectCommand:
8
if(c='P')
9
{
10
state=ExpectPWMNumber;
11
PWMValue=0;
12
...
kann ich aber garnicht lesen, ich weiß nicht zu 100% Sicherheit, was das
if da auf meine Laufzeit bewirkt. (das schaue ich aber demnächst auch
mal an, weil es schon viel kürzer ist) Aktuell prüfe ich jetzt noch mal
die 5te stelle des arrays.
Danke übrigens euch allen für die schnellen Antworten ;)
Mfg,
tommyProg
Tho Wes schrieb:> So, also ich habe nun ein Stringende Zeichen bei den passenden Stellen> ergänzt, und nun funktionieren wenigstens die Werte von 1-99 einwandfrei> und überschreiben sich nichtmehr.>> Code im Anhang.>> Die 4te Position habe ich allerdings noch nicht belegt.> Nun, höchstwahrscheinlich ist genau da der Fehler.> Ich muss ihn sagen, dass, wenn die 5te Position keine Zahl ist, schreibe> ein Stringende Zeichen auf die 3te Position meines Arrays (4.stelle).>> Danke Karl übrigens für die Idee, den unteren Code> mit>
1
>while(1)
2
>{
3
>charc=nextCharacterfromUartifoneexists
4
>
5
>switch(state)
6
>{
7
>caseExpectCommand:
8
>if(c='P')
9
>{
10
>state=ExpectPWMNumber;
11
>PWMValue=0;
12
>...
13
>
>> kann ich aber garnicht lesen, ich weiß nicht zu 100% Sicherheit, was das> if da auf meine Laufzeit bewirkt. (das schaue ich aber demnächst auch> mal an, weil es schon viel kürzer ist) Aktuell prüfe ich jetzt noch mal> die 5te stelle des arrays.> Danke übrigens euch allen für die schnellen Antworten ;)>> Mfg,> tommyProg
So, also die Überprüfung auf die Stelle habe ich nun implementiert und
getestet, und nun läufts einwanfrei, nur muss ich es noch vereinfachen.
Da hatte ich mal so eine schöne for-schleife...
Ehm, eine Frage von der Logik her:
Bei einem Zustandsautomaten mit 15 (fast einzelnen Zuständen) musste ich
kein Stringende zeichen auf die jeweilige Position einfügen, und das
Programm lief enormst stabil.
Nun ist es so, dass ich ein Stringende Zeichen einfügen muss, wenn ich
12 Zustandsautomaten zu einen "reinen" programmcode mache.
Warum ist das so?
mfg,
tommyProg
Peter II schrieb:> Eric B. schrieb:>>> zwischenzustand_array[ZWISCHENZUSTAND_ARRAY_SIZE] = { 0 };>>>> Das ist Quatsch. Du brauchst entweder:>> warum sollte das Quatsch sein?
Weil man ein einzelnes Element ausserhalb vom Array nicht ein
komplettes Array zuweisen soll.
Tho Wes schrieb:> case ExpectCommand:> if( c = 'P' )> {> state = ExpectPWMNumber;> PWMValue = 0;> ...> [/c]>> kann ich aber garnicht lesen, ich weiß nicht zu 100% Sicherheit, was das> if da auf meine Laufzeit bewirkt.
Das ist auch ein Fehler, der dem Tippen im Forum geschuldet ist.
Da sollte eigentlich ja auch
1
if(c=='P')
stehen :-)
Und wegen Laufzeit.
Ganz ehrlich: Bei dem Käse, den du da zusammenprogrammierst, solltest du
dir um Laufzeit überhaupt noch keine Sorgen machen. Denn egal was du als
Alternative machst, noch schlimmer kann man das schon fast nicht mehr
programmieren.
> Das ist auch ein Fehler, der dem Tippen im Forum geschuldet ist.> Da sollte eigentlich ja auch>
1
>if(c=='P')
2
>
> stehen :-)> Und wegen Laufzeit.> Ganz ehrlich: Bei dem Käse, den du da zusammenprogrammierst, solltest du> dir um Laufzeit überhaupt noch keine Sorgen machen. Denn egal was du als> Alternative machst, noch schlimmer kann man das schon fast nicht mehr> programmieren.
Okay, das sehe ich als kompliment an, weil dann heißt das ja, dass ich
nurnoch besser werden kann xD.
Aber warum muss ich die Stringende Zeichen seperat ergänzen, wenn ich
einen Zustandsautomaten "aufspalte"?
Tho Wes schrieb:> Aber warum muss ich die Stringende Zeichen seperat ergänzen, wenn ich> einen Zustandsautomaten "aufspalte"?
Du musst das Stringende IMMER ergänzen, wenn du einen String aus
einzelnen Zeichen zusammensetzt! Es sei denn in den Zeiten, die du
zusammensetzt ist das Stringende-'\0' schon mit drinn. Trotzdem wird man
eher auf Nummer sicher gehen. Die paar Taktzyklen kosten nichts.
> Okay, das sehe ich als kompliment an, weil dann heißt das ja, dass> ich nurnoch besser werden kann xD.
Nimms nicht tragisch. Mein erster Sortieralgorithmus war auch furchtbar.
Kryptisch, komplex unwartbar und wenn der Mond günstig gestanden ist,
hat er sogar funktioniert. Allerdings hab ich dann schnell gelernt, wie
man sowas richtig macht. Lange bevor ich mein erstes richtiges Projekt
begonnen habe. Aber das macht nichts. Selbst für ein Übungsprogramm war
er fuchtbar, kryptisch und unwartbar - sprich inakzeptabel. Nachdem ich
gesehen habe, wie man sowas richtig und vernüftig angeht, war mir auch
klar, dass mir noch viel fehlt, ehe ich an ein echtes Projekt auch nur
denken kann.