*在跟着别人写了一遍过后,发现串口软件会把原本一个整体的内容当成两次内容,导致显示出来的时候会发现内容会在中间出现换行*
*通过尝试,在DataReceived事件触发后,不要立即从缓冲区读取发来的内容,设置Sleep等待50ms。然后就可解决问题*

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace PortHelper
{
public partial class Form1:Form
{
private SerialPort SerialPort = new SerialPort();
public Form1()
{
InitializeComponent();
InitConfig();
}
private void InitConfig()
{
//GetPortNames()返回值是string[] ,自动返回你电脑上的串口名
cbSerial.Items.AddRange(SerialPort.GetPortNames());
if(cbSerial.Items.Count>0)
{
cbSerial.SelectedIndex = 0;
}
else
{
cbSerial.Text = "未检测到串口";
}
//对波特率的combobox项使用代码进行设置, 一般在控件上直接设置就好了
string[] baudData = new String[] {"9600", "19200", "38400","57600", "115200","Custom"};
cbBaudRate.Items.AddRange(baudData);
cbBaudRate.SelectedIndex = 0;//作用:下拉列表框里会默认显示9600
//对其他几个也进行默认设置
cbDataBits.SelectedIndex = 3;//数据位列表框
cbStop.SelectedIndex = 0;//停止位列表框
cbParity.SelectedIndex = 0;//校验位列表框
//所有的下拉框都不能随意输入内容,只能当选中特定项时才能输入
cbSerial.DropDownStyle = ComboBoxStyle.DropDownList;
cbBaudRate.DropDownStyle = ComboBoxStyle.DropDownList;
cbDataBits.DropDownStyle = ComboBoxStyle.DropDownList;
cbStop.DropDownStyle = ComboBoxStyle.DropDownList;
cbParity.DropDownStyle = ComboBoxStyle.DropDownList;
//默认状态下,编码方式设为ASCII
radioButton1.Checked = true;
SerialPort.DataReceived += new SerialDataReceivedEventHandler(Com_DataReceived);
}
private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//当这个事件解决器响应后,不要让它立刻去读缓冲区的内容,等50ms再读,
//否则内容还没完全写到缓冲区内就被读走了,就会出现我开头出现的状况
//添加了这个等待时间再去读取就不会出现一个完整的内容要读两次;一定要写在开头,不然也没用
System.Threading.Thread.Sleep(50);
从缓冲区读取数据到byte[]
byte[] reDatas = new byte[SerialPort.BytesToRead];//BytesToRead字段:获取接收缓冲区中数据的字节数
SerialPort.Read(reDatas, 0, reDatas.Length);
//实现数据解码
AddData(reDatas);
}
public void AddData(byte[] Data)
{
if(radioButton1.Checked)
{
AddContent(new ASCIIEncoding().GetString(Data));
}
else if(radioButton2.Checked)
{
StringBuilder sb = new StringBuilder();
for(int i=0 ; i<Data.Length; i++)
{
sb.AppendFormat("{0:x2}" + " ", Data[i]);
}
//你若把上面的x换成X,下面这句中就不需要ToUpper()再去转换成大写了
AddContent(sb.ToString().ToUpper());
}
}
private void AddContent(string content)
{
BeginInvoke(new MethodInvoker(delegate
{
//txtRecv是我控件的name
txtRecv.AppendText(content + "\r\n");
SerialPort.DiscardInBuffer();
}));
}
private void start_button_Click(object sender, EventArgs e)
{
if(SerialPort.IsOpen == false)
{
//把串口的属性配置好后,才能连接通信
SerialPort.PortName = cbSerial.SelectedItem.ToString();
SerialPort.BaudRate = Convert.ToInt32(cbBaudRate.Text.ToString());
SerialPort.DataBits = Convert.ToInt32(cbDataBits.SelectedItem.ToString());
SerialPort.StopBits =(StopBits)Convert.ToInt32(cbStop.SelectedItem.ToString());
SerialPort.Parity = (Parity)Convert.ToInt32(cbParity.SelectedIndex.ToString());
try
{
SerialPort.Open();
send_button.Enabled = true;
}
catch(Exception ex)
{
MessageBox.Show("未能成功开启串口");
return;
}
start_button.Text = "关闭";
}
else
{
try
{
SerialPort.Close();
send_button.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show("关闭失败");
}
start_button.Text = "开启";
}
cbSerial.Enabled = !SerialPort.IsOpen;
cbBaudRate.Enabled = !SerialPort.IsOpen;
cbDataBits.Enabled = !SerialPort.IsOpen;
cbStop.Enabled = !SerialPort.IsOpen;
cbParity.Enabled =!SerialPort.IsOpen;
}
private void send_button_Click(object sender, EventArgs e)
{
byte[] sendData = null;
if(radioButton1.Checked)
{
sendData = Encoding.ASCII.GetBytes(txtSend.Text.Trim());
}
else if(radioButton2.Checked)
{
sendData = ToHexFromString(txtSend.Text.Trim());
}
SerialPort.Write(sendData, 0, sendData.Length);
}
//这个函数我写的有些问题,后面再完善,不过对现在使用没影响
private byte[] ToHexFromString(string str)
{
byte[] data = Encoding.ASCII.GetBytes(str);
StringBuilder builder = new StringBuilder();
for(int i=0;i<data.Length; i++)
{
builder.AppendFormat("{0:X2}" + " ", data[i]);
}
string strTemp = builder.ToString().Trim();
string[] chars = strTemp.Split(new char[] {' '});
byte[] hexByte = new byte[chars.Length];
for(int i=0; i<chars.Length; i++)
{
hexByte[i] = Convert.ToByte(chars[i],16);
}
return hexByte;
}
private void clear_btn_Click(object sender, EventArgs e)
{
txtRecv.Clear();
}
}
}
##问题
编写的时候参考内容链接:link