Forum: Mikrocontroller und Digitale Elektronik Prüfsumme Profibus Problem


von Sven R. (sveniii)


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

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Typecast auf uint16_t überall rein machen?

von Sven R. (sveniii)


Lesenswert?

hallo,

doch noch Einer munter ;)

wie soll ich das machen beim C-Compiler?
Ich habe alle mit char definiert,
dannn müsste es doch automatisch mit 8 bit rechnen, auch unsigned char 
brachte keine Verbesserung...

von Sven R. (sveniii)


Lesenswert?

und beim Senden rechne ich ja genau so,
und die Summe stimmt, der Master akzeptiert es und auch auf dem LA...

von Stefan W. (dl6dx)


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

von Sven R. (sveniii)


Lesenswert?

Danke,
das ist der mikroC Compiler

ich schau dann mal ob er die uint Kommandos kennt...

aber müsste es dann nicht auch bei der TX Prüfsumme Probleme geben,
welche ich genauso berechne?

von Stefan W. (dl6dx)


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

von Sven R. (sveniii)


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.. :-(

von Stefan W. (dl6dx)


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

von Sven R. (sveniii)


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ß

von Stefan W. (dl6dx)


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

von Sven R. (sveniii)


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

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.