关于串口编程的(一)
2016-05-13 06:39
429 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。
所谓串口,也叫串行接口,即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,一般命令也是十六进制的。所以转换的方法需要用到。
[csharp] view
plain copy
print?
/// <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、对串口的打开,发送命令,关闭等的类。
[csharp] view
plain copy
print?
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;
}
}
使用
[csharp] view
plain copy
print?
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
所谓串口,也叫串行接口,即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,一般命令也是十六进制的。所以转换的方法需要用到。
[csharp] view
plain copy
print?
/// <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、对串口的打开,发送命令,关闭等的类。
[csharp] view
plain copy
print?
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;
}
}
使用
[csharp] view
plain copy
print?
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
相关文章推荐
- Regular Expressions (3) ---- Using Regex in .NET
- Regular Expressions (2) ---- Common Used Samples
- Regular Expressions (1) ---- What is Regular Expressions?
- .NET系统学习----Globalization & Resources
- 成为C++高手之while循环
- 几种编程语言的基本介绍
- Python笔记:除、取整、取余、乘方
- Python笔记:加减乘除,格式化字符串
- 我学过的java4
- ipython的两种安装方式
- Maven 教程入门(整理版)
- 用C++实现单链表
- C# 将多个DataTable添加到指定的DataSet中
- Java并发编程:Lock
- java thread reuse(good)
- 成为Java顶尖高手要看的11本书
- 怎样在Ubuntu 14.04中安装Java
- 《Python核心编程》第7章 习题
- Python-continue的使用和if的位置
- 关于Laravel的二、三事(1)简单的路由