生产中经常会使用到串口来处理数据,在此做一下记录:
- 1.创建界面
在WinForm中创建界面还是相对比较简单的。串口相关的界面主要包含以下几点
- 串口选择框
- 波特率选择框
- 开启、关闭按钮
大致如下:
注意
红色的图片表示的是串口开启的状态,为了便于区分当前串口状态。红色表示关闭,绿色表示开启
- 2.窗口开启/关闭
/// <summary>
/// 自动加载获取串口
/// </summary>
private void GetComList()
{
string[] ports = SerialPort.GetPortNames();
foreach (string port in ports)
{
cbbCom.Properties.Items.Add(port);
}
if (cbbCom.Properties.Items.Count > 0)
{
cbbCom.SelectedIndex = 0;
cbbCom.Enabled = true;
}
}
/// <summary>
/// 定义的串口
/// </summary>
SerialPort ComDevice = new SerialPort();
/// <summary>
/// 串口开启/关闭事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnCom_Click(object sender, EventArgs e)
{
try
{
if (cbbCom.SelectedIndex < 0 || cbbBaudRate.SelectedIndex < 0)
{
XtraMessageBox.Show("请选择波特率 或 串口","消息",MessageBoxButtons.OK,MessageBoxIcon.Warning);
return;
}
if (BtnCom.Tag.ToString() == "0")
{
ComDevice.PortName = cbbCom.SelectedItem.ToString();//串口
ComDevice.BaudRate = Convert.ToInt32(cbbBaudRate.Text.Trim());//波特率吧
ComDevice.Parity = (Parity)0;
ComDevice.DataBits = 8;
ComDevice.ParityReplace = 0x00;//<<<<<<<<<<------------很重要!!!
ComDevice.StopBits = (StopBits)1;
ComDevice.ReadTimeout = 300;//
ComDevice.Encoding = Encoding.Default;//System.Text.Encoding.GetEncoding("GB2312");//此行非常重要 可解决接收中文乱码问题
try
{
ComDevice.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
BtnCom.Text = "关闭串口";
BtnCom.Tag = "1";
cbbCom.Enabled = false;
picComStatus.Image = Properties.Resources.green;
ComDevice.DataReceived += new SerialDataReceivedEventHandler(ComDevice_DataReceived);
}
else
{
try
{
ComDevice.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
BtnCom.Text = "开启串口";
BtnCom.Tag = "0";
cbbCom.Enabled = true;
picComStatus.Image = Properties.Resources.red;
}
}
catch (Exception ex)
{
XtraMessageBox.Show(ex.ToString());
}
}
- 3.数据处理
private StringBuilder builder = new StringBuilder();
/// <summary>
/// 串口的DataReceived事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ComDevice_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int n = ComDevice.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
ComDevice.Read(buf, 0, n);//读取缓冲数据
//因为要访问ui资源,所以需要使用invoke方式同步ui。
this.Invoke((EventHandler)(delegate
{
string strCode = System.Text.Encoding.ASCII.GetString(buf);//builder.ToString();
try
{
builder.Append(strCode);
if (builder[builder.Length - 1] == '\r')
{
Analyse(builder.ToString().Substring(0, builder.Length - 1));
builder.Clear();
}
else if (builder[builder.Length - 2] == '\r' && builder[builder.Length - 1] == '\n')
{
Analyse(builder.ToString().Substring(0, builder.Length - 2));
builder.Clear();
}
}
catch { }
}));
}
/// <summary>
/// 串口数据处理
/// </summary>
/// <param name="sn"></param>
private void Analyse(string data)
{
//ToDo数据处理
//发送数据到光标所在的位置,并带回车键,
//是否需要回车视具体情况而定,如果扫描枪自带回车,这里可以去除
SendKeys.SendWait(sn + "{ENTER}");
}