• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

C#上位机串口工具

武飞扬头像
"dandan"不能定义
帮助1

1.窗体设计
学新通

注意:
1.上述窗体用到了按钮、Radio、Panel、GroupBox、TextBox、SerialPorts、ComboBox等控件,组件。
2.对于Panel、GroupBox控件,需要先插入。再插入其他控件。其中Panel一般是为了将Radio进行组合而使用。GroupBox是为了更明显的显示界面给用户。
3.其中TextBox一般只能横向拉伸,不能纵向拉伸,选择TsxtBox框上的黑色三角符号,然后勾选“MultiLine”之后,即可进行上下左右拉伸。其中为了让其出现滚动条可以在属性中选择“ScrollBars”。
学新通学新通

2.窗体函数事件
2.1 窗体函数中直接进行初始化和设置

//窗体事件
private void Form1_Load(object sender, EventArgs e)
{
	//对端口进行设置
	for (int i = 1; i < 20; i  )
	{
		comboBox1.Items.Add("COM"  i.ToString());
	}
	//对串口号、波特率进行默认值设置
	comboBox1.Text = "COM1";
	comboBox2.Text = "4800";
	radioButton1.Checked = true;   //函数中选择发送模式 为“数值”发送模式。 radioButton1为单选按钮属性(name)名字
	radioButton3.Checked = true;   //函数中选择接收模式 为“数值”接收模式。 radioButton3为单选按钮属性(name)名字
	button1.Text = "打开串口";     //确保 “打开串口”按键文本属性为 “打开串口”
	button2.Text = "关闭串口";     //确保 “关闭串口”按键文本属性为 “关闭串口”
}
学新通

学新通

主要是进行窗体初始化设置,下拉框设置,选择发送模式 和接收模式设置为“数值”模式。

2.2 在窗体函数中,只进行初始化,其他工作封装在一个函数中。

//窗体事件
private void Form1_Load(object sender, EventArgs e)
{
	Updata_Serialport_Name(comboBox1);  //调用更新可用串口函数,comboBox1为 端口 组合框名字
	
	/*//对端口进行设置
	for (int i = 1; i < 20; i  )
	{
		comboBox1.Items.Add("COM"  i.ToString());
	}*/
	//对串口号、波特率进行默认值设置
	comboBox1.Text = "COM1";
	comboBox2.Text = "4800";
	radioButton1.Checked = true;   //函数中选择发送模式 为“数值”发送模式。 radioButton1为单选按钮属性(name)名字
	radioButton3.Checked = true;   //函数中选择接收模式 为“数值”接收模式。 radioButton3为单选按钮属性(name)名字
	button1.Text = "打开串口";     //确保 “打开串口”按键文本属性为 “打开串口”
	button2.Text = "关闭串口";     //确保 “关闭串口”按键文本属性为 “关闭串口”

	//必须手动添加处理串口数据接收
	//serialPort1.DataReceived  = new  EventHandler(this.Port_DataReceived);//SerialDataReceived 
}
/*用户自定义更新可用串口函数*/
private void Updata_Serialport_Name(ComboBox MycomboBox)
{
	//System.IO.Ports.SerialPort.GetPortNames()函数功能为获取计算机所有可用串口,以字符串数组形式输出
	string[] ArryPort = System.IO.Ports.SerialPort.GetPortNames(); //定义字符串数组,数组名为 ArryPort,将可用的串口信息存放在字符串中
	MycomboBox.Items.Clear();       //清除当前组合框下拉菜单内容                  
	for (int i = 0; i < ArryPort.Length; i  )
	{
		MycomboBox.Items.Add(ArryPort[i]);   //将所有的可用串口号添加到端口对应的组合框中
	}
}
学新通

注意:
1.System.IO.Ports.SerialPort.GetPortNames()函数功能为获取计算机所有可用串口,以字符串数组形式输出。可简写为SerialPort.GetPortNames()。但要加using System.IO.Ports;命名空间
2.MycomboBox.Items.Add()在MycomboBox控件下添加下拉信息。
3.Updata_Serialport_Name()该函数类似于串口扫描函数。

学新通
3.串口数据信息接收,字符和数值两种模式进行处理

//串口数据信息接收
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)//SerialDataReceived 
{
//接收方式为字符模式,字符方式读
//Checked:获取或设置一个值,该值指示是否已选中控件。
if (!radioButton3.Checked)
{
	//字符串方式读缓冲区中的数据
	string str = serialPort1.ReadExisting();
	//把读取的数据添加至接收区。AppendText():向文本框的当前文本追加文本。
	textBox2.AppendText(str);
}
//接收方式为数值模式,数值方式读
else
{
	byte data;
	//ReadByte()从 System.IO.Ports.SerialPort 输入缓冲区中同步读取一个字节。返回:强制转换为 System.Int32 的字节;或者,如果已读取到流的末尾,则为 -1。
	//因为函数ReadByte()的返回值为int,因此要转换强制转换为byte。
	data = (byte)serialPort1.ReadByte();
	//Convert.ToString() 将 8 位无符号整数的值转换为其等效的指定基数的字符串表示形式。
	// 参数: 
	// value:要转换的 8 位无符号整数。
	// toBase:返回值的基数,必须是 2、8、10 或 16。
	// 返回结果: 以 toBase 为基数的 value 的字符串表示形式。
	//转换为大写十六进制字符串
	string str = Convert.ToString(data, 16).ToUpper();
	//对单个值,进行补0
	textBox2.AppendText("0x"   ((str.Length == 1) ? "0"   str : str));
	/*
	if (str.Length == 1)
	{
		str = "0"   str;
	}
	else
	{
		str = str;
	}
	textBox2.AppendText("0x"   str);
	 */
}
学新通

注意:
1.Checked:获取或设置一个值,该值指示是否已选中控件。
2.AppendText():向文本框的当前文本追加文本。
3.ReadByte()从 System.IO.Ports.SerialPort 输入缓冲区中同步读取一个字节。返回:强制转换为 System.Int32 的字节;或者,如果已读取到流的末尾,则为 -1。
4.Convert.ToString() 将 8 位无符号整数的值转换为其等效的指定基数的字符串表示形式。
参数:
4.1 value:要转换的 8 位无符号整数。
4.2 toBase:返回值的基数,必须是 2、8、10 或 16。
返回结果:
以 toBase 为基数的 value 的字符串表示形式。
学新通

4.打开按钮

private void button1_Click(object sender, EventArgs e)
{
	try
	{
		//在打开串口之前获取串口号和波特率
		serialPort1.PortName = comboBox1.Text;
		//转换为10进制,10可省略
		serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text,10);
		//打开串口
		serialPort1.Open();
		//打开串口按钮不可用,变成灰色
		button1.Enabled = false;
		//关闭串口按钮可用。
		button2.Enabled = true;
	}
	catch
	{ 
		MessageBox.Show("端口错误,请检查串口","打开串口错误");
	}
   
}
学新通

打开按钮后,打开按钮图标变灰色,不可用。关闭按钮图标可用。

学新通

5.关闭按钮

private void button2_Click(object sender, EventArgs e)
{
	try
	{
		//关闭串口
		serialPort1.Close();
		//打开串口按钮可用
		button1.Enabled = true;
		//关闭串口按钮不可用,变成灰色
		button2.Enabled = false;
	}
	catch
	{
		//一般关闭串口不出错,此处对程序不进行处理
	}
}
学新通

关闭按钮后,关闭按钮图标变灰色,不可用。打开按钮图标可用。
学新通

6.发送按钮,实现串口的发送功能,从字符和数值两个模式进行撰写。

private void button3_Click(object sender, EventArgs e)
{
	byte[] data = new byte[1];
	// IsOpen :获取一个值,该值指示 System.IO.Ports.SerialPort 对象的打开或关闭状态。
	// 返回结果: 如果串行端口已打开,则为 true;否则为 false。 默认值为 false。
	if (serialPort1.IsOpen)//串口打开
	{ 
		//发送框不能为空
		if (textBox1.Text != "")
		{ 
			//发送模式为字符模式
			if (!radioButton1.Checked)
			{
				try
				{
					//将发送的数据存在于缓冲区
					serialPort1.WriteLine(textBox1.Text);
				}
				catch(Exception err)
				{
					MessageBox.Show("串口数据写入错误", "发送错误");
				}
			}
			//发送模式为数值模式
			else
			{
				try
				{
					//文本数据长度
					int dataLength = textBox1.Text.Length;
					//判断本本个数是奇数还是偶数
					int dataRemain = textBox1.Text.Length % 2;
					//(dataLength - dataRemain)/2 十六进制发送时,看有几个字节。

					//处理前length-1个数据
					for (int i = 0; i < (dataLength - dataRemain)/2; i  )
					{
						// Substring(): 
						// 从此实例检索子字符串。 子字符串从指定的字符位置开始且具有指定的长度。
						// 参数: 
						//   startIndex:
						//     此实例中子字符串的起始字符位置(从零开始)。
						//   length:
						//     子字符串中的字符数。
						// 返回结果: 
						//     与此实例中在 startIndex 处开头、长度为 length 的子字符串等效的一个字符串,如果 startIndex 等于此实例的长度且 length
						//     为零,则为 System.String.Empty。
						data[0] = Convert.ToByte(textBox1.Text.Substring(i*2,2),16);//将获取的数值转换为十六进制每两位两位存入data[0]这个字节中

						//Convert.ToByte(): 
						//将指定基数的数字的字符串表示形式转换为等效的 8 位无符号整数。
						// 参数: 
						//   value:
						//     包含要转换的数字的字符串。
						//   fromBase:
						//     value 中数字的基数,它必须是 2、8、10 或 16。
						// 返回结果: 
						//     与 value 中数字等效的 8 位无符号整数,如果 value 为 null,则为 0(零)。

						serialPort1.Write(data, 0, 1);//循环发送每一个字节,如abc则发0xab

						// Write(data, 0, 1): 
						// 使用缓冲区的数据将指定数量的字节写入串行端口。
						// 参数: 
						//   buffer:
						//     包含要写入端口的数据的字节数组。
						//   offset:
						//     buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
						//   count:
						//     要写入的字节数。

					}

					//处理奇数个数据的最后一位
					if(textBox1.Text.Length % 2 != 0)
					{   
						//将最后一位转换为十六进制数据存入data中。
						data[0] = Convert.ToByte(textBox1.Text.Substring(textBox1.Text.Length-1, 1),16);
						//发送最后一位
						serialPort1.Write(data, 0, 1);
					}
				}
				catch (Exception err)
				{
					MessageBox.Show("发送数据错误", "发送错误");
				}
			}

		}
	}

}
学新通

注意:

  1. Substring():
    从此实例检索子字符串。 子字符串从指定的字符位置开始且具有指定的长度。
    参数:
    startIndex:此实例中子字符串的起始字符位置(从零开始)。
    length:子字符串中的字符数。
    返回结果:
    与此实例中在 startIndex 处开头、长度为 length 的子字符串等效的一个字符串,如果 startIndex 等于此实例的长度且 length为零,则为 System.String.Empty。

2.Convert.ToByte():
将指定基数的数字的字符串表示形式转换为等效的 8 位无符号整数。
参数:
value:包含要转换的数字的字符串。
fromBase:value 中数字的基数,它必须是 2、8、10 或 16。
返回结果:
与 value 中数字等效的 8 位无符号整数,如果 value 为 null,则为 0(零)。

3.Write(data, 0, 1):
使用缓冲区的数据将指定数量的字节写入串行端口。
参数:
buffer:包含要写入端口的数据的字节数组。
offset:buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
count:要写入的字节数。

4.IsOpen :
获取一个值,该值指示 System.IO.Ports.SerialPort 对象的打开或关闭状态。
返回结果:
如果串行端口已打开,则为 true;否则为 false。 默认值为 false。
学新通学新通
7.文本框,将滚动条调整至当前位置

private void textBox1_TextChanged(object sender, EventArgs e)
{
	//将滚动条调整至当前位置。
	textBox1.ScrollToCaret();
}

private void textBox2_TextChanged(object sender, EventArgs e)
{
	textBox2.ScrollToCaret();
}

8.清空接收文本

private void button4_Click(object sender, EventArgs e)
{
     textBox2.Text = "";
}

9.运行结果
学新通
往期链接:

1.C#上位机(简单实现串口发送).
2.C#上位机(定时器计数).

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggegaj
系列文章
更多 icon
同类精品
更多 icon
继续加载