PAYATHON 2026

VB.Net 通过 Serial port 向 CD7220 发送十六进制代码

技术老齐

结论

发送 0xBC 时,应调用 SerialPort.Write(Byte(), offset, count) 直接写入一个字节:

Dim poundByte As Byte() = {CByte(&HBC)}
mySerialPort.Write(poundByte, 0, poundByte.Length)

字符串 "BC"、"&HBC" 和 ChrW(&HBC) 处理的都是文本字符。经过 SerialPort.Encoding 转换后,发送出去的字节未必是 BC。

以上写法还要求 CD7220 当前使用的字符表将字节 0xBC 映射为 £。如果设备切换过字符表,请先按照手册选用正确的字符表。

直接发送 £ 为什么可能无效

.NET 字符串中的 £ 是 Unicode 字符 U+00A3,CD7220 所需的则是设备字符表中的单字节值 0xBC,两者的编码值不同。

SerialPort.Write(String) 和 WriteLine(String) 会先根据 SerialPort.Encoding 将字符串转换成字节。默认编码通常无法将 £ 转换为设备要求的 0xBC,最终可能发送 ? 或其他字节。

下面这种写法同样不可靠:

mySerialPort.Write(ChrW(&HBC))

ChrW(&HBC) 表示 Unicode 字符 U+00BC,也就是 ¼,不是数值为 BC 的原始字节。

只发送 GBP 符号

如果只是测试 £ 能否正常显示,可以这样发送:

Imports System.IO.Ports

Using mySerialPort As New SerialPort(
    "COM3",
    9600,
    Parity.None,
    8,
    StopBits.One)

    mySerialPort.Open()

    Dim poundByte As Byte() = {CByte(&HBC)}
    mySerialPort.Write(poundByte, 0, poundByte.Length)
End Using

串口传输的是字节流,十六进制只是字节值的一种书写方式。0xBC、&HBC 和十进制 188 表示同一个字节。

在普通文本中插入 £

如果字符串中既有普通 ASCII 字符,也有 £,可以先按设备字符表进行转换,再发送数据:

Private Function EncodeCd7220(value As String) As Byte()
    Dim result As New List(Of Byte)(value.Length)

    For Each ch As Char In value
        If ch = "£"c Then
            result.Add(CByte(&HBC))
        Else
            Dim code As Integer = AscW(ch)

            If code >= 0 AndAlso code <= &H7F Then
                result.Add(CByte(code))
            Else
                ' 当前转换函数没有定义其他非 ASCII 字符的设备编码
                result.Add(CByte(AscW("?"c)))
            End If
        End If
    Next

    Return result.ToArray()
End Function

Private Sub WriteCd7220(port As IO.Ports.SerialPort, value As String)
    Dim data As Byte() = EncodeCd7220(value)
    port.Write(data, 0, data.Length)
End Sub

发送两行内容时,可以写成:

Imports System.IO.Ports

Dim displayText As String = If(varPassed, String.Empty)

If displayText.Length > 40 Then
    displayText = displayText.Substring(0, 40)
Else
    displayText = displayText.PadRight(40)
End If

Dim line1 As String = displayText.Substring(0, 20)
Dim line2 As String = displayText.Substring(20, 20)

Using mySerialPort As New SerialPort(
    "COM3",
    9600,
    Parity.None,
    8,
    StopBits.One)

    mySerialPort.Open()

    WriteCd7220(mySerialPort, line1)

    Dim crlf As Byte() = {CByte(&HD), CByte(&HA)}
    mySerialPort.Write(crlf, 0, crlf.Length)

    WriteCd7220(mySerialPort, line2)
End Using

例如,字符串 "TOTAL £12.50" 中的 £ 会被转换为单字节 BC,其余 ASCII 字符按原值发送。

WriteLine 与显示器换行的关系

WriteLine 不知道显示器有两行,也不会自动将每次调用对应到一行。它只会发送字符串,并在末尾追加 SerialPort.NewLine 指定的字节。

如果字符串末尾已经加入 vbCrLf,又调用了 WriteLine:

mySerialPort.WriteLine(line1 & vbCrLf)

发送的数据会先包含手动添加的 CR LF,后面再附加 WriteLine 自己的换行符,可能造成重复换行或产生多余的控制字符。

控制这类串口显示设备时,使用 Write 明确发送 0x0D、0x0A 或手册规定的光标定位命令会更稳妥。如果 CD7220 手册要求的换行序列不是 CR LF,请将示例中的:

Dim crlf As Byte() = {CByte(&HD), CByte(&HA)}

替换为手册指定的控制字节。每行可显示 20 个字符只是设备的显示容量,不表示设备会把每次串口写入都当成独立的一行。

备注:内容仅供参考。