Serialport und Encoding; Problem beim Konvertieren ASCII in Prüfziffer

29/04/2009 - 18:15 von Jo Neigel | Report spam
Hi Group,

um Daten an ein serielles Geràt zu senden, muss ich am Ende zwei
Prüfziffern dranhàngen.
Dazu muss man die Summe aller Ascii-Werte nehmen und durch 256
dividieren.
Der Rest ergibt die 2te Checksumme.
Beide Checksum werden an das Satzende angehàngt.
Meine Umsetzung sieht so aus:


For i As Integer = 0 To sLine.Length - 1
sReadByte = sLine.Substring(i, 1)
iChecksum += Asc(sReadByte)
sWriteLine &= sReadByte
Next
iCheck1 = iChecksum \ 256
iCheck2 = iChecksum Mod 256
If iCheck1 = 13 Then iCheck1 = 14 'Ausnahmebehandlung für chr13
If iCheck2 = 13 Then iCheck2 = 14 'Ausnahmebehandlung für chr13
sWriteLine &= Chr(iCheck1) & Chr(iCheck2)
-
Der String wird dann an das serielle Geràt gesendet:
serialPort1.Write(sWriteLine & vbCr)
-

Das klappt auch soweit, nur nicht immer :-((
Wenn aber sLine z.B. den Wert 'test' hat, wird die Checksum vom
seriellen Geràt abgewiesen.
Mit einem Portmonitor ist mir aufgefallen, dass die Anwendung des
Herstellers in diesem Fall einen andere Checksum ermittelt:
Korrekt wàre (HEX): 74 65 73 74 01 C0 0D
Ich sende:74 65 73 74 01 3F 0D

Meine Vermutung:
Wahrscheinlich taucht das Problem ab dem erweiterten Zeichensatz (ab
128) auf.
Muss ich hier mit eine Encoding Parameter bei SerialPort arbeiten?
Das habe ich ohne Erfolg versucht: serial.Encoding System.Text.Encoding.GetEncoding("Windows-1252")

Hat mir jemand einen Tipp?

gruß Jo
 

Lesen sie die antworten

#1 Armin Zingler
30/04/2009 - 01:48 | Warnen spam
Jo Neigel wrote:
Hi Group,

um Daten an ein serielles Geràt zu senden, muss ich am Ende zwei
Prüfziffern dranhàngen.
Dazu muss man die Summe aller Ascii-Werte nehmen und durch 256
dividieren.
Der Rest ergibt die 2te Checksumme.
Beide Checksum werden an das Satzende angehàngt.
Meine Umsetzung sieht so aus:


For i As Integer = 0 To sLine.Length - 1
sReadByte = sLine.Substring(i, 1)
iChecksum += Asc(sReadByte)
sWriteLine &= sReadByte
Next
iCheck1 = iChecksum \ 256
iCheck2 = iChecksum Mod 256
If iCheck1 = 13 Then iCheck1 = 14 'Ausnahmebehandlung für chr13
If iCheck2 = 13 Then iCheck2 = 14 'Ausnahmebehandlung für chr13
sWriteLine &= Chr(iCheck1) & Chr(iCheck2)
-
Der String wird dann an das serielle Geràt gesendet:
serialPort1.Write(sWriteLine & vbCr)
-

Das klappt auch soweit, nur nicht immer :-((
Wenn aber sLine z.B. den Wert 'test' hat, wird die Checksum vom
seriellen Geràt abgewiesen.
Mit einem Portmonitor ist mir aufgefallen, dass die Anwendung des
Herstellers in diesem Fall einen andere Checksum ermittelt:
Korrekt wàre (HEX): 74 65 73 74 01 C0 0D
Ich sende:74 65 73 74 01 3F 0D



Habe es getestet. Bei mir haben iCheck1 und iCheck2 die Werte 01 und C0.
Insofern also richtig. Wie wandelst du den String wieder in ein Byte-Array
um?

Meine Vermutung:
Wahrscheinlich taucht das Problem ab dem erweiterten Zeichensatz (ab
128) auf.
Muss ich hier mit eine Encoding Parameter bei SerialPort arbeiten?
Das habe ich ohne Erfolg versucht: serial.Encoding > System.Text.Encoding.GetEncoding("Windows-1252")



Das kommt darauf an, welche Codierung das Geràt erwartet. Wenn es ASCII
wàre, dann bist du auf die Zeichen < 128 beschrànkt. Ansonsten dürfte
System.Text.Encoding.Default (vermutlich) auch funktionieren.


Wenn das oben dein echter Code ist, dann làsst sich das aber wesentlich
vereinfachen. Es gibt verschiedene Möglichkeiten. Da du ohnehin die
Zeichencodes zur Berechnung der Checksum benötigst, würde ich den String
gleich in ein Byte-Array unwandeln statt die Überladung
"Serialport.Write(String)" zu verwenden:

Shared Function GetBytes(ByVal s As String) As Byte()

Dim Result(s.Length + 2) As Byte
Dim Summe As Integer

System.Text.Encoding.Default.GetBytes(s, 0, s.Length, Result, 0)

Summe = Aggregate Item In Result Select CInt(Item) Into Sum()
Result(s.Length) = CByte(Summe \ 256)
Result(s.Length + 1) = CByte(Summe And &HFF)
Result(s.Length + 2) = &HD

Return Result

End Function

Das sieht mehr aus als zuvor, jedoch ersparst du dir dadurch die mehrfache
Stringverknüpfung (&) und die Umwandlung ins Byte-Array ist auch mit drin.
Ich habe jetzt mal Encoding.Default verwendet. Dass du damit auf Strings <
256 Zeichen und Zeichencodes < 256 beschrànkt bist, dürfte klar sein.


Armin

Ähnliche fragen