当前位置:文档之家› vs2010C#串口通信程序(比较全面)

vs2010C#串口通信程序(比较全面)

/*********************************************
'页面名称: Form1
'作用/描述: 串口通信
'原作者: 未知
'原作日期:
'修改者: yhx
'修改日期: 2014.11.2?
'备注: 补充串口功能,两台电脑的串口通信
'************************************************/

using System;
using System.Collections.Generic;
using https://www.doczj.com/doc/1815347710.html,ponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;

namespace SerialportSample
{
public partial class SerialportSampleForm : Form
{
private int ijinzhi_16 = 0;
private int stoptimesend = 0; //定时发送判断标志位
private long lngstopsend_flag = 0; //意外停止发送标志位
private int itimesendover = 0; //停止再次定时发送标志位
private System.Timers.Timer time; //定时器
private delegate void setText(); //实例化一个委托
private SerialPort comm = new SerialPort(); //串行端口资源
private StringBuilder builder = new StringBuilder(); //避免在事件处理方法中反复的创建,定义到外面。
private long lngreceived_count = 0; //接收字节计数
private long lngsend_count = 0; //发送字节计数
private int Timebutton_Click_count = 0; //定时计数标志位

///


/// 函数功能:初始化器件
///


public SerialportSampleForm()
{
InitializeComponent();
}
///
/// 函数功能:窗体初始化,自动识别COM口,
/// 设置检测到的COM口和默认的波特率
///

///
///
private void Form1_Load(object sender, EventArgs e)
{
//向数据位下拉中添加选项
comboBox2.Items.Add("6");
comboBox2.Items.Add("7");
comboBox2.Items.Add("8");
comboBox2.SelectedIndex = 2; //默认选择数据位“8”
BindParity(); //校验位配置
stopbits(); //停止位配置
foreach (string s in SerialPort.GetPortNames()) //获取当前计算机串行端口的名称
{
comboPortName.Items.Add(s); //自动识别com口
}
comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1; //设置com口
comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600"); //默认波特率是9600

comm.Parity = comboBox1.SelectedValue.ToString() == "0" ? Parity.None : (comboBox1.SelectedValue.ToString() == "1" ? Parity.Odd : Parity.Even); //串口获取奇偶校验位
comm.DataBits = Convert.ToInt16(comboBox2.SelectedItem.ToString()); //串口获取数据位设置长度
comm.StopBits = comboBox3.SelectedValue.ToString() == "0" ? StopBits.None : (comboBox3.SelectedValue.ToString() == "1" ? StopBits.One : (comboBox3.SelectedValue.ToString() == "2" ? StopBits.Two : StopBits.OnePointFive)); //串口获取停止位长度

//初始化SerialPort对象
comm.NewLine = "\r\n"; //换行定义
comm.RtsEnable = true; //根据实际情况吧
TimeGet.Text = "1000";
//comm.ReceivedBytesThreshold = 6;
comm.DataReceived += comm_DataReceived; //添加事件注册
comm.Encoding = System.Text.Encoding.GetEncoding("GB2312");
}
///


/// 函数功能:校验位配置
///

void BindParity()
{
DataTable dt = new DataTable(); //定义数据表
//创建对象并添加到表中(一下两行)
dt.Columns.Add("ValueMember");
dt.Columns.Add("DisplayMember");

for (int i = 0; i < 3; i++)
{
DataRow dr = dt.NewRow(); //创建与上表有相同构架的一行数据

if (((int)Parity.None).Equals(i)) //数据位中的选项为“None”时
{
dr[0] = (int)Parity.None; //将“None”转换类型后放入dr中
dr[1] = Parity.None.ToString();
}

if (((int)Parity.Odd).Equals(i)) //数据位中的选项为“Odd”时
{
dr[0] = (int)Parity.Odd; //将“Odd”转换类型后放入dr中
dr[1] = Parity.Odd.ToString();
}

if (((int)Parity.Even).Equals(i)) //数据位中的选项为“Even”时
{
dr[0] = (int)Parity.Even; //将“Even”转换类型后放入dr中
dr[1] = Parity.Even.ToString();
}

dt.Rows.Add(dr); //将dr添加到dt表的行里
}
comboBox1.DataSource = dt; //设置数据位的内容
//设置数据位的属性(以下两行)
comboBox1.DisplayMember = "DisplayMember";
comboBox1.ValueMember = "ValueMember";
comboBox1.SelectedIndex = 0; //默认选择“Even”
}
///
/// 函数功能:停止位配置
///

void stopbits()
{
DataTable dt = new DataTable();

//定义数据表
//创建对象并添加到表中(一下两行)
dt.Columns.Add("ValueMember");
dt.Columns.Add("DisplayMember");
for (int i = 0; i < 4; i++)
{
DataRow dr = dt.NewRow(); //创建与上表有相同构架的一行数据
if (((int)StopBits.None).Equals(i)) //停止位中的选项为“None”时
{
dr[0] = (int)StopBits.None; //将“None”转换类型后放入dr中
dr[1] = StopBits.None.ToString();
}
if (((int)StopBits.One).Equals(i)) //停止位中的选项为“One”时
{
dr[0] = (int)StopBits.One; //将“One”转换类型后放入dr中
dr[1] = StopBits.One.ToString();
}
if (((int)StopBits.Two).Equals(i)) //停止位中的选项为“Two”时
{
dr[0] = (int)StopBits.Two; //将“Two”转换类型后放入dr中
dr[1] = StopBits.Two.ToString();
}
if (((int)StopBits.OnePointFive).Equals(i)) //停止位中的选项为“OnePointFive”时
{
dr[0] = (int)StopBits.OnePointFive; //将“OnePointFive”转换类型后放入dr中
dr[1] = StopBits.OnePointFive.ToString();
}
dt.Rows.Add(dr); //将dr添加到dt表的行里
}
comboBox3.DataSource = dt; //设置停止位的内容
//设置停止位的属性(一下两行)
comboBox3.DisplayMember = "DisplayMember";
comboBox3.ValueMember = "ValueMember";
comboBox3.SelectedIndex = 1; //默认选择“One”
}

///


/// 函数功能:数据接收函数
/// ASCII接收 和 16进制接收
///

///
///
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string strreceive = ""; //接收缓冲区的字符串变量
int iNum = comm.BytesToRead; //先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
byte[] buf = new byte[iNum]; //声明一个临时数组存储当前来的串口数据
comm.Read(buf, 0, iNum); //读取缓冲数据
builder.Remove(0, builder.Length); //清除字符串构造器的内容
builder.Clear(); //清除缓存
this.Invoke((EventHandler)(delegate //因为要访问ui资源,所以需要使用invoke方式同步ui
{
if (chec

kBoxHexView.Checked) //判断是否是显示为16进制
{
foreach (byte b in buf)
{
builder.Append(b.ToString("X2") + " "); //依次的拼接出16进制字符串
}
this.txGet.AppendText(builder.ToString()); //追加的形式添加到文本框末端,并滚动到最后
}
else //不是16进制接收时执行
{
strreceive = System.Text.Encoding.Default.GetString(buf); //解码汉字字母
builder.Append(strreceive); //直接按ASCII规则转换成字符串
this.txGet.AppendText(strreceive); //追加的形式添加到文本框末端,并滚动到最后
}
lngreceived_count += iNum; // 增加接收计数
labelGetCount.Text = "累计接收:" + lngreceived_count.ToString(); //修改接收计数
}));
}
///


/// 函数功能:打开串口/关闭串口
///

///
///
private void buttonOpenClose_Click(object sender, EventArgs e)
{
if (comm.IsOpen) //根据当前串口对象,判断是否打开
{
textBox1.Text = " 关闭";
comm.Close(); //打开时点击,则关闭串口
}
else
{
//关闭时点击,则设置好端口,波特率后打开
comm.PortName = comboPortName.Text; //记录当前串口号
comm.BaudRate = int.Parse(comboBaudrate.Text); //记录当前波特率
textBox1.Text = " 打开";
try
{
comm.Open(); //打开串口
}
catch(Exception ex)
{
comm = new SerialPort(); //串口出现异常信息,则创建一个新的comm对象,之前的不能用了
MessageBox.Show(ex.Message); //显示异常信息
}
}
//设置按钮的状态
buttonOpenClose.Text = comm.IsOpen ? "关闭串口" : "打开串口"; //同一个按钮显示不同的状态
buttonSend.Enabled = comm.IsOpen; //打开上位机,按钮默认为“打开串口”
}

///
/// 函数功能:点击发送发送数据
///

///
///
private void buttonSend_Click(object sender, EventArgs e)
{
if (comm.IsOpen) //根据当前串口对象,判断是否打开

{
send(); //执行发送函数
}
else //如果未打开串口就进行操作,提示错误
{
MessageBox.Show("请先打开串口!");
}
}
///


/// 函数功能:复位接收的字节数计数器并更新界面。
///

///
///
private void buttonReset_Click(object sender, EventArgs e)
{
lngreceived_count = 0; //接收和发送的字节数计数器清零。
labelGetCount.Text = "累计接收:0"; //接收字节显示为零

}
///
/// 函数功能:子线程中函数可以调用主线程中变量
///


public void Threadp()
{
setText d = new setText(send); //实例化一个委托
this.Invoke(d); //在拥用此控件的基础窗体句柄的线程上执行指定的委托
}

///
/// 函数功能:字符串转换成16进制
///

///
///
public byte[] HexStringToByteArray(string str)
{
byte[] buffer = new byte[str.Length / 2]; //重新定义存储字符数组
try
{
for (int i = 0; i < str.Length; i += 2)
{
buffer[i / 2] = (byte)Convert.ToByte(str.Substring(i, 2), 16); //字符串进行类型转换并储存
}
}
catch
{
ijinzhi_16 = 1;
if (Timebutton_Click_count == 1)// == 1 && itimesendover == 1) //已经选择定时发送
{
//Timebutton_Click_count = 0;
//itimesendover = 0;
lngstopsend_flag = 1; //意外停止发送标志位置1
if (stoptimesend == 0)
{
time.AutoReset = false; //定时时间间隔结束后停止
time.Enabled = false; //不再触发定时器工作
}
MessageBox.Show("请输入正确的十六进制数!"); //输入字符串不为16进制格式时,提示错误
txSend.Text = ""; //发送数据区显示为空
}
else //正常发送
{
lngstopsend_flag = 1; //意外停止发送标志位置1
MessageBox.Show("请输入正确的十六进制数!"); //输入字符串不为16进制格式时,提示错误
}
}
return buffer; //返回字符串转换后的数据
}


///
/// 函数功能:发送数

据,ASCII或者16进制发送
///


private void send()
{
Encoding gb = System.Text.Encoding.GetEncoding("gb2312"); //获取gb2312中文字符编码
byte[] bytsend = gb.GetBytes(txSend.Text); //存放发送区的内容
int istr_num = 0; //记录单次发送窗口输入字节数
string strsendtxt = string.Empty; //字符串中间变量
byte[] bytmessage; //重新定义信息数组
string strsendtext = ""; //记录当前发送窗口内容
//16进制发送
if (txSend.Text == "" && Timebutton_Click_count == 1)
{
time.AutoReset = false; //定时时间间隔结束后停止
time.Enabled = false; //不再触发定时器工作
}
if (txSend.Text.Length != 0) //发送数据区有内容
{
if (checkBoxHexSend.Checked) //勾选16进制发送后执行
{
strsendtext = txSend.Text.Trim(); //记录当前发送窗口内容
strsendtext = strsendtext.Replace(" ", ""); //将字符串中的空格取消
bytmessage = new byte[strsendtext.Length]; //重新定义信息数组
istr_num = strsendtext.Length; //获取当前发送窗口字符串去除空格后的字节数
bytmessage = HexStringToByteArray(strsendtext); //字符串转换成16进制函数
if (lngstopsend_flag == 0) //输入16进制字符串格式正确
{
comm.Write(bytmessage, 0, istr_num / 2); //转换后的数据写入串口
}
}
else //未勾选16进制发送后执行
{
if (comm.IsOpen)
{
comm.Write(bytsend, 0, bytsend.Length); //将发送窗口的内容写入串口
istr_num = bytsend.Length; //存储发送的字节数
}
else
{
itimesendover = 0; //停止再次定时发送标志位清零,下次定时发送时进行判断
time.AutoReset = false; //定时时间间隔结束后停止
time.Enabled = false; //不再触发定时器工作
Timebutton_Click_count = 0; //定时发送点击次数清零
stoptimesend = 0; //允许定时发送标志位
}
}
if (ijinzhi_16 == 0)
{
lngsend_count += istr_num; //累加发

送字节数
labelSendCount.Text = "累计发送:" + lngsend_count.ToString(); //更新界面,显示总发送字节数
}
//lngsend_count += istr_num; //累加发送字节数
//labelSendCount.Text = "累计发送:" + lngsend_count.ToString(); //更新界面,显示总发送字节数

}
else //发送数据区没有内容
{

if (Timebutton_Click_count == 1) //已经点击过定时发送
{
MessageBox.Show("发送内容不能为空!请先停止发送,进行修改后,再次发送!"); //错误提醒
stoptimesend = 1; //中断定时发送的标志位置1,
//Timebutton_Click_count = 0;
}
else //没有点击定时发送
{
MessageBox.Show("发送内容不能为空!"); //错误提醒
}
if (lngstopsend_flag == 1)// && Timebutton_Click_count == 0)
{
lngstopsend_flag = 0; //发送字符串格式错误改正后,意外停止发送标志位清零
time.AutoReset = false; //定时时间间隔结束后停止
time.Enabled = false; //不再触发定时器工作
}

}
if (lngstopsend_flag == 1)
{
lngstopsend_flag = 0; //发送字符串格式错误改正后,意外停止发送标志位清零
}
}

///


/// 函数功能:定时函数
///

///
///
private void Timebutton_Click(object sender, EventArgs e)
{
if (comm.IsOpen) //根据当前串口对象,判断是否打开
{
if (txSend.Text != "")
{
if (Timebutton_Click_count++ < 1)
{
if (itimesendover == 0) //当时已在定时发送则不再执行此部分函数
{
itimesendover = 1; //停止再次定时发送标志位置1
int itimetext = 0;
string strgettext = TimeGet.Text.ToString(); //获取定时时间,由使用者手动输入
if (int.TryParse(strgettext, out itimetext) == false) //判断定时栏输入的格式是是否为整数数字
{
MessageBox.Show("您输入的时间格式不正确,请输入 >=1 的整数!");
TimeGet.Text = "1000";

//不是数字,清空定时栏
Timebutton_Click_count = 0;
itimesendover = 0;
}
else //判断定时栏输入的格式为整数数字时
{
send(); //定时发送数据

if (stoptimesend == 0 && ijinzhi_16 == 0)
{
if (TimeGet.Text == "1000")
{
time = new System.Timers.Timer(1000); //设置定时时间
time.Elapsed += new System.Timers.ElapsedEventHandler(timer1_Tick); //执行定时函数
time.AutoReset = true; //定时时间间隔结束后触发
time.Enabled = true; //再次触发定时器工作
}
else
{
double dblms = Convert.ToDouble(strgettext); //类型转换
time = new System.Timers.Timer(dblms); //设置定时时间
time.Elapsed += new System.Timers.ElapsedEventHandler(timer1_Tick); //执行定时函数
time.AutoReset = true; //定时时间间隔结束后触发
time.Enabled = true; //再次触发定时器工作
}
}
}
}//end if (itimesendover == 0)
}//end if (Timebutton_Click_count++ < 1)
else //已经点击过定时发送,如果再点即提示错误
{
MessageBox.Show("如需修改,请先停止定时发送!");
}
}//end if (txSend.Text != "")
else //未打开串口进行操作,提示错误
{
MessageBox.Show("发送内容不能为空!"); //错误提醒
}
}//end if (comm.IsOpen)
else
{

MessageBox.Show("请先打开串口!");
}
}


///


/// 函数功能:定时计数
///

///
///
private void timer1_Tick(object sender, EventArgs e)
{
Threadp(); //设置可以调用主线程变量
}

///
/// 函数功能:停止定时发送
///

///

aram>
///
private void Stopbutton_Click(object sender, EventArgs e)
{
if (itimesendover == 1 && stoptimesend == 0 && Timebutton_Click_count != 0 && ijinzhi_16 == 0)
{
time.AutoReset = false; //定时时间间隔结束后停止
time.Enabled = false; //不再触发定时器工作
}
itimesendover = 0; //停止再次定时发送标志位清零,下次定时发送时进行判断
ijinzhi_16 = 0;
Timebutton_Click_count = 0; //定时发送点击次数清零
stoptimesend = 0; //允许定时发送标志位
}


///


/// 函数功能:清空接收数据区内容
///

///
///
private void ClearRec_button_Click(object sender, EventArgs e)
{
txGet.Text = ""; //接收数据区显示为空
}

///
/// 函数功能:清空发送数据区内容
///

///
///
private void ClearSend_button_Click(object sender, EventArgs e)
{
txSend.Text = ""; //发送数据区显示为空
if (TimeGet.Text.Length != 0 && Timebutton_Click_count != 0) //定时发送时清空发送数据区
{
time.AutoReset = false; //关闭定时器
//Timebutton_Click_count = 0;
}

}

private void checkBoxHexView_CheckedChanged(object sender, EventArgs e)
{

}

private void label8_Click(object sender, EventArgs e)
{

}
///
/// 函数功能:退出退出整个程序
///

///
///
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
///
/// 函数功能:复位发送的字节数计数器并更新界面。
///

///
///
private void button2_Click(object sender, EventArgs e)
{
lngsend_count = 0; //接收和发送的字节数计数器清零。
labelSendCount.Text = "累计发送:0"; //发送字节显示为零
}

private void txGet_TextChanged(object sender, EventArgs e)
{

}
}
}

相关主题
文本预览
相关文档 最新文档