Prüfsumme Profibus Problem

OP #3017640
Lesenswert?

Hallo,

Habe heut mal ein kniffliges Problem:

Ich hänge mit einem max485 und 48Mhz PIC an einem Profibus DP.
soweit so gut.
alles funktioniert erstaunlich gut, auch das berechnen der TX Prüfsumme
(sonst würde ja der Master auch meckern...)
was NICHT funktionier ist die Auswertung der eingehenden Prüfsumme.
Und das obwohl auf dem LA alles arithmetisch stimmt.

ich berechne die Prüfsumme so:
RFCS = 
DA+SA+FC+DATA[1]+DATA[2]+DATA[3]+DATA[4]+DATA[5]+DATA[6]+DATA[7]+DATA[8] 
+DATA[9]+DATA[10]+DATA[11]+DATA[12]

die Nutzdaten wahlweise auch bei variabler Länge in einer Schleife 
addiert,
funkt aber auch nicht.

also nochmal wenn ich die Werte aus dem LA abschreibe und 
zusammenaddiere,
dann stimmt es mit der PS überein.
Aber wenn das Programm es machen soll, dann geht gar nichts mehr,
weil ich dann einen Sprung zum Ende mache.

gibt es da noch einen Trick? oder sowas?
klar, die Schaltung läuft auch ohne Prüfsumme beim Empfangen,
ich möchte es aber halbwegs professionell machen.

 Grüße Sven
#3017890
Lesenswert?

Sven R. schrieb:
> auch unsigned char brachte keine Verbesserung

Interessant. Welcher Compiler?
Welchen Datentyp hat deine Variable für die Prüfsumme?

Die Prüfsumme wird über die vorzeichenlose Addition aller 
Telegrammelemente berechnet, wobei bei der Addition ein 
Wertbereichsüberlauf ignoriert wird.

Hier ist die Frage, was der Compiler bei "unsigned char" und einem 
Overflow anstellt. C89[1] sagt dazu nämlich nur, dass die Verwendung der 
char-Datentypen zu anderen Zwecken als dem Speichern von Zeichen 
implementationsabhängig ist.

Wenn dein Compiler uint8_t kennt, nimm mal den Typ für die 
Summenvariable. Sonst nimm unsigned int und schneide zum Schluss mit 
(summe & 0xFF) die höherwertigen Bits ab.

Grüße

Stefan

[1] K&R 2. Ausgabe
#3018056
Lesenswert?

Sven R. schrieb:
> aber müsste es dann nicht auch bei der TX Prüfsumme Probleme geben,
> welche ich genauso berechne?

Da gibt es mehrere Möglichkeiten, warum es doch funktionieren könnte.

Welche das ist, weiß ich nicht, meine Glaskugel ist leider gerade 
verliehen.

Aber zeig doch mal den entsprechenden Code, dann sehen wir weiter.

Grüße

Stefan
OP #3018114
Lesenswert?

ok,
ich zeige mal paar Ausschnitte der Berechnung, der ganze code wäre 
zulang
..

Berechnung RX:

 VARIA:
 DATleng=Leng-9;// Nutzdatenlaenge

 SD2 = RByte[1];
 LE  = RByte[2];
 LER = RByte[3];
 SD2x= RByte[4]; //Konstantenzuweisung
 DA  = RByte[5]; // Empfängeradr,
 SA  = RByte[6]; // Absender (01 PLC)
 FC  = RByte[7];
 FCS = RByte[Leng-1];
 ED  = RByte[Leng];
 b=1;

 do {
 DATA[DATleng]=RByte[DATleng+7];
 RFCS=RFCS+DATA[DATleng];
 DATleng--;
 }while (DATleng>0);  //Datenblock zuweisen.

 RFCS = RFCS+DA+SA+FC; 
//+DATA[1]+DATA[2]+DATA[3]+DATA[4]+DATA[5]+DATA[6]+DATA[7]+DATA[8]+DATA[ 
9]+DATA[10]+DATA[11]+DATA[12]  ;
 if(DA==0X02){
 if (FCS!=RFCS) goto END; // Prüfsumme checken    (funkt nicht!!)
 }


Berechnung TX:

   i=1;

   TByte[1]= 0X68;
   TByte[2]= 0X0F;
   TByte[3]= 0X0F;
   TByte[4]= 0X68;
   TByte[5]= 0X01; //Empfänger
   TByte[6]= DA; // Absender
   TByte[7]= 0X08; // FC Standtart Anwort
   TByte[8]= 0X00; //DATEN
   TByte[9]= 0X00;
   TByte[10]=0X00;
   TByte[11]=0X00;
   TByte[12]=0X00;
   TByte[13]=0X00;
   TByte[14]=0X00;
   TByte[15]=0X00;

   TByte[21]=0X16;

   TFCS= 
TByte[5]+DA+TByte[7]+TByte[8]+TByte[9]+TByte[10]+TByte[11]+TByte[12]+TBy 
te[13]+TByte[14]+TByte[15]+TByte[16]+TByte[17]+TByte[18]+TByte[19];

    TByte[20]=TFCS;
   delay_us(10);

  do{
  if(PIR1.TXIF==1){

  Rest= TByte[i]; //  Paritäts Berechnung
  Rest ^= Rest >> 4;          // xor bit wise: 0=0^4, 1=1^5, 2=2^6, 
3=3^7
  Rest ^= Rest >> 2;          // xor bit wise: 0=0^2, 1=1^3
  Rest ^= Rest >> 1;
  PAR = Rest & 1;

  TXSTA.TX9D= PAR;
  TXREG=TByte[i];
  i++;
  }

  } while (i<22);

sicher etwas unübersichtlich, bin kein gelernter Programmierer.. :-(
#3018979
Lesenswert?

Sven R. schrieb:
> sicher etwas unübersichtlich

Bitte unterschätze niemals die Wichtigkeit eines gut lesbaren 
Quelltextes. Im "Gestrüpp" übersieht man leichter Fehler.

Ok, jetzt zum inhaltlichen:

Es fehlen alle Variablendefinitionen. Die sind aber für die Frage, was 
falsch läuft, eminent wichtig.

Ein paar grundsätzliche Gedanken zur Prüfsummenberechnung: So gut wie 
alle Prüfsummen, CRC etc. werden über alle Elemente der Nachricht 
berechnet.
Nach der Profibus-Spec Abschnitt 4.7.4 wird die FCS über alle Elemente 
zwischen SD und FCS/ED berechnet.

Deshalb empfiehlt es sich, das auch so zu machen. Du hast anscheinend 
die empfangene Nachricht im Array RByte[]. Dann berechne sie auch direkt 
über die Elemente des Arrays. Wenn ich die Organisation dieses Puffers 
richtig verstanden habe, also von RByte[1] (Byte nach SD) bis RByte[Leng 
- 2] (Byte vor der empfangenen FCS). Damit sollte das eigentlich passen:
1
uint8_t fcs = 0;
2

3
for (i = 1; i < (Leng - 1); ++i)
4
  {
5
  fcs += RByte[i];
6
  }
7
// i zeigt jetzt auf die empfangene FCS
8
if (fcs != RByte[i])
9
  {
10
  // FCS-Fehler, Nachricht verwerfen
11

12
  }

Grüße

Stefan
OP #3019207
Lesenswert?

Hallo Stefan,

bei mir steht das aber so geschrieben :

"Beim Format ohne Daten (SD1) muss die Prüfsumme durch die arithmetische 
Summe von DA, SA, und FC
ohne Start- (SD) und End-delimiter (ED) und ohne Berücksichtigung der 
Überträge gebildet werden. Bei den
Formaten fester Länge mit Daten (SD3) und variabler Länge (SD2) muss die 
Prüfsumme noch zusätzlich die
Nutzdaten (PDU) mit einbeziehen."

also ab DA-FC?

Gruß
#3019333
Lesenswert?

Sven R. schrieb:
> die arithmetische Summe ohne Berücksichtigung der Überträge
> ohne Start- (SD) und End-delimiter (ED)

> Format ohne Daten (SD1)
> DA, SA, und FC

DA ist das erste Zeichen nach SD1, FC das letzte Zeichen vor der FCS.

> Bei den Formaten fester Länge mit Daten (SD3) und variabler
> Länge (SD2) muss die Prüfsumme noch zusätzlich die
> Nutzdaten (PDU) mit einbeziehen

Also der Block von DA (einschl.) bis zum letzten Byte der Nutzdaten (das 
letzte Zeichen vor der FCS)...

Die Formulierung der Norm ist nicht besonders toll, aber eindeutig.

Du rechnest immer vom ersten Byte der Nachricht nach dem Start Delimiter 
(bei allen Nachrichtentypen mit FCS ist das DA) bis zum letzten Byte vor 
der FCS (FC bei SD1 bzw. das letzte Byte der PDU bei SD2 und SD3).

Danach hast du die "Soll-FCS" und kannst sie beim Senden anhängen bzw. 
beim Empfang vergleichen.

Grüße

Stefan
OP #3020077
Lesenswert?

hallo

ich habs jetzt so geschrieben
und da gehts:

 for(j=5;j<Leng-2;j++){
 RFCS = RFCS + RByte[j];
 }

 if (RByte[j]!=RFCS) goto END;

war wohl vorher irgendwie ein Byte daneben, oder so?
keine Ahnung mit dem unit8 hats nichts zu tun den nimmt der Comp nicht 
an.

vielen Dank für die Hilfe!

Grüße Sven

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren