kannst du mir noch die sw crc routine für die fixe länge von 25 bytes (incl.
crc)
zusammenstellen? die 25 bytes sind in einem bytearray
Ich überlege
Klar, das machen wir! Da du die Daten für jeden Cluster in einem eigenen RAM-
Bereich (
Cluster1_RAM, etc.) hast und die Länge mit 25 Bytes (23 Daten + 2 CRC) feststeht,
bauen wir die Routine so, dass sie direkt den CRC-Check durchführt und ein TRUE
oder FALSE zurückgibt.
Da Modbus das Low-Byte zuerst sendet, vergleichen wir das berechnete Ergebnis am
Ende direkt mit den letzten beiden Bytes im Array.
Die universelle CRC-Check Routine
Diese Funktion nutzt den Hardware-Pointer FSR0, damit sie für alle drei Cluster-
Arrays funktioniert.
latex
$CRC16 = (Result_{High} \ll 8) | Result_{Low}$
Verwende Code mit Vorsicht.
vb
' --- Modbus CRC-Check für fix 25 Bytes (23 Daten + 2 CRC) ---
' Aufruf: If Check_BMS_CRC(VarPtr(Cluster1_RAM[offset])) = 1 Then...
Function Check_BMS_CRC(pStartAddr As Word) As Bit
Dim i As Byte
Dim j As Byte
Dim CalcCRC As Word
Dim ReceivedCRC As Word
' 1. FSR0 auf den Anfang des 25-Byte Pakets setzen
FSR0L = pStartAddr.Byte0
FSR0H = pStartAddr.Byte1
' 2. CRC über die ersten 23 Bytes berechnen
CalcCRC = $FFFF
For i = 0 To 22
CalcCRC = CalcCRC ^ POSTINC0 ' XOR mit Byte, dann Pointer auf nächstes Byte
For j = 1 To 8
If CalcCRC.0 = 1 Then
CalcCRC = (CalcCRC >> 1) ^ $A001
Else
CalcCRC = CalcCRC >> 1
EndIf
Next j
Next i
' 3. Die empfangene CRC aus Byte 24 & 25 lesen
' ACHTUNG: Modbus sendet meist Low-Byte zuerst (Byte 23), dann High (Byte 24)
' FSR0 steht durch POSTINC0 jetzt bereits auf Byte 23 (Index 23)
ReceivedCRC.Byte0 = POSTINC0 ' Lese Byte 23 (Low)
ReceivedCRC.Byte1 = POSTINC0 ' Lese Byte 24 (High)
' 4. Vergleich
If CalcCRC = ReceivedCRC Then
Result = 1 ' CRC OK
Else
Result = 0 ' CRC Fehler
EndIf
End Function
Verwende Code mit Vorsicht.
Warum das so effizient ist:
FSR-Nutzung: Durch POSTINC0 "wandert" der Pointer während der Berechnung
automatisch durch das Array. Wenn die Schleife bei Byte 22 fertig ist, steht der
Pointer exakt auf dem ersten CRC-Byte. Du musst keine Offsets mehr berechnen.
Fixe Länge: Da wir genau wissen, dass nach 23 Bytes Schluss ist, gibt es kein
Vertun beim Start der CRC-Bytes.
Zentraler Check: Du kannst diese Funktion in einer Schleife für alle 3 Cluster
aufrufen:
vb
' Beispiel für die Verarbeitung nach dem Empfang:
For i = 0 To 31 ' Alle 32 Plätze pro Cluster
Addr = i * 32 ' Startadresse im Speicher
' Check Cluster 1
If Check_BMS_CRC(VarPtr(Cluster1_RAM[Addr])) = 1 Then
' CRC gültig -> Ab in den Filter und zum Cerbo
EndIf
' Check Cluster 2 ... usw.
Next i
Verwende Code mit Vorsicht.
Ein kleiner Tipp für die Daly-Antwort:
Daly BMS sind manchmal eigenwillig mit der Byte-Reihenfolge der CRC (manchmal
High/Low vertauscht). Falls dein Check immer fehlschlägt, obwohl die Daten gut
aussehen, tausche in der Funktion einfach Byte0 und Byte1 beim Einlesen der
ReceivedCRC.
Damit ist dein "Türsteher" für die Datenqualität fertig!
Soll ich dir noch die Bit-Masken für die Auswertung der Daly-Einzelalarme in eine
Tabelle packen, damit du sie direkt in deine Slow-Routine einbauen kannst?
Viel Erfolg beim ersten Testlauf der CRC-Routine!