C#串口打印機:控制類開發與實戰
一、引言
在嵌入式設備、POS 終端、工業控制等場景中,串口打印機因其穩定的通信性能和廣泛的兼容性,仍是重要的數據輸出設備。本文基于 C# 語言,深度解析一個完整的串口打印機控制類Printer
,該類封裝了串口通信、數據格式化、圖片打印等核心功能,可快速實現對各類串口打印機的控制,適用于 Windows 桌面應用開發。
二、Printer 類核心架構設計
1. 串口通信基礎模塊
初始化配置
public Printer(string portName)
{serialPort = new SerialPort{PortName = portName,BaudRate = 9600, // 波特率Parity = Parity.Odd, // 奇校驗StopBits = StopBits.One // 停止位};OpenPort(); // 打開串口
}public Printer() : this("COM2") { } // 默認COM2端口
-
雙構造函數設計:支持指定端口名初始化和默認端口(COM2)初始化,滿足不同設備連接需求
-
固定通信參數:采用工業級標準配置(9600 波特率 / 奇校驗 / 1 停止位),適配大多數傳統打印機
端口管理
private void OpenPort()
{if (!serialPort.IsOpen){serialPort.Open(); // 安全打開串口}
}private void ClosePort()
{if (serialPort.IsOpen){serialPort.Close();serialPort.Dispose(); // 釋放資源}
}
-
包含完整的端口生命周期管理,避免資源泄漏
-
異常處理通過
MessageBox
反饋,適合 WinForms 界面應用
2. 多類型數據發送功能
字節數據發送(核心方法)
public void Write(byte[] data, int len) // 定長數組
public void Write(params byte[] data) // 不定長參數
public void Write(string strBuf) // 字符串(自動編碼轉換)
-
參數重載設計:支持三種主流數據類型發送,覆蓋 90% 以上的打印指令場景
-
編碼轉換:通過
ToHex
方法實現 GB2312 編碼轉換,解決中文亂碼問題(打印機常用編碼)
private byte[] ToHex(string str, string charset)
{Encoding enc = Encoding.GetEncoding(charset);return enc.GetBytes(str); // 字符轉字節數組
}
3. 圖片打印核心功能
點陣圖取模算法
private byte[,] GetBytesByBMP(Bitmap bmp)
{// 1. 灰度處理:將彩色圖像轉為單色素材// 2. 點陣生成:通過閾值(192)區分黑白像素// 3. 字節編碼:8點一行轉換為1字節數據var bitArray = new bool[height, width];for (int i=0; i<width; i++)for (int j=0; j<height; j++){double gray = 0.299*R + 0.587*G + 0.114*B;bitArray[j,i] = gray < 192; // 深色像素標記為1}// 二進制轉字節(逐行處理,8位一組)var res = new byte[rows, cols];for (int i=0; i<height; i+=8)for (int j=0; j<width; j++){byte b = 0;for (int k=7; k>=0; k--)b += (byte)((bitArray[i+k,j] ? 1 : 0) << k);res[row++,j] = b;}return res;
}
- 灰度算法:采用 ITU-R 601-2 亮度公式,準確區分打印點
- 內存優化:自動處理非 8 的整數倍高度,補全虛擬行確保字節對齊
圖片打印協議實現
public void PrintImage(Bitmap bmp)
{byte[,] gImage = GetBytesByBMP(bmp);int width = gImage.GetLength(1);// 發送圖片數據頭(ESC K指令)for (int i = gImage.GetLength(0)-1; i >= 0; i--){Write(0x1B, 0x4B, (byte)width, (byte)(width >> 8)); // 發送每行像素數據for (int j=0; j<width; j++)Write(gImage[i,j]);Write(0x0D); // 換行符}
}
- 遵循 ESC/POS 打印機控制協議(0x1B 0x4B 為圖形打印指令)
- 支持任意尺寸位圖打印,自動處理上下翻轉(適應打印機坐標系)
三、典型應用場景與調用示例
1. 基礎指令發送(控制打印機)
Printer p = new Printer("COM3"); // 連接指定串口// 發送初始化指令(ESC @)
p.Write(0x1B, 0x40);
// 發送定長數據(如票據頭數據)
byte[] header = Encoding.UTF8.GetBytes("票據打印系統");
p.Write(header, header.Length);
2. 字符串打印(中文支持)
// 直接發送字符串(自動轉換為GB2312編碼)
p.Write("您好,這是測試打印!\r\n");// 支持特殊格式控制(需符合打印機指令集)
p.Write("\x1B\x45" + "加粗文本" + "\x1B\x46");
3. 圖片打印(LOGO / 二維碼)
// 加載本地圖片并打印using (Bitmap logo = new Bitmap("logo.bmp"))
{p.PrintImage(logo);
}
四、性能優化與異常處理
1. 線程安全
- 建議在多線程環境中添加鎖機制:
private object lockObj = new object();
public void SafeWrite(byte[] data)
{lock (lockObj) { serialPort.Write(data); }
}
2. 錯誤處理增強
// 原代碼優化建議try { /* 操作 */ }
catch (Exception ex) 
{MessageBox.Show($"串口通信異常:{ex.Message}");ClosePort(); // 異常時確保端口關閉
}
3. 資源釋放
- 建議實現
IDisposable
接口:
public void Dispose()
{ClosePort();GC.SuppressFinalize(this);
}
五、適用場景與設備兼容性
1. 典型應用領域
- POS 收銀系統(小票打印)
- 工業控制設備(狀態報表輸出)
- 嵌入式終端(票據打印模塊)
- 物聯網設備(傳感器數據打印)
2. 設備適配建議
-
指令集差異:不同品牌打印機(如 EPSON、Zebra)可能需要調整控制指令(如圖片打印指令可能為 0x1B 0x2A)
-
波特率配置:若設備使用不同波特率(如 19200),需修改構造函數中的
BaudRate
參數 -
編碼選擇:對于支持 UTF-8 的新型打印機,可修改
ToHex
方法的默認編碼
六、總結與擴展方向
1. 類庫優勢
- 一站式封裝:集成串口通信、數據轉換、圖片處理三大核心功能
- 高擴展性:通過重載
Write
方法可輕松添加新的數據類型支持 - 快速集成:無需關注底層串口協議,3 行代碼實現基礎打印功能
2. 改進方向
- 跨平臺支持:移除 WinForms 依賴(如
Bitmap
),使用跨平臺圖像庫(如 SkiaSharp) - 異步通信:添加
WriteAsync
方法,提升高并發場景下的性能 - 狀態監控:增加接收緩沖區處理,實現打印機狀態查詢功能
3. 最佳實踐
- 初始化時通過
SerialPort.GetPortNames()
獲取可用串口列表 - 重要打印任務添加重試機制(3 次失敗后提示用戶)
- 復雜格式打印建議先通過串口調試工具(如 SSCOM)驗證指令
通過合理使用Printer
類,開發者可在 10 分鐘內完成串口打印模塊開發,顯著降低硬件交互成本。建議根據具體打印機型號調整控制指令和編碼方式,確保最佳兼容性。