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.Text.RegularExpressions; 11 12 namespace SerialportSample 13 { 14 public partial class SerialportSampleForm : Form 15 { 16 private SerialPort comm = new SerialPort(); 17 private StringBuilder builder = new StringBuilder();//避免在事件处理方法中反复的创建,定义到外面。 18 private long received_count = 0;//接收计数 19 private long send_count = 0;//发送计数 20 private bool listenning = false;//是否没有执行完invoke相关操作 21 private bool closing = false;//是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke 22 23 public SerialportSampleForm() 24 { 25 InitializeComponent(); 26 } 27 28 //窗体初始化 29 private void Form1_Load(object sender, EventArgs e) 30 { 31 //初始化下拉串口名称列表框 32 string[] ports = SerialPort.GetPortNames(); 33 Array.Sort(ports); 34 comboPortName.Items.AddRange(ports); 35 comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1; 36 comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600"); 37 38 //初始化SerialPort对象 39 comm.NewLine = "\r\n"; 40 comm.RtsEnable = true;//根据实际情况吧。 41 42 //添加事件注册 43 comm.DataReceived += comm_DataReceived; 44 } 45 46 void comm_DataReceived(object sender, SerialDataReceivedEventArgs e) 47 { 48 int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致 49 byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据 50 received_count += n;//增加接收计数 51 comm.Read(buf, 0, n);//读取缓冲数据 52 builder.Clear();//清除字符串构造器的内容 53 //因为要访问ui资源,所以需要使用invoke方式同步ui。 54 this.Invoke((EventHandler)(delegate 55 { 56 try 57 { 58 listenning = true; 59 //判断是否是显示为16禁止 60 if (checkBoxHexView.Checked) 61 { 62 //依次的拼接出16进制字符串 63 foreach (byte b in buf) 64 { 65 builder.Append(b.ToString("X2") + " "); 66 } 67 } 68 else 69 { 70 //直接按ASCII规则转换成字符串 71 builder.Append(Encoding.ASCII.GetString(buf)); 72 } 73 //追加的形式添加到文本框末端,并滚动到最后。 74 this.txGet.AppendText(builder.ToString()); 75 //修改接收计数 76 labelGetCount.Text = "Get:" + received_count.ToString(); 77 } 78 finally 79 { 80 listenning = false; 81 82 } 83 })); 84 } 85 86 private void buttonOpenClose_Click(object sender, EventArgs e) 87 { 88 //根据当前串口对象,来判断操作 89 if (comm.IsOpen) 90 { 91 closing = true; 92 while (listenning)//监听时做完ui操作 93 Application.DoEvents(); 94 //打开时点击,则关闭串口 95 comm.Close(); 96 closing = false; 97 } 98 else 99 { 100 //关闭时点击,则设置好端口,波特率后打开 101 comm.PortName = comboPortName.Text; 102 comm.BaudRate = int.Parse(comboBaudrate.Text); 103 try 104 { 105 comm.Open(); 106 } 107 catch(Exception ex) 108 { 109 //捕获到异常信息,创建一个新的comm对象,之前的不能用了。 110 comm = new SerialPort(); 111 //现实异常信息给客户。 112 MessageBox.Show(ex.Message); 113 } 114 } 115 //设置按钮的状态 116 buttonOpenClose.Text = comm.IsOpen ? "Close" : "Open"; 117 buttonSend.Enabled = comm.IsOpen; 118 } 119 120 //动态的修改获取文本框是否支持自动换行。 121 private void checkBoxNewlineGet_CheckedChanged(object sender, EventArgs e) 122 { 123 txGet.WordWrap = checkBoxNewlineGet.Checked; 124 } 125 126 private void buttonSend_Click(object sender, EventArgs e) 127 { 128 //定义一个变量,记录发送了几个字节 129 int n = 0; 130 //16进制发送 131 if (checkBoxHexSend.Checked) 132 { 133 //我们不管规则了。如果写错了一些,我们允许的,只用正则得到有效的十六进制数 134 MatchCollection mc = Regex.Matches(txSend.Text, @"(?i)[\da-f]{2}"); 135 List<byte> buf = new List<byte>();//填充到这个临时列表中 136 //依次添加到列表中 137 foreach (Match m in mc) 138 { 139 buf.Add(byte.Parse(m.Value)); 140 } 141 //转换列表为数组后发送 142 comm.Write(buf.ToArray(), 0, buf.Count); 143 //记录发送的字节数 144 n = buf.Count; 145 } 146 else//ascii编码直接发送 147 { 148 //包含换行符 149 if (checkBoxNewlineSend.Checked) 150 { 151 comm.WriteLine(txSend.Text); 152 n = txSend.Text.Length + 2; 153 } 154 else//不包含换行符 155 { 156 comm.Write(txSend.Text); 157 n = txSend.Text.Length; 158 } 159 } 160 send_count += n;//累加发送字节数 161 labelSendCount.Text = "Send:" + send_count.ToString();//更新界面 162 } 163 164 private void buttonReset_Click(object sender, EventArgs e) 165 { 166 //复位接受和发送的字节数计数器并更新界面。 167 send_count = received_count = 0; 168 labelGetCount.Text = "Get:0"; 169 labelSendCount.Text = "Send:0"; 170 } 171 } 172 }
这里的listening的细节可以避免串口关闭的锁死的情况
时间: 2024-10-16 15:36:44