所谓串口,也叫串行接口,即COM口,采用串行通讯方式(即数据一位一位的传送)的接口。也就是电脑后面D形9针插口。
最近做了两个都和串口编程有关的功能,一个是不间断电源,一个是RS232型串口打印机。因为是串口所以主要的用法都不难,难点是对设备的相应命令的理解和使用上。因为不同类型的、不同厂家的设备命令是不同的,因为也没法总一个总结。那就对于串口的简单用法做一些总结吧。
主要用到的类是SerialPort,在System.IO.Ports下。传设备的基本使用步骤如下:
1、设置串口的参数。因为不同的设备对串口的参数要求是不同的,最常见就是波特率,一般好像都是9600。
2、打开串口。也就是SerialPort的Open()方法。
3、想串口写命令或写文本内容。一般情况下,如果是数字类型的命令都是十六进制的,当然也有十进制的,不过如果有十六进制和十进制两种,我觉得最好用十六进制的,因为十六进制好转换为byte数组。
向串口写命令的方法是SerialPort的Write(byte[] buffer, int offset, int count)。比如一个命令,十六进制下:00 FF,十进制下:00 255;那么这段命令最终转为byte[]时,00和FF分别转换,但是对于00和255显然就不怎么方便了。看一下后面的一个例子就明白了。
4,接收返回值。向串口发送命令,有的是指示执行操作的,有的是查询状态的,因此需要读取返回值。
下面对于某一个串口设备的控制,写一个简单的例子。
1、字符操作类,因为串口写入的须要是byte数组型,读出又要将byte数组转为string,一般命令也是十六进制的。所以转换的方法需要用到。
/// <summary> /// 串口字符类 /// </summary> public class CharOperated { public static string ByteArrayToHexString(byte[] byteData) { StringBuilder result = new StringBuilder(byteData.Length * 3); foreach (byte b in byteData) { result.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' ')); } return result.ToString().ToUpper(); } /// <summary> /// 十六进制的字符串转成byte数组 /// </summary> /// <returns></returns> public static byte[] HexStringToByteArray(string content) { content = content.Replace(" ", ""); byte[] buffer = new byte[content.Length / 2]; for (int i = 0; i < content.Length; i += 2)//因为十六进制命令一般都是两位十六进制一起。 { buffer[i / 2] = (byte)Convert.ToByte(content.Substring(i, 2), 16); } return buffer; } /// <summary> /// 16进制编码的字串解析成 ascii码 /// </summary> /// <param name="statusCode"></param> /// <returns></returns> public static string DecodeHexToAsc(string statusCode) { string rtn = ""; statusCode = statusCode.Replace(" ", ""); for (int i = 0; i < (statusCode.Length / 2); i++) { string key = statusCode.Substring(2 * i, 2); int asii = Convert.ToInt32(key, 16);//将16进制字符串转换成其ASCII码(实际是Unicode码) rtn += Chr(asii); } return rtn; } /// <summary> /// ascii码转字符 /// </summary> /// <param name="asciiCode"></param> /// <returns></returns> public static string Chr(int asciiCode) { if (asciiCode >= 0 && asciiCode <= 255) { System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding(); byte[] byteArray = new byte[] { (byte)asciiCode }; string strCharacter = asciiEncoding.GetString(byteArray); return (strCharacter); } return string.Empty; } }
2、对串口的打开,发送命令,关闭等的类。
public class ComManager { private SerialPort comm = null; private static string currentPortName = string.Empty; private static object sendCommandLock = new object(); public ComManager(SerialPort comm) { if (this.comm == null) { this.comm = comm; } } /// <summary> /// 串口参数设定 /// </summary> private void SetSerialPort() { //根据设备要求设置参数,比如某一设备要求参数如下: comm.BaudRate = 9600; comm.Encoding = System.Text.Encoding.GetEncoding("GB2312"); comm.RtsEnable = true; } /// <summary> /// 打开串口设备 /// </summary> private void SerialPortOpen() { try { if (comm.IsOpen) { comm.Close(); } currentPortName = "COM1";//此处可指定串口,也可以实时读取设备到底连接在那个串口,实际情况根据设备情况而定。 //currentPortName = DoGetUPSPortName();以某一设备为例遍历所有串口,找到连接该设备的串口 SetSerialPort(); if (string.IsNullOrEmpty(currentPortName)) { return; } comm.PortName = currentPortName; comm.Open(); } catch { } } /// <summary> /// 向串口发送命令 /// </summary> /// <param name="sendstring"></param> public void SendDatastring(string sendstring) { lock (sendCommandLock) { //16进制转二进制 byte[] data = CharOperated.HexStringToByteArray(sendstring); //打开口串口设备 SerialPortOpen(); //发送命令到串口设备 if (comm.IsOpen) { comm.DiscardInBuffer(); comm.Write(data, 0, data.Length); } } } /// <summary> /// 向串口写字符串 /// </summary> /// <param name="sendstring"></param> public void WriteLingContent(string content) { lock (sendCommandLock) { //打开口串口设备 SerialPortOpen(); //发送报文到串口设备 if (comm.IsOpen) { comm.WriteLine(content); comm.DiscardInBuffer(); } } } /// <summary> /// 读取端口返回值 /// </summary> /// <returns></returns> private string DoReadPortResult() { string resultString = string.Empty; try { int bytes = comm.BytesToRead; byte[] buffer = new byte[bytes]; comm.Read(buffer, 0, bytes); string rtnStrPort = CharOperated.ByteArrayToHexString(buffer); resultString = CharOperated.DecodeHexToAsc(rtnStrPort); if (comm.IsOpen) { comm.DiscardInBuffer(); } } catch { } return resultString; } /// <summary> /// 获取某一设备的端口号 /// </summary> /// <returns></returns> private string DoGetUPSPortName() { string commName = string.Empty; try { Computer localComputer = new Computer(); foreach (string portItem in localComputer.Ports.SerialPortNames) { try { if (string.IsNullOrEmpty(portItem)) { continue; } commName = portItem; byte[] data = CharOperated.HexStringToByteArray("发送的命令"); comm.Close(); SetSerialPort(); comm.PortName = portItem; comm.Open(); //发送报文到串口设备 if (comm.IsOpen) { comm.DiscardInBuffer(); comm.Write(data, 0, data.Length); } Thread.Sleep(500); //if (条件) //{ //} //else //{ // commName = string.Empty; //} } catch { } finally { if (comm.IsOpen) { comm.Close(); } } } } catch { } finally { if (comm.IsOpen) { comm.Close(); } } return commName; } }
使用
class Program { private static SerialPort serialPortCom = new SerialPort();//串口定义 。 private static string receiveResult = string.Empty; //接收数据。 static void Main(string[] args) { ComManager cm = new ComManager(serialPortCom); cm.SendDatastring("00FF");//命令 cm.WriteLingContent("内容"); Thread.Sleep(200);//停几百毫秒,然后读取 string result = SerialPortComDataReceived(); } private static string SerialPortComDataReceived() { if (serialPortCom == null || !serialPortCom.IsOpen) { return string.Empty; } int bytes = serialPortCom.BytesToRead; byte[] buffer = new byte[bytes]; serialPortCom.Read(buffer, 0, bytes); receiveResult = string.Empty; receiveResult = CharOperated.ByteArrayToHexString(buffer); receiveResult = receiveResult.Trim(); return receiveResult; } }
详细代码下载: http://download.csdn.net/detail/yysyangyangyangshan/5516631