PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : CRC8 <==> SAE J1850 - Was mache ich falsch?



CarHifiStore
08.03.2009, 18:40
Hallo,

auf Empfehlung bin ich nun hier im Robonetz gelandet - wenn es hier keine Lösung gibt geht es nicht, hieß es ;-)

Mein Problem: Ich muss eine CRC-Checksumme nach SAE J1850-Standart über 10 Datenbytes erstellen. Die Bascom-CRC-Routine kann ich nicht nehmen weil sie 8C (Dallas) als Generatorpolynom nimmt. Nach Wiki muss ich 1D als Polynom nehmen. Also hab ich mir eine Routine geschrieben bei der ich das Polynom frei einsetzen kann:



Dim Ar(10) As Byte
Dim Temp1 As Byte ' Temporäre Variable
Dim Temp2 As Byte ' Temporäre Variable

Dim X As Byte

Dim Crc As Byte
Dim Crcpoly As Byte

Dim Bytecounter As Byte
Dim Bitcounter As Byte


Ar(1) = &HB2
Ar(2) = &HD0
Ar(3) = &HE0
Ar(4) = &H70
Ar(5) = &H00
Ar(6) = &H00
Ar(7) = &H00
Ar(8) = &H00
Ar(9) = &H00
Ar(10) = &H00


Crcpoly = &H1D

Gosub Calc_crc


Print Hex(crc)
Crc = Crc8(ar(1) , 10)
Print Hex(crc)

End

Calc_crc:
Crc = 0

For Bytecounter = 1 To 10
Temp2 = Ar(bytecounter)
For Bitcounter = 0 To 7

Temp1 = Temp2 Xor Crc
Temp1 = 1 And Temp1

Shift Crc , Right
Crc = Crc And &HFF

Shift Temp2 , Right
Temp2 = Temp2 And &HFF

If Temp1 <> 0 Then
Crc = Crc Xor Crcpoly

End If


Next


Next

Return


Die Routine funktioniert, wenn ich 8C einsetzte bekomme ich das gleiche Ergebnis wie die CRC8-Routine berechnet.

Setze ich aber die 1D ein bekomme ich nicht das richtige Ergebnis nach J1850 zurück. Hat SAE J1850 noch andere Eigenheiten von denen ich nichts weiß? Habe hier noch zwei Beispiele von kompletten Datensätzen, das letzte Byte ist die CRC die zurückkommen müsste.



'A2 82 50 00 00 00 00 00 00 00 4D
'B2 D0 E0 70 00 00 00 00 00 00 88


Bitte helft mir - Google ist schon heißgelaufen und in der Suche hab ich auch nichts weiteres gefunden.

Gruß Frank

Netzman
08.03.2009, 19:08
Ich habe mal einen Testlauf für CRCPoly von 0 bis 255 durchlaufen lassen, bei keinem Wert kam als Ergebnis &H88, ich vermute also dass deine Routine doch nicht so richtig funktioniert.

Ich weiß nicht ob du bei deiner Recherche darüber gestolpert bist: http://en.wikipedia.org/wiki/Cyclic_redundancy_check , steht eigentlich alles da drin. (Habe auch statt &H1D &HB8, wie in der Tabelle angegeben, probiert, ohne Ergebnis).

mfg

CarHifiStore
08.03.2009, 19:46
Hallo,

jep, das hatte ich auch mal gemacht. Auch die ganzen englischen und deutschen Wiki-Seiten hab ich durch....aber irgendwie ist die Nuss zu hart für mich ;-)
Mit 8C als Polynom bekomme ich identische Ergbenisse wie die Bacom-Routine, daher gehe ich davon aus das die Routine funktioniert.

Ich hab hier noch ein Beispiel welches funktionieren soll, leider in einer Sprache der ich nicht mächtig bin:



// Define Global variables
// message buffer variables
unsigned char msg_buf[20], nbytes, bit_point;
unsigned char * byte_point;
// Switch to select VPW PWM or ISO 0, 1, 2, respectively
unsigned char protocol;
// values to define protocol variable
#define vpw 0
#define pwm 1
#define iso 2
/************************************************** *******************
CRC CALCULATION SUBROUTINE
Calculates the crc as defined by SAE, or the checksum for ISO
************************************************** *******************/
// This routine assumes that all the data bytes are in the array msg_buf[]
// Starting with msg_buf[0] as the first byte.
// nbytes indicates how many bytes are in the array.
// The subroutine calculates both the checksum and the CRC byte as
// defined by SAE and ISO specifications.
// Either the CRC or the Checksum is returned, depending on what
// protocol is selected.
unsigned char crc(void)
{
unsigned char crc_reg=0xff,poly,i,j, checksum=0;
for (i=0, byte_point=msg_buf; i<nbytes; ++i, ++byte_point)
{
for (j=0, bit_point=0x80 ; j<8; ++j, bit_point>>=1)
{
if (bit_point & *byte_point) // case for new bit =1
{
if (crc_reg & 0x80) poly=1; // define the polynomial
else poly=0x1c;
crc_reg= ( (crc_reg << 1) | 1) ^ poly;
}
else // case for new bit =0
{
poly=0;
if (crc_reg & 0x80) poly=0x1d;
crc_reg= (crc_reg << 1) ^ poly;
}
}
checksum += *byte_point; // Calculate checksum
}
if (protocol==iso) return checksum; // Iso uses checksum,
return ~crc_reg; // Otherwise, use CRC


Ohne den Code richtig zu verstehen sind IMHO doch Unterschiede zur "normalen" CRC-Berechnung zu sehen.....vieleicht kann das ja jemand in Bascom übersetzen....

Gruß Frank

Netzman
08.03.2009, 21:22
ich habe mich mal daran versucht, bekomme aber kein richtiges Ergebnis.
Da haperts wahrscheinlich noch an der Übersetzung C->BASCOM...

mein bisheriger Fortschritt:
$regfile = "m32def.dat"

Declare Function Crc_sae(byref Datapointer As Word , Byval Datalength As Byte) As Byte

Dim Ar(10) As Byte , Pointer As Word
Dim Crc As Byte

Ar(1) = &HB2
Ar(2) = &HD0
Ar(3) = &HE0
Ar(4) = &H70
Ar(5) = &H00
Ar(6) = &H00
Ar(7) = &H00
Ar(8) = &H00
Ar(9) = &H00
Ar(10) = &H00
Pointer = Varptr(ar(1))

Crc = Crc_sae(pointer , 10)
Print Crc

End


Function Crc_sae(byref Datapointer As Word , Byval Datalength As Byte) As Byte
Dim Temp As Byte , Temp2 As Byte
Dim I As Byte , J As Byte , Crc_reg As Byte , Poly As Byte
Crc_reg = &HFF

For I = 1 To Datalength
Temp = Inp(datapointer)
Incr Datapointer
For J = 7 To 0 Step -1
If Temp.j = 1 Then
Temp2 = Crc_reg And &H80
If Temp2 <> 0 Then
Poly = 1
Else
Poly = &H1C
End If
Shift Crc_reg , Left , 1
Crc_reg = Crc_reg Or 1
Crc_reg = Crc_reg ^ Poly
Else
Poly = 0
Temp2 = Crc_reg And &H80
If Temp2 <> 0 Then Poly = &H1D
Shift Crc_reg , Left , 1
Crc_reg = Crc_reg ^ Poly
End If
Next
Next
Crc_reg = Not Crc_reg
Crc_sae = Crc_reg
End Function

mfg

CarHifiStore
08.03.2009, 23:47
Hallo Netzman?,

vielen Dank erst mal das Du Dir die Mühe gemacht hast. Jetzt wo die grobe Syntax aufgebröselt ist komme ich vieleicht selber wieder weiter....setze mich Morgen noch mal dran....

Gruß Frank

CarHifiStore
10.03.2009, 21:58
....ich hab den Code - Vielen Dank an Netzmann =D> \:D/

Nur die ^ durch Xor ersetzt und es lief.

Hier noch mal für alle die funktionierende Version:

Crc_reg = &HFF

For I = 1 To 10
Temp = Ar(i)

For J = 7 To 0 Step -1
If Temp.j = 1 Then
Temp2 = Crc_reg And &H80
If Temp2 <> 0 Then
Poly = 1
Else
Poly = &H1C
End If
Shift Crc_reg , Left , 1
Crc_reg = Crc_reg Or 1
Crc_reg = Crc_reg Xor Poly
Else
Poly = 0
Temp2 = Crc_reg And &H80
If Temp2 <> 0 Then Poly = &H1D
Shift Crc_reg , Left , 1
Crc_reg = Crc_reg Xor Poly
End If
Next
Next
Crc_reg = Not Crc_reg

Das war die härteste Nuss im Projekt, jetzt kanns weiter gehen ;-)

Bis Bald
Frank

Netzman
10.03.2009, 23:35
*stirnklatsch* ;)

mfg