首页 > 代码库 > 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 串口通讯之地磅
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。