继上次的读卡之后,要做一个地磅的读取。
下面是我在读卡Demo上改的读取地磅的。
地磅是一直向串口发送数据的,所以需要截取数据来一直判断数据是否合法,然后计算出结果。
其中遇到了一个小问题,文末有介绍。
本人初学菜鸟,大牛们有意见欢迎评论。
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.IO.Ports;
10 using System.IO;
11 using System.Threading;
12
13 namespace WindowsFormsApplicationcs
14 {
15 public partial class FormMain : Form
16 {
17 //声明端口对象
18 SerialPort myport = null;
19 //处理数据的数据数组
20 byte[] buf = new byte[50];
21 //声明委托类型
22 public delegate void Displaydelegate(byte[] buf);
23 //委托变量
24 public Displaydelegate disp_delegate;
25
26 public FormMain()
27 {
28 InitializeComponent();
29 //安全线程外更新空间
30 //Form.CheckForIllegalCrossThreadCalls = false;
31 }
32
33 //窗口加载
34 private void FormMain_Load(object sender, EventArgs e)
35 {
36 Form.CheckForIllegalCrossThreadCalls = false;
37 txtPort.Text = "COM3";
38 myport = new SerialPort();
39 disp_delegate = new Displaydelegate(DispUI);
40 }
41
42 //打开串口按钮
43 private void button1_Click(object sender, EventArgs e)
44 {
45 try
46 {
47
48 //设置串口端口
49 myport.PortName = txtPort.Text.ToString();
50 //设置比特率
51 myport.BaudRate = Convert.ToInt32(cmbBaud.Text);
52 //设置数据位
53 myport.DataBits = Convert.ToInt32(cmbBits.Text);
54 //设置停止位
55 switch (cmbStopBits.SelectedIndex)
56 {
57 case 0: myport.StopBits = StopBits.None; break;
58 case 1: myport.StopBits = StopBits.One; break;
59 case 2: myport.StopBits = StopBits.OnePointFive; break;
60 case 3: myport.StopBits = StopBits.Two; break;
61 }
62
63 //设置奇偶校验位
64 switch (cmbParity.SelectedIndex)
65 {
66 case 0: myport.Parity = Parity.Even; break;
67 case 1: myport.Parity = Parity.Mark; break;
68 case 2: myport.Parity = Parity.None; break;
69 case 3: myport.Parity = Parity.Odd; break;
70 case 4: myport.Parity = Parity.Space; break;
71 }
72
73 //缓冲区只接受一个字符
74 myport.ReceivedBytesThreshold = 1;
75 //接收事件添加委托
76 myport.DataReceived += new SerialDataReceivedEventHandler(this.myport_DataReceived);
77 //打开串口
78 myport.Open();
79 if (myport.IsOpen)
80 {
81 MessageBox.Show("端口已打开");
82 this.tstldqzt.Text = "当前状态:端口已打开";
83 }
84 else
85 {
86 MessageBox.Show("端口未能打开!");
87 }
88 }
89 catch (Exception ex)
90 {
91 MessageBox.Show("端口打开出现错误!\n" + ex.Message.ToString());
92 }
93 }
94
95 //委托方法
96 //接收数据
97 private void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
98 {
99 Thread.Sleep(100);
100 if (myport.BytesToRead > 0)//如果缓冲区内有数据
101 {
102 myport.Read(buf, 0, 1);//从缓冲区读取数据到buf暂存数组,
103 }
104
105 if (buf[0] == 0x02)//如果开头等于2,则表明是信息开始 0x02
106 {
107 try
108 {
109 while (myport.BytesToRead == 9);
110 myport.Read(buf, 0, 9);//从缓冲区读取一条正确数据到buf暂存数组
111 string s = string.Empty;
112
113 for (int i = 0; i < 9; i++)
114 {
115 s += (char)buf[i];
116 }
117
118 StringBuilder b = new StringBuilder("");
119
120 if (s.Substring(0, 1) == "-")
121 b.Append("-");
122
123 int strint = Convert.ToInt32(s.Substring(1,7));
124 int dianint = Convert.ToInt32(s.Substring(8,1));
125
126 switch (dianint)
127 {
128 case 1: strint = strint / 10; break;
129 case 2: strint = strint / 100; break;
130 case 3: strint = strint / 1000; break;
131 case 4: strint = strint / 10000; break;
132 }
133 b.Append(strint);
134 txtReceive.Text += "开始" + b + "结束\r\n";
135
136 //this.Invoke(disp_delegate, buf);
137 }
138 finally
139 {
140 myport.DiscardInBuffer();//清空缓冲区
141 }
142 }
143 }
144
145 //更新ui方法
146 public void DispUI(byte[] buf)
147 {
148
149 }
150
151
152 //关闭方法
153 private void button2_Click(object sender, EventArgs e)
154 {
155 myport.Close();
156 if (!myport.IsOpen)
157 {
158 this.tstldqzt.Text = "当前状态:端口已关闭";
159 MessageBox.Show("端口已关闭");
160 }
161 }
162
163 //清屏按钮
164 private void button3_Click(object sender, EventArgs e)
165 {
166 this.txtReceive.Clear();
167 }
168
169 //菜单栏关于
170 private void tsmiabout_Click(object sender, EventArgs e)
171 {
172 frmAbout frmabout = new frmAbout();
173 frmabout.ShowDialog();
174 }
175
176 //菜单栏保存结果
177 private void tsmisave_Click(object sender, EventArgs e)
178 {
179 if (this.txtReceive.Text == "")
180 { MessageBox.Show("当前结果为空,请先测试"); }
181 string path = Directory.GetCurrentDirectory() + "\\端口测试结果.txt";
182 File.WriteAllText(path, this.txtReceive.Text.ToString(), Encoding.ASCII);
183 }
184
185 }
186 }
这里其实有个问题,就是一个窗口一般会涉及到多个串口设备的通讯,
公司目前的需求也不例外,可以看到我使用了一个thread.sleep,
这样虽然当时解决了问题,但是当一个窗口有多个串口通讯更新ui的时候应该会出现问题,
但因为当时手头没有设备也没做进一步的测试,。
因为不加这句话就会无法实时更新ui,当时打了一个多小时的短点记了好多数据,
才确定了不是数据处理那部分的问题,思考一下原因应该是while把线程堵死了,一直在做运算。
但是使用invoke不是新开线程委托吗?为什么也是更新不了ui。
百度了发现如下解释
invoke是在拥有此控件的基础窗口句柄的线程上指定指定的委托
begininvoke是在创建此控件的基础窗口句柄的线程上异步执行指定的委托
使用begininvoke应该就可以不干扰其他的串口通讯更新ui了