初学C# 写的第一个上位机 很多东西都不懂 勉强实现了功能
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;
using StudentSerialPort;
using System.IO;
using System.Threading;
namespace 串口助手
{
public partial class Form1 : Form
{
private SerialPort ComDevice = new SerialPort();
private StringBuilder builder = new StringBuilder();
private UInt32 tx, rx = 0;
OpenFileDialog file = new OpenFileDialog();
public Form1()
{
InitializeComponent();
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; //不检查跨线程访问
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (string portName in GetHardName.GetSerialPort())
{
comboBox1.Items.Add(portName);//直接获取设备名
}
// comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames()); //只获取可用COM口
comboBox1.SelectedIndex=comboBox1.Items.Count>1?1:0;//默认选择第一个可用的串口
comboBox2.Text = "115200";
comboBox3.Text = "无校验";
comboBox4.Text = "1位";
comboBox5.Text = "8位";
radioButton2.Checked = true;
radioButton4.Checked = true;
timer1.Stop();//关闭定时器
toolStripStatusLabel1.Text = DateTime.Now.ToString() + " |";
toolStripStatusLabel2.Text = "接收:" + rx.ToString() + " " + "发送:" + tx.ToString() + " |";
toolStripStatusLabel3.Text = "|未选择文件|";
ComDevice.Encoding = System.Text.Encoding.GetEncoding("GB2312");
//向ComDevice.DataReceived(是一个事件)注册一个方法Com_DataReceived,
//当端口类接收到信息时时会自动调用Com_DataReceived方法
ComDevice.DataReceived += new SerialDataReceivedEventHandler(Com_DataReceived);
}
/// <summary>
/// 串口接收事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
if (radioButton4.Checked)//字符模式接收
{
//int len = ComDevice.BytesToRead;
//rx += (uint)len;
//ComDevice.Encoding = System.Text.Encoding.GetEncoding("GB2312");
string str = ComDevice.ReadExisting();
rx += (UInt32)str.Length;//获取接收字节数
// builder.Append(Encoding.Default.GetString(buf));
// this.textBox1.AppendText(builder.ToString());
toolStripStatusLabel2.Text = "接收:" + rx.ToString() + " " + "发送:" + tx.ToString() + " |";
this.textBox1.AppendText(str);
}
else//数值模式
{
int n = ComDevice.BytesToRead;
byte[] buf = new byte[n];
ComDevice.Read(buf, 0, n);
builder.Clear();
rx += (UInt32)n;
toolStripStatusLabel2.Text = "接收:" + rx.ToString() +" "+ "发送:" + tx.ToString() + " |";
foreach (byte i in buf)
{
builder.Append(i.ToString("x2") + " ");
}
this.textBox1.AppendText(builder.ToString());
}
}
catch
{ }
}
/// <summary>
/// 打开或关闭端口按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "打开端口")
{
try
{
int start = comboBox1.Text.IndexOf("COM");
int stop = comboBox1.Text.IndexOf(")");
ComDevice.PortName = comboBox1.Text.Substring(start, stop - start);
ComDevice.BaudRate = Convert.ToInt32(comboBox2.Text);
switch (comboBox3.Text)//校验位选择
{
case "无校验":
ComDevice.Parity = Parity.None;break;
case "奇校验":
ComDevice.Parity = Parity.Odd;break;
case "偶校验":
ComDevice.Parity = Parity.Even; break;
case "1校验":
ComDevice.Parity = Parity.Mark; break;
case "0校验":
ComDevice.Parity = Parity.Space; break;
default: ComDevice.Parity = Parity.None; break;
}
switch (comboBox4.Text)//停止位选择
{
case "1位":
ComDevice.StopBits = StopBits.One; break;
case "1.5位":
ComDevice.StopBits = StopBits.OnePointFive; break;
case "2位":
ComDevice.StopBits = StopBits.Two; break;
default: ComDevice.StopBits = StopBits.One; break;
}
switch (comboBox5.Text)//数据位选择
{
case "8位":
ComDevice.DataBits = 8; break;
case "7位":
ComDevice.DataBits = 7; break;
default: ComDevice.DataBits = 8; break;
}
ComDevice.Open();
this.Invoke(new EventHandler(delegate
{
button1.Text = "关闭端口";
comboBox1.Enabled = false;
comboBox2.Enabled = false;
comboBox3.Enabled = false;
comboBox4.Enabled = false;
comboBox5.Enabled = false;
button2.Enabled = false;
}));
}
catch
{
MessageBox.Show("端口打开失败!", "警告");
}
}
else
{
ComDevice.Close();
this.Invoke(new EventHandler(delegate//委托主线程改变button1.Text内容
{
button1.Text = "打开端口";
button2.Enabled = true;
comboBox1.Enabled = true;
comboBox2.Enabled = true;
comboBox3.Enabled = true;
comboBox4.Enabled = true;
comboBox5.Enabled = true;
}));
}
}
private void button2_Click(object sender, EventArgs e)//刷新按钮
{
comboBox1.Items.Clear();
foreach (string portName in GetHardName.GetSerialPort())
{
comboBox1.Items.Add(portName);
}
comboBox1.SelectedIndex = comboBox1.Items.Count > 1 ? 1 : 0;
}
private void button3_Click(object sender, EventArgs e)//发送按钮
{
if (!ComDevice.IsOpen)
{
MessageBox.Show("请先打开一个串口", "提示");
return;
}
Send();
}
private void button5_Click(object sender, EventArgs e)//清空发送区
{
textBox2.Text = "";
}
private void timer1_Tick(object sender, EventArgs e)//定时器事件
{
Send();//发送
}
private void Send()
{
Thread t1 = new Thread(new ThreadStart(serialsend));//创建一个接收线程
t1.Start();//发送线程启动
}
/// <summary>
/// 串口发送指定字符串
/// </summary>
/// <param name="str1"></param>
private void Send(string str1)
{
try
{
byte[] texts = System.Text.Encoding.Default.GetBytes(str1);
ComDevice.Write(texts, 0, texts.Length);
// toolStripProgressBar1.Value = texts.Length;
tx += (UInt32)str1.Length;
toolStripStatusLabel2.Text = "接收:" + rx.ToString() + " " + "发送:" + tx.ToString() + " |";
}
catch
{ }
}
private void serialsend()
{
if (radioButton1.Checked == true)//数值发送模式
{
if (textBox2.Text != "")//发送输入框有内容
{
if (IsHex(textBox2.Text))//判断是否是16进制
{
try
{
// textBox2.Text = textBox2.Text.Replace(" ", "");
// textBox2.Text = textBox2.Text.Replace("\r", "");
// textBox2.Text = textBox2.Text.Replace("\n", "");
byte[] data = new byte[1];
// MessageBox.Show(textBox2.Text.Length.ToString());
for (int i = 0; i < textBox2.Text.Length / 2; i++)
{
data[0] = Convert.ToByte(textBox2.Text.Substring(i * 2, 2).ToUpper(), 16);
//MessageBox.Show(data[0].ToString());
ComDevice.Write(data, 0, 1);
}
if (textBox2.Text.Length % 2 != 0)
{
data[0] = Convert.ToByte(textBox2.Text.Substring(textBox2.Text.Length - 1, 1).ToUpper(), 16);
ComDevice.Write(data, 0, 1);
}
tx += (UInt32)textBox2.Text.Length;
toolStripStatusLabel2.Text = "接收:" + rx.ToString() + " " + "发送:" + tx.ToString() + " |";
}
catch
{
MessageBox.Show("请输入“0-9”“A-F”“a-f”", "提示");
}
}
else//发送输入框含有非16进制内容 转换成ascii 码发送
{
try
{
byte[] ascii = System.Text.Encoding.ASCII.GetBytes(textBox2.Text);//将当前内容转换成ascii码
ComDevice.Write(ascii, 0, textBox2.Text.Length);
tx += (UInt32)textBox2.Text.Length;
toolStripStatusLabel2.Text = "接收:" + rx.ToString() + " " + "发送:" + tx.ToString() + " |";
}
catch
{
}
}
}
else
{ }/*发送框内无内容 等待用户输入*/
}
else//以字符模式发送
{
if (textBox2.Text != "")
{
// textBox2.Text = textBox2.Text.Replace(" ", "");
// textBox2.Text = textBox2.Text.Replace("\r", "");
// textBox2.Text = textBox2.Text.Replace("\n", "");
try
{
//System.Text.Encoding.Default utf8 = new System.Text.UTF8Encoding();
byte[] texts = System.Text.Encoding.Default.GetBytes(textBox2.Text);
ComDevice.Write(texts, 0, texts.Length);
// ComDevice.WriteLine(textBox2.Text);
tx += (UInt32)textBox2.Text.Length;
toolStripStatusLabel2.Text = "接收:" + rx.ToString() + " " + "发送:" + tx.ToString() + " |";
}
catch
{ }
// ComDevice.WriteLine(texts);
}
else
{ }/*发送框内无内容 等待用户输入*/
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)//定时发送勾选框
{
if (checkBox1.Checked && ComDevice.IsOpen)//如果定时发送勾选上 且 串口打开
{
try
{
int time = Convert.ToInt16(textBox3.Text);
if (time < 1 && time > 100000)
{
MessageBox.Show("周期需在1~100000之间", "提示");
checkBox1.Checked = false;
return;
}
timer1.Interval = time;
textBox3.Enabled = false;
timer1.Start();
}
catch
{
MessageBox.Show("周期需在1~100000之间","提示");
checkBox1.Checked = false;
}
}
else
{
textBox3.Enabled = true;
timer1.Stop();
}
}
private void textBox3_KeyPress(object sender, KeyPressEventArgs e)//周期文本框只能输入数字
{
e.Handled = e.KeyChar < '0' || e.KeyChar > '9'; //允许输入数字
if (e.KeyChar == (char)8) //允许输入回退键
{
e.Handled = false;
}
}
/// <summary>
/// 1.以16进制发送时 如果发送输入框无数据 则进制输入非16进制数
/// 2.如果发送输入框已有数据 那么则转换成对应的ascii码发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void textBox2_TextChanged(object sender, EventArgs e)//发送输入框内容改变事件
{
string str = textBox2.Text;
if ( radioButton1.Checked )//16进制模式
{
if (str == "")return ;
const string PATTERN = @"[A-Fa-f0-9]+$";//正则匹配
bool sign = false;
for (int i = 0; i < str.Length; i++)
{
sign = System.Text.RegularExpressions.Regex.IsMatch(str[i].ToString(), PATTERN);
if (!sign)
{
return;
}
}
}
}
/// <summary>
/// 判断字符串是否是 16进制
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private bool IsHex(string str)
{
if (str == "") return false;
const string PATTERN = @"[A-Fa-f0-9]+$";//正则匹配
bool sign = false;
for (int i = 0; i < str.Length; i++)
{
sign = System.Text.RegularExpressions.Regex.IsMatch(str[i].ToString(), PATTERN);
if (!sign)
{
return false;
}
}
return true;
}
private void timer2_Tick(object sender, EventArgs e)//定时器2负责更新左下角时间
{
this.Invoke(new EventHandler(delegate
{
toolStripStatusLabel1.Text = DateTime.Now.ToString() + " |";
}));
}
private void button6_Click(object sender, EventArgs e)//打开文件按钮
{
file.Filter = "文本文件(*.txt)|*.txt|所有文件(*.*)|*.*|HEX文件(*.hex*)|*.hex*";//文件过滤器
//记忆上次打开的目录
file.RestoreDirectory = true;
//设置是否允许多选
file.Multiselect = false;
if (file.ShowDialog() == DialogResult.OK)
{
//显示文件名和拓展名
toolStripStatusLabel3.Text = "|" + System.IO.Path.GetFileName(file.SafeFileName) + "|";
}
}
/// <summary>
/// 文件名如果无效 还未做处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button7_Click(object sender, EventArgs e)//发送文件按钮
{
if (ComDevice.IsOpen)
{
try
{
string str = File.ReadAllText(file.FileName, Encoding.Default);//读取文件
// toolStripProgressBar1.Maximum = str.Length;
// toolStripProgressBar1.Value = 0;
Send(str);
}
catch
{ }
}
else
{
MessageBox.Show("请打开一个串口","提示");
}
}
private void button4_Click_1(object sender, EventArgs e)//清空接收区
{
textBox1.Text = "";
tx = rx = 0;
toolStripStatusLabel2.Text = "接收:" + rx.ToString() + " " + "发送:" + tx.ToString() + " |";
}
}
}
源码下载地址