最近跟着刘工写了一套用于单片机与电脑通信的串口助手,此处将自己手敲的代码记录下来,供大家一起学习交流。
一、程序界面
程序界面
程序界面说明 文章来源:https://www.toymoban.com/news/detail-514385.html
二、代码(Form1.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Runtime.InteropServices;
namespace 上位机模板
{
public partial class Form1 : Form
{
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
string FileName = System.AppDomain.CurrentDomain.BaseDirectory + "Backup.ini";//ini文件名
StringBuilder BackupBuf = new StringBuilder(100);
bool Timer3_Flag = false;
public Form1()
{
InitializeComponent();
serialPort1.Encoding = Encoding.GetEncoding("GB2312");
//关闭跨线程错误报告
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
}
//查找串口,并加到comboBox1中
private void SearchAndAddSerialToComboBox(SerialPort MyPort, ComboBox MyBox, TextBox MyTextBox)
{
string[] ComputerPortName = SerialPort.GetPortNames();
string BackupPort;
GetPrivateProfileString("串口1", "端口号", "", BackupBuf, 100, FileName);
BackupPort = BackupBuf.ToString();
MyBox.Items.Clear();
MyBox.Text = "";
for (byte i = 0; i < ComputerPortName.Length; i++)
{
try
{
MyPort.PortName = ComputerPortName[i];
MyPort.Open();
MyBox.Items.Add(MyPort.PortName);
MyPort.Close();
if (BackupPort == MyPort.PortName)
{
MyBox.Text = BackupPort;
}
if (MyBox.Text == "")
{
MyBox.Text = MyPort.PortName;
}
}
catch
{
}
}
if(MyBox.Text == "")
{
MyTextBox.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
MyTextBox.AppendText("没有检测到串口!\r\n");
}
WritePrivateProfileString("串口1", "端口号", MyBox.Text, FileName);
}
//CRC校验
private UInt16 Crc_Check(byte[] Data, byte DataLEN)
{
UInt16 CRC = 0xFFFF;
for (byte i = 0; i < DataLEN; i++)
{
CRC ^= Data[i];
for (byte j = 0; j < 8; j++)
{
if ((CRC & 0x0001) == 0x0001)
{
CRC = (UInt16)((CRC >> 1) ^ 0xA001);
}
else
{
CRC = (UInt16)(CRC >> 1);
}
}
}
CRC = (UInt16)((CRC >> 8) + (CRC << 8));
return CRC;
}
//手动扫描按键
private void button1_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen == true)
{
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
//timer1.Stop();
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("扫描并添加串口时关闭串口!\r\n");
}
SearchAndAddSerialToComboBox(serialPort1, comboBox1, textBox1);
}
//串口开关按键
private void button2_Click(object sender, EventArgs e)
{
if (button2.Tag.ToString() == "ON")
{
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("手动关闭串口!\r\n");
}
else
{
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text, 10);
serialPort1.Open();
button2.BackgroundImage = Properties.Resources.Image_OpenSerial;
button2.Tag = "ON";
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("串口开启成功!\r\n");
timer1.Start();
}
catch
{
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("串口开启失败!\r\n");
timer1.Stop();
}
}
WritePrivateProfileString("串口1", "端口号", comboBox1.Text, FileName);
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox2.Text = "115200";
SearchAndAddSerialToComboBox(serialPort1, comboBox1, textBox1);
//恢复发送栏
GetPrivateProfileString("串口1", "发送栏", "", BackupBuf, 100, FileName);
textBox2.Text = BackupBuf.ToString();
}
//下拉框切换串口
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (serialPort1.IsOpen == true)
{
serialPort1.Close();
try
{
serialPort1.Open();
button2.BackgroundImage = Properties.Resources.Image_OpenSerial;
button2.Tag = "ON";
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("串口更换成功!\r\n");
}
catch
{
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("串口更换失败!\r\n");
}
}
}
//扫描串口定时器
private void timer1_Tick(object sender, EventArgs e)
{
if (serialPort1.IsOpen == false)
{
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
SearchAndAddSerialToComboBox(serialPort1, comboBox1, textBox1);
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//接收ASCII格式
if (checkBox1.Checked == false)
{
try
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
string str = serialPort1.ReadExisting();
textBox1.AppendText(str);
textBox1.AppendText("\r\n");
//统计接收字节数
UInt32 RBytes = Convert.ToUInt32(textBox4.Text, 10);
RBytes += (UInt32)str.Length;
textBox4.Text = RBytes.ToString();
}
catch
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("ASCII格式接受错误!\r\n");
}
}
//接收HEX格式
else
{
try
{
if (Timer3_Flag == true)
{
Timer3_Flag = false;
textBox1.AppendText("\r\n");
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
}
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
byte[] data = new byte[serialPort1.BytesToRead];
serialPort1.Read(data, 0, data.Length);
for (int Member = 0; Member < data.Length; Member++)
{
string str = Convert.ToString(data[Member], 16).ToUpper();
textBox1.AppendText(((str.Length == 1) ? ("0" + str) : str) + " ");
}
textBox1.AppendText("\r\n");
//统计接收字节数
UInt32 RBytes = Convert.ToUInt32(textBox4.Text, 10);
RBytes += (UInt32)data.Length;
textBox4.Text = RBytes.ToString();
}
catch
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("HEX格式接受错误!\r\n");
}
}
}
//清除接收按键
private void button3_Click(object sender, EventArgs e)
{
textBox1.Clear();
textBox4.Text = "0";
}
//串口发送按键
private void button4_Click(object sender, EventArgs e)
{
byte[] data = new byte[1];
//发送ASCII格式
if (checkBox2.Checked == false)
{
try
{
//支持中文
Encoding Chinese = System.Text.Encoding.GetEncoding("GB2312");
byte[] Sendbytes = Chinese.GetBytes(textBox2.Text);
for (int Member = 0; Member < Sendbytes.Length; Member++)
{
data[0] = (byte)Sendbytes[Member];
serialPort1.Write(data, 0, 1);
}
if (checkBox4.Checked == true)
{
data[0] = 0X0D;
serialPort1.Write(data, 0, 1);
data[0] = 0X0A;
serialPort1.Write(data, 0, 1);
}
//统计发送字节数
UInt32 SBytes = Convert.ToUInt32(textBox3.Text, 10);
SBytes += (UInt32)Sendbytes.Length;
if (checkBox4.Checked == true)
{
SBytes += 2;
}
textBox3.Text = SBytes.ToString();
}
catch
{
textBox1.AppendText("\r\n串口发送错误!\r\n");
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
}
}
//发送HEX格式
else
{
string Buf = textBox2.Text.ToUpper();
Buf = Buf.Replace("0X", "");
Buf = Buf.Replace(" ", "");
byte[] Calculate_Crc = new byte[Buf.Length / 2];
textBox2.Clear();
try
{
for (int i = 0; i < Buf.Length / 2; i++)
{
textBox2.AppendText(Buf.Substring(i * 2, 2) + " ");
data[0] = Convert.ToByte(Buf.Substring(i * 2, 2), 16);
serialPort1.Write(data, 0, 1);
Calculate_Crc[i] = data[0];
}
//统计发送字节数
UInt32 SBytes = Convert.ToUInt32(textBox3.Text, 10);
SBytes += (UInt32)(Buf.Length / 2);
if (checkBox3.Checked == true)
{
SBytes += 2;
}
textBox3.Text = SBytes.ToString();
}
catch
{
textBox1.AppendText("\r\n串口发送错误!\r\n");
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
}
//发送CRC
if (checkBox3.Checked == true)
{
UInt32 CRC = Crc_Check(Calculate_Crc, (byte)Calculate_Crc.Length);
byte CRC_H = (byte)(CRC >> 8);
byte CRC_L = (byte)CRC;
try
{
data[0] = CRC_L;
serialPort1.Write(data, 0, 1);
data[0] = CRC_H;
serialPort1.Write(data, 0, 1);
}
catch
{
textBox1.AppendText("\r\n串口发送错误!\r\n");
serialPort1.Close();
button2.BackgroundImage = Properties.Resources.Image_CloseSerial;
button2.Tag = "OFF";
}
}
}
if (checkBox5.Checked == true)
{
textBox2.Clear();
}
}
//清除发送按键
private void button5_Click(object sender, EventArgs e)
{
textBox2.Clear();
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
if (checkBox2.Checked == true)
{
checkBox4.Enabled = false;
checkBox3.Enabled = true;
}
else
{
checkBox4.Enabled = true;
checkBox3.Enabled = false;
}
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
WritePrivateProfileString("串口1", "发送栏", textBox2.Text, FileName);
}
private void checkBox6_CheckedChanged(object sender, EventArgs e)
{
//启动定时发送
if (checkBox6.Checked == true)
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("启动定时发送!\r\n");
try
{
timer2.Interval = Convert.ToUInt16(comboBox3.Text);
}
catch
{
MessageBox.Show("输入时间有误,设定为默认值", "提示");
comboBox3.Text = "1000";
timer2.Interval = 1000;
}
timer2.Start();
}
//关闭定时发送
else
{
textBox1.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "->");
textBox1.AppendText("关闭定时发送!\r\n");
timer2.Stop();
}
}
//定时发送定时器
private void timer2_Tick(object sender, EventArgs e)
{
button4.PerformClick();
}
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
timer2.Interval = Convert.ToUInt16(comboBox3.Text);
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
//开启断帧
if (checkBox1.Checked == true)
{
comboBox4.Enabled = true;
timer3.Interval = Convert.ToUInt16(comboBox4.Text);
timer3.Start();
}
//关闭断帧
else
{
comboBox4.Enabled = false;
timer3.Stop();
}
}
//断帧定时器
private void timer3_Tick(object sender, EventArgs e)
{
Timer3_Flag = true;
}
//断帧选项改变
private void comboBox4_SelectedIndexChanged(object sender, EventArgs e)
{
timer3.Interval = Convert.ToUInt16(comboBox4.Text);
}
//波特率选项改变
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text, 10);
}
}
}
三、备注
此处在Form1的属性中,将AutoSize设为True,AutoScroll设为True,AutoScaleMode设为Font,以应对在不同分辨率显示下的界面失真问题。文章来源地址https://www.toymoban.com/news/detail-514385.html
到了这里,关于使用Microsoft Visual Studio编写C#上位机(串口助手)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!