2025年1月2日 星期四 甲辰(龙)年 十月廿九 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > .net

Winform 串口通讯之地磅

时间:04-11来源:作者:点击数:19

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

下面是我在读卡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了

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门