继上次的读卡之后,要做一个地磅的读取。
下面是我在读卡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了