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
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...
und beim Senden rechne ich ja genau so, und die Summe stimmt, der Master akzeptiert es und auch auf dem LA...
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
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?
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
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.. :-(
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
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ß
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.