串口硬體本質上是逐位元組(byte)收發的。 `SerialPort.Write(byte[], int, int)` 是最底層、最高效的 API。所有其他型別最終都會被轉換為位元組陣列才發送。
| 來源型別 | 轉換方式 | 範例 |
|---|---|---|
| 字串 | 指定編碼 `Encoding.GetBytes()` | `Encoding.ASCII.GetBytes("AT\r\n")`、`Encoding.UTF8.GetBytes(str)` |
| 整數 (int/short/long) | `BitConverter.GetBytes()` 或手動移位 | `BitConverter.GetBytes(0x1234)` → 小端序 `{0x34, 0x12}` |
| 浮點數 (float/double) | `BitConverter.GetBytes()` | `BitConverter.GetBytes(3.14f)` |
| 結構體 | `Marshal.StructureToPtr` + `byte[]` / `BinaryWriter` | 需 `[StructLayout(LayoutKind.Sequential)]`,注意對齊 |
| 16進位字串 | 自寫解析或 `SoapHexBinary` | `"AA BB 01"` → `new byte[]{0xAA,0xBB,0x01}` |
| 物件序列化 | `BinaryFormatter` / `protobuf-net` / `MessagePack` | 跨語言建議用 Protobuf/MessagePack |
public static class SerialPortExtensions {
public static void WriteString(this SerialPort port, string text, Encoding encoding = null) {
encoding = encoding ?? Encoding.ASCII;
port.Write(encoding.GetBytes(text), 0, encoding.GetByteCount(text));
}
public static void WriteInt32(this SerialPort port, int value, bool littleEndian = true) {
byte[] bytes = BitConverter.GetBytes(value);
if (!littleEndian) Array.Reverse(bytes);
port.Write(bytes, 0, 4);
}
public static void WriteHex(this SerialPort port, string hex) {
// 移除空格、換行
hex = hex.Replace(" ", "").Replace("\r", "").Replace("\n", "");
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < bytes.Length; i++)
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
port.Write(bytes, 0, bytes.Length);
}
}
// 使用
serialPort.WriteString("AT+RESET\r\n");
serialPort.WriteInt32(sensorId);
serialPort.WriteHex("AA 55 01 02 03");
「除了 byte[] 還能用什麼」→ 任何型別,只要能轉成 byte[] 就能發送。掌握 `Encoding.GetBytes`、`BitConverter.GetBytes`、結構體編組、16進位解析等轉換技巧,並封裝強型別擴充方法,能大幅提升串口開發效率與可讀性。