alvin.chen
2019-11-29 edf127edc771f715c49f86e91e768633f0a0ed93
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;
 
namespace HalconTools
{
    public class SerialportWrapper
    {
        private SerialPort comm = new SerialPort();
        string[] ports;
        private long received_count = 0;//接收计数  
        private long send_count = 0;//发送计数  
 
        public StringBuilder builder = new StringBuilder();//避免在事件处理方法中反复的创建,定义到外面。  
 
        private bool flagHexDisplay = false;
        private bool flagSendNewLine = false;
 
        public SerialportWrapper()
        {
            //初始化下拉串口名称列表框  
            ports = SerialPort.GetPortNames();
            Array.Sort(ports);
 
            //初始化SerialPort对象  
            comm.NewLine = "/r/n";
            comm.RtsEnable = true;//根据实际情况吧。  
            //添加事件注册  
            comm.DataReceived += comm_DataReceived;
        }
 
        void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
            byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
            received_count += n;//增加接收计数  
            comm.Read(buf, 0, n);//读取缓冲数据  
            //builder.Remove(0, builder.Length);//清除字符串构造器的内容  
 
            //因为要访问ui资源,所以需要使用invoke方式同步ui。  
            if (flagHexDisplay)
            {
                //依次的拼接出16进制字符串  
                foreach (byte b in buf)
                {
                    builder.Append(b.ToString("X2") + " ");
                }
            }
            else
            {
                //直接按ASCII规则转换成字符串  
                builder.Append(Encoding.ASCII.GetString(buf));
            }
        }
 
        public void Open(string portName, int baudRate, bool hexDisplay)
        {
            bool flagPortExists = false;
 
            foreach (string port in ports)
            {
                if (port.Equals(portName))
                {
                    flagPortExists = true;
                }
            }
 
            if (!flagPortExists)
            {
                MessageBox.Show("指定串口(%s)不存在", portName);
            }
 
            comm.PortName = portName;
            comm.BaudRate = baudRate;
            this.flagHexDisplay = hexDisplay;
 
            try
            {
                comm.Open();
            }
            catch (Exception ex)
            {
                //捕获到异常信息,创建一个新的comm对象,之前的不能用了。  
                comm = new SerialPort();
                //现实异常信息给客户。  
                MessageBox.Show(ex.Message);
            }
        }
 
        public void Open(int index, int baudRate, bool hexDisplay)
        {
            if (index > ports.Length)
            {
                MessageBox.Show("指定串口(%d)不存在", index.ToString());
            }
 
            comm.PortName = ports[index];
            comm.BaudRate = baudRate;
            this.flagHexDisplay = hexDisplay;
 
            try
            {
                comm.Open();
            }
            catch (Exception ex)
            {
                //捕获到异常信息,创建一个新的comm对象,之前的不能用了。  
                comm = new SerialPort();
                //现实异常信息给客户。  
                MessageBox.Show(ex.Message);
            }
        }
 
 
        public void Close()
        {
            //根据当前串口对象,来判断操作  
            if (comm.IsOpen)
            {
                //打开时点击,则关闭串口  
                comm.Close();
            }
        }
        
        public void Send(string content)
        {
            //定义一个变量,记录发送了几个字节  
            int n = 0;
            //16进制发送  
            if (flagHexDisplay)
            {
                //我们不管规则了。如果写错了一些,我们允许的,只用正则得到有效的十六进制数  
                MatchCollection mc = Regex.Matches(content, @"(?i)[/da-f]{2}");
                List<byte> buf = new List<byte>();//填充到这个临时列表中  
                //依次添加到列表中  
                foreach (Match m in mc)
                {
                    buf.Add(byte.Parse(m.Value));
                }
                //转换列表为数组后发送  
                comm.Write(buf.ToArray(), 0, buf.Count);
                //记录发送的字节数  
                n = buf.Count;
            }
            else//ascii编码直接发送  
            {
                //包含换行符  
                if (flagSendNewLine)
                {
                    comm.WriteLine(content);
                    n = content.Length + 2;
                }
                else//不包含换行符  
                {
                    comm.Write(content);
                    n = content.Length;
                }
            }
            send_count += n;//累加发送字节数  
        }
 
        public void Reset()
        {
            //复位接受和发送的字节数计数器并更新界面。  
            send_count = received_count = 0;
            builder.Remove(0, builder.Length);
        }
 
        public void Clear()
        {
            builder.Remove(0, builder.Length);
        }
    }
}