Winform 串口通讯之地磅

Posted 阿轩的BLOG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,则表明是信息开始 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了

 

以上是关于Winform 串口通讯之地磅的主要内容,如果未能解决你的问题,请参考以下文章

C#上位机开发一:串口通讯之如何制作一个串口调试助手

电子秤怎么连接电脑

2021-11-18 WPF上位机 87-串口通信和网口通讯

串行通讯之UARTLoopback

delphi学习笔记2之动态库调用和串口通讯

Android OTG之USB转串口模块通讯