Forum: Compiler & IDEs Nicht nachvollziehbares Verhalten!


von heinzelmännchen (Gast)


Lesenswert?

Guten Morgen,
ich bin so langsam am verzweifeln.
Ich habe ein Programm geschrieben welches über Rs485 mit zwei anderen 
Baugruppen kommuniziert.Soweit funktioniert auch alles wie es soll.
Hier die relevanten Codestellen.
1
uint16_t output_Data[2];
2
3
output_Data[0]=0x0500;
4
output_Data[1]=0x0500;
5
6
if (requesttimeout==0)     // Daten Austausch mit den Endstufen!
7
{
8
      if (chanal >3)
9
      {
10
        chanal=1;
11
      }
12
      if (chanal==1)
13
      {
14
        request(1,1,output_Data[(chanal-1)]);
15
      }
16
      if (chanal==2)
17
      {
18
        request(2,1,output_Data[(chanal-1)]);
19
      }
20
      chanal++;
21
}
22
void request(uint8_t add,uint8_t command,uint16_t data)
23
{
24
  POUT.add=add;
25
  POUT.command=command;
26
  POUT.data=data;//&=0b11111011;
27
  POUT.crc = CalcCRC16((uint8_t*)&POUT,5);
28
  Transmit((u8 *)&POUT,sizeof(POUT));
29
}
30
void Transmit(u8 *cData,uint8_t len)
31
{
32
  while(len-- > 0)
33
  {
34
    uart_putc( *cData++);// shift out data
35
  }
36
37
}
Zum meinem Problem.
im oberen Byte von output_Data wird der duty cycle vom Ventilator 
übertragen im unterem Byte von output_Data werden Steuer Bit übertragen.
Nun passiert es das obwohl output_Data den Wert 0x0500 hat trotzdem das 
3.Bit im unterem Byte gesetzt wird.
Wenn ich jedoch in Funktion POUT.data=data&=0b11111011; das 3.Bit aus 
maskiere passiert nichts.
wie kann es passieren das ein Bit einfach so gesetzt wird.

Bin mit meinem Latein total am ende.
Danke für Eure hilfe

Fredi

von Johann L. (radiostar)


Lesenswert?

Deine Ausmaskierung mittels &= halte ich für falsch. Da &= den gleichen 
Vorrang hat wie = wäre ich mir nicht sicher, ob data vo oder nach der 
Maskierung an POUT.data zugewiesen wird. Mag sein, daß es stimmt, wie Du 
es gemacht hast, aber was passiert denn, wenn Du schreibst:

POUT.data = data&0b11111011;

und was passiert, wenn Du scheibst:

POUT.data = 0;

ist dann Bit 3 immer noch gesetzt?

von (prx) A. K. (prx)


Lesenswert?

J. L. schrieb:
> Deine Ausmaskierung mittels &= halte ich für falsch. Da &= den gleichen
> Vorrang hat wie = wäre ich mir nicht sicher, ob data vo oder nach der
> Maskierung an POUT.data zugewiesen wird.

Ist rechts-assoziativ, also kommt erst der rechte Teil, dann der linke.

von MaWin (Gast)


Lesenswert?

Du bildest die CRC über 5 Byte obwohl add,  command und data zusammen 
nur 4 haben. Was ist noch in der Struktur ? Wie ist ihr Alignment? Und 
was heißt das dubiose chanal?

von Johann L. (radiostar)


Lesenswert?

A. K. schrieb:
> Ist rechts-assoziativ, also kommt erst der rechte Teil, dann der linke.

Weiß ich. Aber auch Compiler haben Fehler.

von hp-freund (Gast)


Lesenswert?

heinzelmännchen schrieb:
> if (chanal >3)

Was passiert wenn chanal==3 ?

von heinzelmännchen (Gast)


Lesenswert?

Danke für die Antworten.


J. L. schrieb:
> was passiert denn, wenn Du schreibst:
>
> POUT.data = data&0b11111011;
>
> und was passiert, wenn Du scheibst:
>
> POUT.data = 0;
>
> ist dann Bit 3 immer noch gesetzt?

In beiden Fällen ist Bit 3 nicht gesetzt!

MaWin schrieb:
> Du bildest die CRC über 5 Byte obwohl add,  command und data zusammen
> nur 4 haben. Was ist noch in der Struktur ? Wie ist ihr Alignment? Und
> was heißt das dubiose chanal?

Die Struktur siet so aus
1
typedef volatile struct // 7 Byte
2
{
3
  uint8_t start;
4
  uint8_t add;
5
  uint8_t command;
6
  uint16_t data;
7
  unsigned int crc;
8
}protoOut;

hp-freund schrieb:
> Was passiert wenn chanal==3 ?

Dann passiert momentan nichts!

LG
Fredi

von heinzelmännchen (Gast)


Lesenswert?

Wie kann ich vorgehen den Fehler zu finden?

Lg
Fredi

von Peter D. (peda)


Lesenswert?

Man müßte erstmal wissen, welches Protokoll Du zur Übertragung benutzt 
und ob sich dieses Protokoll nach einem Übertragungsfehler wieder selbst 
synchronisieren kann.

Ein MC kann nämlich nicht hellsehen, welches Byte in einem Datenstrom 
das erste und welches das letzte ist. Daher muß man erstmal eine 
eindeutige Vorschrift zur Erkennung definieren. Diese Vorschrift ist das 
Protokoll.

von heinzelmännchen (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Man müßte erstmal wissen, welches Protokoll Du zur Übertragung benutzt
> und ob sich dieses Protokoll nach einem Übertragungsfehler wieder selbst
> synchronisieren kann.

Es gibt ein Protokoll das auch funktioniert.
Mein Problem ist das in meinem output_Data aus irgend einem Grund das 3. 
Bit gesetzt wird!
Ich habe die meiner Meinung wichtigen Code stellen gepostet.
Ich kann aber wenn es zur Fehleranalyse hilft den Kompletten Code 
posten.

Vielen Dank für Deine Hilfe

Fredi

von Walter S. (avatar)


Lesenswert?

heinzelmännchen schrieb:
> POUT.data=data&=0b11111011;

ist das die Anweisung die nicht das macht was du willst?

von heinzelmännchen (Gast)


Lesenswert?

Guten Morgen,

Walter S. schrieb:
>> POUT.data=data&=0b11111011;
>
> ist das die Anweisung die nicht das macht was du willst?

Nein die Anweisung macht genau das was ich will!
Mit dieser Anweisung Maskiere ich das Fehlerhaft gesetzte Bit 3 aus(Ich 
setze Bit3 im ganzen Programm nicht und trotzdem wird es am und zu 
gesetzt )

Die Markierung Funktioniert ich möchte aber verstehen  warum Bits 
einfach von alleine gesetzt werden!

Vielen Dank


Fredi

von Karl H. (kbuchegg)


Lesenswert?

Im geposteten Code gibt es keine Erklärung für dein gesetztes 3. Bit.
Das Problem wird wohl irgendwo im restlichen Code stecken.

von heinzelmännchen (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe jetzt das ganze Projekt angehängt!
Ist leider relativ groß!
Kann mir jemand Tips geben wie ich meinen Fehler finden kann?

Vielen Dank

Fredi

von Karl H. (kbuchegg)


Lesenswert?

Hier zb wird in deinem Code Bit 3 bei Bedarf gesetzt
1
      if ((Temp[0]>menuParameters[FAN_TEMP])||(Temp[1]>menuParameters[FAN_TEMP])||(Temp[2]>menuParameters[FAN_TEMP])||(Temp[3]>menuParameters[FAN_TEMP]))
2
      {
3
        output_Data[0] |= 0x04;
4
        output_Data[1] |= 0x04;
5
      }
6
      else if ((Temp[0]<(menuParameters[FAN_TEMP]-menuParameters[TEMPHYST]))&&(Temp[1]<(menuParameters[FAN_TEMP]-menuParameters[TEMPHYST]))&&(Temp[2]<(menuParameters[FAN_TEMP]-menuParameters[TEMPHYST]))&&(Temp[3]<(menuParameters[FAN_TEMP]-menuParameters[TEMPHYST])))
7
      {
8
        output_Data[0] &= ~0x04;
9
        output_Data[1] &= ~0x04;
10
      }

ergo würde ich da mal ansetzen und nachsehen, was da eigentlich so für 
Werte rauskommen, bzw. welcher Wert mit welchem anderen Wert verglichen 
wird.

Du hast ein LCD. Benutze es, um dir Werte auszugeben. Verdonnere dein 
Programm dazu, dir zu helfen und nicht nur irgendwelche Menüs 
hinzuzaubern.

von troll (Gast)


Lesenswert?

Und nebenbei bemerkt, diese &&-Bandwürmer kann man problemlos auf 
mehrere Zeilen aufteilen... Wirklich übersichtlich ist das nämlich 
nicht.

von Karl H. (kbuchegg)


Lesenswert?

Beispielsweise ist das hier
1
void ParameterRestor(void)
2
{
3
  eeprom_read_block(scaleoffset,EE_saleoffset,sizeof(scaleoffset));
4
  eeprom_read_block(menuParameters,EE_menuParameters,sizeof(menuParameters));
5
  for (uint8_t i =0;i<MENU_SIZE;i++)
6
  {
7
    if ((menuParameters[i]<MENU_LIMITS_MIN[i])||(menuParameters[i]>MENU_LIMITS_MAX))

ziemlich sicher nicht das, was du willst. Man beachte, dass 
MENU_LIMITS_MAX ohne Array Indizierung benutzt wird. Verblüfft mich, 
dass dein Compiler dazu nichts zu sagen hatte.
Mit einer besseren Schreibweise, bei der man nicht auf alle Leerzeichen 
verzichtet und nicht unbedingt alles in eine Zeile quetscht, sondern 
auch mal einen Zeilenumbruch zur optischen Gliederung einführt
1
    if (( menuParameters[i] < MENU_LIMITS_MIN[i] ) ||
2
        ( menuParameters[i] > MENU_LIMITS_MAX ) )
3
      menuParameters[i] = MENU_LIMITS_MIN[i];

hätte man das sogar sehen können, dass es hier eine optische 
'Inkonsistenz' gibt, weil die beiden schliessenden Klammern der 
Einzelausdrücke nicht untereinander stehen.





Generell:
Wenn mehrere Dinge logisch zusammengehören, wie bei dir
  Menüpunkt-Text
  aktueller Wert
  minimaler Wert
  maximaler Wert

dann ist es vernünftig, diesen Zusammenhang dadurch zu unterstreichen, 
dass du dir eine Struktur definierst, in der du diese Zusammenfassung 
sichtbar machst. Parallele Arrays dafür zu führen ist eine 
fehleranfällige Sache. Der wichtigere Zusammenhang ist der der 
Einzelteile untereinander und nicht, dass es mehrere davon gibt. Genauso 
wie bei einem Datum der Zusammenhalt Tag/Monat/Jahr der wichtigere ist, 
und nicht, dass du 25 Tage, 25 Monate und 25 Jahre im Programm speichern 
musst, weil du 25 Geburtstage (also 25 unterschiedliche Datümer) 
speichern musst. Zuinnerst steht erst mal das Datum an sich, und dann 
erst kommt die Hierarchieebene, dass es 25 Stück davon gibt.
1
struct paramValue
2
{
3
  int16_t     actValue;
4
  int16_t     minValue;
5
  int16_t     maxValue;
6
  const char* menueText;
7
};

damit hast du erst mal diesen Zusammenhang geschaffen. Ein paramValue 
(also ein "Parameter-Wert" besteht IMMER aus diesen Komponenten.

Und dann definierst du dir ein Array derartiger Parameter-Werte.
1
struct paramValue paramValues[] =
2
{
3
  { 0, 20,  80, " Fan aktTemp    " },
4
  { 0,  1, 253, " PWM_Backlight  " },
5
  { 0,  1,   1, " Temp Hyst      " },
6
  { 0,  5,  10, " Calib Voltage1 " },
7
  { 0, 10,  20, " Calib Voltage2 " },
8
  { 0,  0,   0, " Calib Voltage3 " },
9
  { 0,  0,   0, " Calib Voltage4 " },
10
};
11
12
#define PARAM_SIZE  sizeof( paramValues ) / sizeof( *paramValues )

und damit arbeitest du dann in weiterer Folge.
Du hast das komplette Array von paramValues.
Von diesem Array einen spezifischen Eintrag, zb
paramValues[0], oder paramValues[1], oder paramValues[i]
wobei jeder einzelne dieser Array-Einträge ein komplettes struct 
paramValue Objekt ist. Du kannst zb einen Zeiger auf ein derartiges 
Objekt an eine Funktion übergeben, und diese Funktion hat dann alles 
beisammen, was sie zur Eingabebehandlung dieses Wertes benötigt.
zb. benötigt sie den minimalen Wert des i-ten Parameter Objektes. Dann 
ist das
  paramValues[i].minValue


Und strukturier deinen Code besser, in dem du ihn in Funktionsgruppen 
aufteilst und dafür Einzelfunktionen machst.

Und: nein. Das Argument 'ich wusste nicht, dass es sowas wie Strukturen 
gibt' lass ich nicht gelten. Wer reale Programme schreiben will, muss 
zumindest das erste Drittel vom K&R durchgearbeitet haben. Wer echte 
Arbeit machen will, muss auch sein Werkzeug wenigstens ansatzweise 
kennen.

von heinzelmännchen (Gast)


Lesenswert?

Danke für Deine Ausführliche Antwort!
Danke für Deine Anregungen und Tips!

LG
Fredi

von heinzelmännchen (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Und strukturier deinen Code besser, in dem du ihn in Funktionsgruppen
> aufteilst und dafür Einzelfunktionen machst.

Was genau meinst Du damit?

Danke LG
Fredi

von Karl H. (kbuchegg)


Lesenswert?

heinzelmännchen schrieb:
> Karl Heinz Buchegger schrieb:
>> Und strukturier deinen Code besser, in dem du ihn in Funktionsgruppen
>> aufteilst und dafür Einzelfunktionen machst.
>
> Was genau meinst Du damit?

Das es nicht sinnvoll ist eine Funktion main() zu haben, die sich über 5 
Bildschirmseiten hinzieht.

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
Noch kein Account? Hier anmelden.