RS232串口专题
启动串口调试助手
项目运行截图
基础类封装
数据类型转换类
using System; using System.Text; namespace SerialPortHelperDemo { /// <summary> /// 16进制使用的隔离符枚举 /// </summary> public enum Enum16Hex { None,//无 Blank,//空格 OX, //OX Ox //Ox } /// <summary> /// 计算进制类助手 /// </summary> public class AlgorithmHelper { #region 十进制转十六进制 public string From10To16(int d) { string hex = ""; if (d < 16) { hex = BeginChange(d); } else { int c; int s = 0; int n = d; int temp = d; while (n >= 16) { s++; n = n / 16; } string[] m = new string[s]; int i = 0; do { c = d / 16; m[i++] = BeginChange(d % 16);//判断是否大于10,如果大于10,则转换为A~F的格式 d = c; } while (c >= 16); hex = BeginChange(d); for (int j = m.Length - 1; j >= 0; j--) { hex += m[j]; } } return hex; } //判断是否为10~15之间的数,如果是则进行转换 public string BeginChange(int d) { string hex = ""; switch (d) { case 10: hex = "A"; break; case 11: hex = "B"; break; case 12: hex = "C"; break; case 13: hex = "D"; break; case 14: hex = "E"; break; case 15: hex = "F"; break; default: hex = d.ToString(); break; } return hex; } #endregion #region 其他函数【16进制中的隔离符处理】 /// <summary> /// 把16进制隔离符转换成实际的字符串 /// </summary> /// <param name="enum16">16进制隔离符枚举</param> /// <returns></returns> private string AddSplitString(Enum16Hex enum16) { switch (enum16) { case Enum16Hex.None: return ""; case Enum16Hex.Ox: return "0x"; case Enum16Hex.OX: return "0X"; case Enum16Hex.Blank: return " "; default: return ""; } } /// <summary> /// 去掉16进制字符串中的隔离符【 如:" ", "0x", "0X"】 /// </summary> /// <param name="inString">需要转换的字符串数据</param> /// <returns></returns> private string DeleteSplitString(string inString) { string outString = string.Empty; string[] delArray = { " ", "0x", "0X" }; if (inString.Contains(" ") || inString.Contains("0x") || inString.Contains("0X"))//存在隔离符 { string[] str = inString.Split(delArray, System.StringSplitOptions.RemoveEmptyEntries);//以隔离符进行转换数组,去掉隔离符,去掉空格。 for (int i = 0; i < str.Length; i++) { outString += str[i].ToString(); } return outString; } else//不存在隔离符就直接返回 { return inString; } } #endregion #region 汉字、英文、纯16进制数、byte[]之间的各种转换方法 /// <summary> /// 字符串转换成16进制 /// </summary> /// <param name="inSting"></param> /// <param name="enum16"></param> /// <returns></returns> public string StringTo16(string inSting, Enum16Hex enum16) { string outString = ""; byte[] bytes = Encoding.Default.GetBytes(inSting); for (int i = 0; i < bytes.Length; i++) { int strInt = Convert.ToInt16(bytes[i] - '\0'); string s = strInt.ToString("X"); if (s.Length == 1) { s = "0" + s; } s = s + AddSplitString(enum16); outString += s; } return outString; } /// <summary> /// 字符串转换成byte[] /// </summary> /// <param name="inSting"></param> /// <returns></returns> public byte[] StringToBtyes(string inSting) { inSting = StringTo16(inSting, Enum16Hex.None);//把字符串转换成16进制数 return From16ToBtyes(inSting);//把16进制数转换成byte[] } /// <summary> /// 把16进制字符串转换成byte[] /// </summary> /// <param name="inSting"></param> /// <returns></returns> public byte[] From16ToBtyes(string inSting) { inSting = DeleteSplitString(inSting);//去掉16进制中的隔离符 byte[] stringByte = new byte[inSting.Length / 2]; for (int a = 0, b = 0; a < inSting.Length; a = a + 2, b++) { try { string str = inSting.Substring(a, 2); stringByte[b] = (byte)Convert.ToInt16(str, 16); } catch (Exception ex) { throw new Exception("输入的数据不是纯16进制数! 参考错误信息:" + ex.Message); } } return stringByte; } /// <summary> /// 把16进制字符串转换成英文数字和汉字混合格式 /// </summary> /// <param name="inSting">需要转换的16进制字符串</param> /// <returns></returns> public string From16ToString(string inSting) { inSting = DeleteSplitString(inSting); return Encoding.Default.GetString(From16ToBtyes(inSting)); } /// <summary> /// 把byte[]转换成String /// </summary> /// <param name="bytes">需要转换的byte[]</param> /// <param name="enum16">隔离符</param> /// <returns></returns> public string BytesToString(byte[] bytes, Enum16Hex enum16) { return From16ToString(BytesTo16(bytes, enum16)); } /// <summary> /// byte[]转换成16进制字符串 /// </summary> /// <param name="bytes">需要转换的byte[]</param> /// <param name="enum16"></param> /// <returns></returns> public string BytesTo16(byte[] bytes, Enum16Hex enum16) { string outString = ""; for (int i = 0; i < bytes.Length; i++) { if (bytes[i].ToString("X").Length < 2)//16进制数为一位时前面填充0 { outString += "0" + bytes[i].ToString("X") + AddSplitString(enum16);//转成16进制数据 } else { outString += bytes[i].ToString("X") + AddSplitString(enum16);//转成16进制数据 } } return outString; } /// <summary> /// 把byte[]直接转换成字符串,直接以2进制形式显示出来。 /// </summary> /// <param name="bytes"></param> /// <returns></returns> public string BytesTo2String(byte[] bytes, Enum16Hex enum16) { string outString = ""; for (int i = 0; i < bytes.Length; i++) { string tempString = Convert.ToString(bytes[i], 2); if (tempString.Length != 8) { string add0 = ""; for (int j = 0; j < 8 - tempString.Length; j++) { add0 += "0"; } outString += add0 + tempString + AddSplitString(enum16); } else { outString += tempString + AddSplitString(enum16); } } return outString; } /// <summary> /// 把字符串传进来,输出一个byte数组【可以把此byte数组直接发送到串口中】 /// </summary> /// <param name="inString">要转换的字符串</param> /// <param name="is16">是否已经是16进制数据,true时已经是(已经转换好的数据),false时不是(需要内部转换)</param> /// <returns>输出一个byte数组</returns> public byte[] StringToBytes(string inString, bool is16) { if (is16) { return From16ToBtyes(inString); } else { return StringToBtyes(inString); } } #endregion } }
窗体后台代码
using System; using System.Collections.Generic; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.IO.Ports; namespace SerialPortHelperDemo { public partial class FrmHelper : Form { //创建串口操作助手对象 private SerialPortHelper serialPortHelper = new SerialPortHelper(); #region 系统初始化 public FrmHelper() { InitializeComponent(); //串口基本参数初始化 this.cboBaudRrate.SelectedIndex = 5; //波特率默认9600 this.cboCheckBit.SelectedIndex = 0; //校验位默认NONE this.cboDataBit.SelectedIndex = 2; //数据位默认8 this.cboStopBit.SelectedIndex = 0; //停止位默认1 //获取当前计算机的端口 if (this.serialPortHelper.PortNames.Length == 0) { MessageBox.Show("当前计算机上没有找到可用的端口!", "警告信息"); this.btnOperatePort.Enabled = false;//禁用打开端口按钮 } else { //将端口添加到下拉框 this.cboCOMList.Items.AddRange(this.serialPortHelper.PortNames); this.cboCOMList.SelectedIndex = 0; } //串口对象委托和串口接收数据事件关联 this.serialPortHelper.SerialPortObject.DataReceived += new SerialDataReceivedEventHandler(this.SerialPort_DataReceived); } #endregion #region 串口参数设置 //波特率的设置 private void cboBaudRrate_SelectedIndexChanged(object sender, EventArgs e) { this.serialPortHelper.SerialPortObject.BaudRate = Convert.ToInt32(this.cboBaudRrate.Text); } //设置奇偶校验 private void cboCheckBit_SelectedIndexChanged(object sender, EventArgs e) { if (cboCheckBit.Text == "EVEN") serialPortHelper.SerialPortObject.Parity = System.IO.Ports.Parity.Even; else if (cboCheckBit.Text == "NONE") serialPortHelper.SerialPortObject.Parity = System.IO.Ports.Parity.None; else if (cboCheckBit.Text == "0DD") serialPortHelper.SerialPortObject.Parity = System.IO.Ports.Parity.Odd; } //设置数据位 private void cboDataBit_SelectedIndexChanged(object sender, EventArgs e) { this.serialPortHelper.SerialPortObject.DataBits = Convert.ToInt32(cboDataBit.Text); } //设置停止位 private void cboStopBit_SelectedIndexChanged(object sender, EventArgs e) { if (cboStopBit.Text == "1") serialPortHelper.SerialPortObject.StopBits = System.IO.Ports.StopBits.One; else if (cboStopBit.Text == "2") serialPortHelper.SerialPortObject.StopBits = System.IO.Ports.StopBits.Two; } #endregion #region 打开与关闭端口 private void btnOperatePort_Click(object sender, EventArgs e) { try { if (this.btnOperatePort.Text.Trim() == "打开端口") { this.serialPortHelper.OpenSerialPort(this.cboCOMList.Text.Trim(), 1); this.lblSerialPortStatus.Text = "端口已打开"; this.lblStatusShow.BackColor = Color.Green; this.btnOperatePort.Text = "关闭端口"; this.btnOperatePort.Image = this.imageList.Images[0]; } else { this.serialPortHelper.OpenSerialPort(this.cboCOMList.Text.Trim(), 0); this.lblSerialPortStatus.Text = "端口未打开"; this.lblStatusShow.BackColor = Color.Red; this.btnOperatePort.Text = "打开端口"; this.btnOperatePort.Image = this.imageList.Images[1]; } } catch (Exception ex) { MessageBox.Show("端口操作异常:" + ex.Message); } } #endregion #region 发送数据 private void btnSend_Click(object sender, EventArgs e) { if (this.txtSender.Text.Trim().Length == 0) { MessageBox.Show("发送内容不能为空!", "提示信息"); } else { //开始发送 SendData(this.txtSender.Text.Trim()); } } //这个方法独立出来,是为了后面扩展自动定时发送数据的时候调用 private void SendData(string data) { try { if (this.ckb16Send.Checked)//发送十六进制数据 { this.serialPortHelper.SendData(data, SendFormat.Hex); } else //发送字符串 { this.serialPortHelper.SendData(data, SendFormat.String); } } catch (Exception ex) { MessageBox.Show("发送数据出现错误:" + ex.Message, "错误提示!"); } } #endregion #region 串口接收数据的事件 /// <summary> /// 串口接收数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { ReceiveData(this.serialPortHelper.ReceiveData()); } catch (Exception ex) { MessageBox.Show("接收数据出现错误:" + ex.Message); } } /// <summary> /// 接收数据的具体实现过程 /// </summary> /// <param name="byteData"></param> private void ReceiveData(byte[] byteData) { string data = string.Empty; if (this.ckb16Receive.Checked)//十六机制接收 { data = this.serialPortHelper.AlgorithmHelperObject.BytesTo16(byteData, Enum16Hex.Blank); //在这里编写具体的数据处理过程。。。可以保存到数据库,或其他文件... } else { data = this.serialPortHelper.AlgorithmHelperObject.BytesToString(byteData, Enum16Hex.None); } //显示到当年文本框中 //因为接收数据的事件是一个独立显存,所有必须通过跨线程访问可视化控件的方法来完成展示 //Invoke()方法的第一个参数必须是返回值为void的委托,第二个参数是给委托对应方法传递的参数 this.txtReceiver.Invoke(new Action<string>(s => { this.txtReceiver.Text += " " + s; }), data); //屏蔽跨线程访问可视化空间引发的异常(不建议使用这种方式) // Control.CheckForIllegalCrossThreadCalls = false; } #endregion //请空数据按钮 private void btnClear_Click(object sender, EventArgs e) { this.txtReceiver.Clear(); this.txtSender.Clear(); } } }