首页 > 代码库 > Winform 串口通讯之地磅

Winform 串口通讯之地磅

继上次的读卡之后,要做一个地磅的读取。

下面是我在读卡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,则表明是信息开始 0x02106             {107                 try108                 {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                 finally139                 {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了

 

Winform 串口通讯之地磅