最近涉及到串口编程比较多,在项目中需要通过串口给硬件设备发送控制指令,为了确认发送的控制指令被正确执行,所以过程一般是这样:
1、 向串口发送控制指令,此时设备没有数据返回
2、 向串口发送状态读取指令确认设备的状态是否已经改变,此时设备会返回当前的状态。
由于有些设备返回的状态数据较少,而有些设备返回的状态数据较多(可能分多次返回),所以需要根据情况来预估等待时间的值。但总觉得根据实际情况给定等待的时间不是很好,有没有更专业的串口编程的方法,请告知,谢谢。
下面是我上面说的办法的代码:
Code
1using System;
2using System.IO.Ports;
3using System.Configuration;
4using System.Threading;
5
6namespace Communication
7{
8 /**//// <summary>
9 /// 串口类
10 /// </summary>
11 public class ComPort : IDisposable
12 {
13 private string portName;
14 /**//// <summary>
15 /// 获取或设置 串口号,默认为 "COM1"
16 /// </summary>
17 public string PortName
18 {
19 get { return this.portName; }
20 set { this.portName = value; }
21 }
22
23 private int baudRate;
24 /**//// <summary>
25 /// 获取或设置 串口波特率, 默认 9600
26 /// </summary>
27 public int BaudRate
28 {
29 get { return this.baudRate; }
30 set { this.baudRate = value; }
31 }
32
33 private int dataBits;
34 /**//// <summary>
35 /// 获取或设置 一个字节的数据位,默认 8
36 /// </summary>
37 public int DataBits
38 {
39 get { return this.dataBits; }
40 set { this.dataBits = value; }
41 }
42
43 private StopBits stopBits;
44 /**//// <summary>
45 /// 获取或设置 停止位, 默认 1
46 /// </summary>
47 public StopBits StopBits
48 {
49 get { return this.stopBits; }
50 set { this.stopBits = value; }
51 }
52
53 //内置的串口对象
54 private SerialPort serialPort;
55
56 private int waitTimeInMilliseconds;
57 /**//// <summary>
58 /// 获取或设置 需要从串口接收数据时的等待时间(以毫秒为单位) , 默认50毫秒
59 /// </summary>
60 public int WaitTimeInMilliseconds
61 {
62 get { return this.waitTimeInMilliseconds; }
63 set { this.waitTimeInMilliseconds = value; }
64 }
65
66 public ComPort()
67 {
68 this.portName = "COM1";
69 this.baudRate = 9600;
70 this.dataBits = 8;
71 this.stopBits = StopBits.One;
72 this.waitTimeInMilliseconds = 50;
73
74 try
75 {
76 this.portName = ConfigurationManager.AppSettings["ComPortName"].ToString();
77 }
78 catch
79 {
80 }
81 try
82 {
83 this.baudRate = int.Parse(ConfigurationManager.AppSettings["ComBaudRate"].ToString());
84 }
85 catch
86 {
87 }
88 try
89 {
90 this.waitTimeInMilliseconds = int.Parse(ConfigurationManager.AppSettings["WaitTimeInMilliseconds"].ToString());
91 }
92 catch
93 {
94 }
95
96 this.serialPort = null;
97 }
98
99 /**//// <summary>
100 /// 串口对象初始化
101 /// </summary>
102 public void Initialize()
103 {
104 this.serialPort = new SerialPort(this.portName, this.baudRate, Parity.None, this.dataBits, this.stopBits);
105 this.serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
106 }
107
108 private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
109 {
110 //当SendCommand的“Thread.Sleep(this.waitTimeInMilliseconds);”被执行时,正在干下面的事情:
111 //如果该过程经历时间较长(比如有很多的数据要读取),可以通过设置增大“this.waitTimeInMilliseconds”的值。
112 //也就是说根据实际情况预估 等待时间 的值,总感觉这样处理不是很好。
113 //有更靠谱的串口编程的方式,请告知,谢谢。
114 int bytes = this.serialPort.BytesToRead;
115 byte[] data = new byte[bytes];
116 this.serialPort.Read(data, 0, bytes);
117
118 //当接收到数据且函数委托不为空时,调用函数委托处理接收到的数据
119 if (null != data)
120 if (null != this.dgDataReceived)
121 this.dgDataReceived(data);
122 }
123
124 /**//// <summary>
125 /// 发送数据
126 /// </summary>
127 /// <param name="data">要发送的数据流</param>
128 /// <param name="bRead">发送完后是否马上读取数据</param>
129 public void SendCommand(byte[] data, bool bRead)
130 {
131 //预防被多线程调用
132 lock (this.serialPort)
133 {
134 this.serialPort.Open();
135
136 this.serialPort.Write(data, 0, data.Length);
137
138 //此时正在执行 serialPort_DataReceived 函数。
139 if (bRead)
140 Thread.Sleep(this.waitTimeInMilliseconds);
141
142 this.serialPort.Close();
143 }
144 }
145
146 public delegate void DGDataReceived(byte[] data);
147 private DGDataReceived dgDataReceived;
148 /**//// <summary>
149 /// 设置 当接收到数据时的函数委托
150 /// </summary>
151 public DGDataReceived DataReceived
152 {
153 set { this.dgDataReceived = value; }
154 }
155
156 IDisposable 成员#region IDisposable 成员
157 public void Dispose()
158 {
159 if (this.serialPort.IsOpen)
160 this.serialPort.Close();
161 }
162 #endregion
163 }
164}
165
1using System;
2using System.IO.Ports;
3using System.Configuration;
4using System.Threading;
5
6namespace Communication
7{
8 /**//// <summary>
9 /// 串口类
10 /// </summary>
11 public class ComPort : IDisposable
12 {
13 private string portName;
14 /**//// <summary>
15 /// 获取或设置 串口号,默认为 "COM1"
16 /// </summary>
17 public string PortName
18 {
19 get { return this.portName; }
20 set { this.portName = value; }
21 }
22
23 private int baudRate;
24 /**//// <summary>
25 /// 获取或设置 串口波特率, 默认 9600
26 /// </summary>
27 public int BaudRate
28 {
29 get { return this.baudRate; }
30 set { this.baudRate = value; }
31 }
32
33 private int dataBits;
34 /**//// <summary>
35 /// 获取或设置 一个字节的数据位,默认 8
36 /// </summary>
37 public int DataBits
38 {
39 get { return this.dataBits; }
40 set { this.dataBits = value; }
41 }
42
43 private StopBits stopBits;
44 /**//// <summary>
45 /// 获取或设置 停止位, 默认 1
46 /// </summary>
47 public StopBits StopBits
48 {
49 get { return this.stopBits; }
50 set { this.stopBits = value; }
51 }
52
53 //内置的串口对象
54 private SerialPort serialPort;
55
56 private int waitTimeInMilliseconds;
57 /**//// <summary>
58 /// 获取或设置 需要从串口接收数据时的等待时间(以毫秒为单位) , 默认50毫秒
59 /// </summary>
60 public int WaitTimeInMilliseconds
61 {
62 get { return this.waitTimeInMilliseconds; }
63 set { this.waitTimeInMilliseconds = value; }
64 }
65
66 public ComPort()
67 {
68 this.portName = "COM1";
69 this.baudRate = 9600;
70 this.dataBits = 8;
71 this.stopBits = StopBits.One;
72 this.waitTimeInMilliseconds = 50;
73
74 try
75 {
76 this.portName = ConfigurationManager.AppSettings["ComPortName"].ToString();
77 }
78 catch
79 {
80 }
81 try
82 {
83 this.baudRate = int.Parse(ConfigurationManager.AppSettings["ComBaudRate"].ToString());
84 }
85 catch
86 {
87 }
88 try
89 {
90 this.waitTimeInMilliseconds = int.Parse(ConfigurationManager.AppSettings["WaitTimeInMilliseconds"].ToString());
91 }
92 catch
93 {
94 }
95
96 this.serialPort = null;
97 }
98
99 /**//// <summary>
100 /// 串口对象初始化
101 /// </summary>
102 public void Initialize()
103 {
104 this.serialPort = new SerialPort(this.portName, this.baudRate, Parity.None, this.dataBits, this.stopBits);
105 this.serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
106 }
107
108 private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
109 {
110 //当SendCommand的“Thread.Sleep(this.waitTimeInMilliseconds);”被执行时,正在干下面的事情:
111 //如果该过程经历时间较长(比如有很多的数据要读取),可以通过设置增大“this.waitTimeInMilliseconds”的值。
112 //也就是说根据实际情况预估 等待时间 的值,总感觉这样处理不是很好。
113 //有更靠谱的串口编程的方式,请告知,谢谢。
114 int bytes = this.serialPort.BytesToRead;
115 byte[] data = new byte[bytes];
116 this.serialPort.Read(data, 0, bytes);
117
118 //当接收到数据且函数委托不为空时,调用函数委托处理接收到的数据
119 if (null != data)
120 if (null != this.dgDataReceived)
121 this.dgDataReceived(data);
122 }
123
124 /**//// <summary>
125 /// 发送数据
126 /// </summary>
127 /// <param name="data">要发送的数据流</param>
128 /// <param name="bRead">发送完后是否马上读取数据</param>
129 public void SendCommand(byte[] data, bool bRead)
130 {
131 //预防被多线程调用
132 lock (this.serialPort)
133 {
134 this.serialPort.Open();
135
136 this.serialPort.Write(data, 0, data.Length);
137
138 //此时正在执行 serialPort_DataReceived 函数。
139 if (bRead)
140 Thread.Sleep(this.waitTimeInMilliseconds);
141
142 this.serialPort.Close();
143 }
144 }
145
146 public delegate void DGDataReceived(byte[] data);
147 private DGDataReceived dgDataReceived;
148 /**//// <summary>
149 /// 设置 当接收到数据时的函数委托
150 /// </summary>
151 public DGDataReceived DataReceived
152 {
153 set { this.dgDataReceived = value; }
154 }
155
156 IDisposable 成员#region IDisposable 成员
157 public void Dispose()
158 {
159 if (this.serialPort.IsOpen)
160 this.serialPort.Close();
161 }
162 #endregion
163 }
164}
165