c#上位机串口通信助手源代码详解.docx
精心整理C#上位机串口通信助手源代码实例详解一、功能1软件翻开时,自动检测有效COM端口2软件翻开时,自动复原到上次关闭时的状态3不必关闭串口,即可直接进行更改初始化设置内容(串口号、波特率、数据位、停止位、校验位), 可按更改后的信息自动将串口重新翻开4可统计接收字节和发送字节的个数5接收数据可按16进制数据和非16进制数据进行整体转换6可将接收到数据进行保存7可设置自动发送,发送时间可进行实时更改8可按字符串、16进制字节、文件方式进行发送,字符串和16进制字节可分别进行存储,内容互不干 扰9按16进制发送时,可自动校验格式,不会输错10可清空发送或接收区域的数据二、使用工具VisualStudio2015三、程序详解1界面创立用winform创立如图1所示界面,控件名字分别为: 端口号:cbxCOMPort 波特率:cbxBaudRate数据位:cbxDataBits 停止位:cbxStopBits校验位:Iabel5翻开串口按钮:btnOpenCom发送(byte ) : tbSendCount 接收(byte ) : tbReceivedCount 清空计数按钮:btnClearCount按16进制显示:cbl6Display 接收区清空内容按钮:btnClearReceived保存数据按钮:btnSaveFile 接收数据框:tbReceivedData发送数据框:tbSendData 自动发送:cbAutomaticSend 间隔时间:tbSpaceTime按16进制发送:cbl6Send发送区清空内容按钮:btnClearSend 读入文件按钮:btnReadFile发送按钮:btnSend2创立一个方法类按Ctrl+shift+A快捷键创立一个类,名字叫Methods ,代码为:usingSystem;usingSystem. Collections; using usingusingSystem. Linq;usingSystem. Text;usingnamespace 串 口助手 sddif (e. KeyChar!='b') tbSendData. Text+=;) ) e.Handled=false;) else e.Handled=true;) ) else ( e.Handled=false;) )点击清空发送内容privatevoidbtnClearSend Click(objectsender, IwentArgse) ( " tbSendData. Text="; if (cbl6Send. Checked) tbSendDatal6二; elsetbSendDataStr二; )点击清空计数器数据privatevoidbtnClearCount Click(objectsender, EventArgse) (tbReceivedCount. Text二; tbSendCount. Text二; )点击是否设置自动发送privatevoidcbAutomaticSend CheckedChanged(objectsender, KventArgse) (if (cbAutomaticSend. Checked) (timer2.Enabled=true;timer2. Interval=Convert. Tolnt32 (tbSpaceTime.Text);) else ( timer2. Enabled=false;) )自动发送时间文本框键盘按键检测privatevoidtbSpaceTime KeyPress(objectsender, KeyPressEvontArgse) ( "正那么匹配stringpattern=0-9|b;Matchm=Regex if (m. Success) ( timer2. Interval=Convert. Tolnt32(tbSpaceTime. Text); e.Handled=false;else精心整理(e.Handled=true;) )串口显示状态privatevoidtimer2 Tick(objectsender, EventArgse) ( -if (sp. IsOpen)DataSend ();) else ( timer2. Enabled=false; cbAutomaticSend. Checked=false;MessageBox. Show(串口未翻开!,错误提示); return;)if ) 检测发送数据是否为空 (timer2. Enabled=false;cbAutomaticSend. Checked=false;MessageBox. Show (请输入要发送的数据!,错误提示); return;) )关闭窗口时出发的事件privatevoidForml FormClosed(objectsender, FormClosedEventArgse) ( try (using(StreamWritersw=newStreamWriter(path, false) (sw. WriteLine (z/cbxCOMPort=,+cbxCOMPort. Text);sw. WriteLine (zzcbxBaudRate=,z+cbxBaudRate. Text);sw. WriteLine (zzcbxDataBits=z/+cbxDataBits. Text);sw.WriteLine ("cbxStopBits=+cbxStopBits. Text);sw. WriteLine (zzcbxParity=/z+cbxParity. Text);sw. WriteLine (zztbSpaceTime=/z+tbSpaceTime. Text);sw. WriteLine (zztbSendDataStr=,z+tbSendDataStr);sw. WriteLine (,ztbSendDatal6=,+tbSendDatal6);sp. Close ();) ) catch(Exceptionex)发送文本框按键抬起时出发的事件privatevoidtbSendData KeyUp(objectsender, KeyEventArgse) ( "if(cbl6Send. Checked)()else tbSendDataStr=tbSendData. Text;点击读入文件按钮privatevoidbtnReadFile_Click(objectsender, liventArgse) ( "openFileDialogl. Fil ter 二所有文件(*. *) | *. *;文件筛选器的设定openFileDialogl. Filterlndex=l;openFileDialogl. Title=选择文件;openFileDialogl. FileName=";openFileDialogl. ShowHelp=true;if (openFileDialogl. ShowDialog()=DialogResult. OK) using (Fi leStreamf s=newl?i leStream (openFileDialogl. Fil eName, Fil eMode. Open) (bytebufferByte=newbytefs. Length;fs. Read (bufferByte, 0, Convert. Tolnt32 (fs. Length);sp.Write(bufferByte, 0, bufferByte. Length);tbSendCount. Text= (Convert. Tolnt32 (tbSendCount. Text) +bufferByte. Length). ToStringO ;点击保存数据按钮privatevoidbtnSaveFile Click(objectsender, IwentArgse) ( "saveFileDialogl. Fil ter 二所有文件(札 *) | *. *"if (saveFileDialogl. ShowDialog()=DialogResult. OK) (stringfName=saveFileDialogl. FileName;using(FileStreamfs=File. Open(fName, FileMode. Append) (fs.Write(receivedDatas. ToArray(), 0, receivedDatas. Count);)需要源代码或有疑问的C#爰好者们,欢迎加入C#技术交流群(), 附加信息为我以下载此文档,进群后找群主索要源代码或进行技 术交流。classMethods获取有效的COM 口publicstaticstringActivePorts() (ArrayLi stactivePorts=newArrayLi st();foreach(stringpnameinSeri al Port. GetPortNames() (activePorts. Add(Convert. Tolnt32(pname. Substring(3);)activePorts. Sort ();stringmystr=newstringactivePorts. Count;inti=0;foreach(intnuminactivePorts)(mystri+=C0M+num. ToStringO;)returnmystr;)16进制字符串转换为byte字符数组publicstaticByte_16strToHex(stringstrValues)(stringhexValuesSplit=strValues. Split ('');hexValues=newBytehexValuesSplit. Length;Console. WriteLine(hexValuesSplit. Length);for(inti=0;i<hexValuesSplit. Length;i+)(hexValuesi=Convert. ToByte(hexValuesSpliti, 16);)returnhexValues;)byte数组以16进制形式转字符串publicstaticstringByteTo16Str(bytebytes) (stringrecData=null; 创立接收数据的字符串foreach(byteoutByteinbytes) 将字节数组以16进制形式遍历到一个字符串内 (recData+=outByte. ToString (X2)+“;)returnrecData;)/16进制字符串转换字符串publicstaticstring_16strToStr(string_16str) ( " 一stringoutStr=null;byte 口 streamByte=_16strToIIex (_16str);outStr=Encoding. Default. GetString(streamByte);returnoutStr;)2Forml. cs的代码为:usingSystem;usingusingSystem.ComponentModel;usingSystem. Data;usingSystem. Drawing;using精心整理usingSystem. Linq; usingSystem. Text; using using usingusingSystem. 10;usingSystem. Collections; namespace 串 口助手 sdd publicpartialclassForml:Form (声明变量SerialPortsp=newSerialPort();bool i sSetProperty=false; 串 口属性设置标志位 privateenumPortState声明接口显示状态,枚举型 (翻开,关闭 )stringpath=AppI)oinain. CurrentDomain. Basel)irectory+Z,confing. ini"声明配置文件路径 stringtbSendDataStr=,/,; 发送窗口字符串存储stringtbSendI)atal6 二;发送窗口 16 进制存储List<byte>receivedDatas=newIJ st<byte> () ;/接收数据泛型数组 接收串口数据privatevoidsp DataReceived(objectsender, SerialDataReceivedEventArgse) ( "byteReceivedData=newbyte sp. BytesToRead; 创立接收字节数组sp. Read (ReceivedData, 0, ReceivedData. Length); 读取所接收到的数据 receivedDatas. AddRange(ReceivedData);tbReceivedCount. Text=(Convert. Tolnt32(tbReceivedCount. Text)+ReceivedData. Length). ToString(); if(cbl6Display. Checked)tbReceivedData. Text=Methods, ByteTol6Str(receivedDatas. ToArray(); elsetbReceivedData. Text=Encoding. Default. GetString(receivedDatas. ToArray(); sp. DiscardlnBuffer ();丢弃接收缓冲区数据 )发送串口数据 privatevoidDataSend() ( try (if (cb!6Send. Checked) (bytehexBytes=Methods. _16strToHex(tbSendDatal6);sp. Write (hexBytes, 0, hexBytes. Length);tbSendCount. Text= (Convert. Tolnt32 (tbSendCount. Text)+hexBytes. Length). ToString(); ) else (sp.WriteLine(tbSendDataStr);tbSendCount. Text= (Convert.Tolnt32 (tbSendCount. Text)+tbSendDataStr. Length). ToString();catch (I'xceptionex)MessageBox return;) )设置串口属性privatevoidSetPortProperty() (设置串口名sp. BaudRate=Convert设置波特率switch 设置停止位 (casel:sp.StopBits=StopBits. One;break;case,zl. 5: sp. StopBits=StopBits. OnePointFive; break;case2:sp.StopBits=StopBits. Two;break;default:sp. StopBits=StopBits. None;break; )sp. DataBits=Convert设置数据位swi t ch 设置奇偶校验位 (case无:sp. Parity=Pari ty. None; break;case奇校验:sp. Parity=Parity. Odd;break;case”偶校验:sp. Parity=Parity. Even;break;default:sp. Parity=Parity. None;break; )sp. ReadTimeout=5000; 设置超时时间为5sControl. CheckFor11legalCrossThreadCal1s=false; 这个类中我们不检查跨线程的调用是否合法(因为.net2. 0以后加强 了平安机制不允许在winform中直接跨线程访问控件的属性)定义DataReceived事件的委托,当串口收到数据后出发事件sp. DataReceived+=newSerialDataReceivedEventHandler (sp DataReceived);) "设置端口显示状态pri vatevoi dl)i spl ayPortState (lrtStat eportState) (toolStripStatusLabel 1. Text二cbxCOMPort. Text+端口处于+portState+状态z,+cbxBaudRate. Text+zz/,+cbxDataBits. Text+"+cbxStopBits. Text+cbxParity. Text; )重新翻开串口privatevoidAgainOpenPort() (if (sp. IsOpen) (try ( sp. Close ();SetPortProperty(); isSetProperty=true; sp. Open ();)catch(Exception) (isSetProperty=false;btnOpenCom. Text二翻开串口;DisplayPortState (PortState.关闭);MessageBox. Show(串口无效或已被占用!,错误提示);精心整理return;)DisplayPortState (PortState.翻开);)else(DisplayPortState (PortState.关闭);)publicForml()(InitializeComponent();)软件启动时加载事件privatevoidForml Load(objectsender,EventArgse) ( .Sregi on加载配置文件I lash tab 1 eht=newl lash tab 1 e ();if (File. Exists(path)(try(stringmyline=zz,/;stringstr=newstring2;using (StreamReadersr=newStreamReader(path)(myline=sr. ReadLine();while(myline!=null)(str=myline. Split ('=,);ht. Add(str0, str1);myline=sr. ReadLine();)catch(Exceptionex)(MessageBox)#endregion#regi on设置窗口为固定大小且不可最大化this.MaximumSize=this. Size;this.MinimumSize=this. Size;this. MaximizeBox=false;#endregion去egion列出常用的波特率1200);2400);4800);9600);19200);38400);43000);56000);57600);115200);if(ht. ContainsKey("cbxBaudRate")/zcbxBaudRatez/. ToString();elsecbxBaudRate. Selectedlndex=3;cbxBaudRate. DropDownStyle=ComboBoxStyle. DropDownList;#endregion#region列出停止位1);L5);2);if(ht. ContainsKey("cbxStopBits")“cbxStopBits".ToStringO);elsecbxStopBits. SelectedIndex=O;cbxStopBits. DropDownSty1e=ComboBoxSty1e. DropDownList;Scndrcgion#region列出数据位8);7);6);5);if(ht. ContainsKey("cbxDataBits)“cbxDataBits"1.ToString();elsecbxDataBits. SelectedIndex=O;cbxDataBits. I)ropDownStyle=ComboBoxStyIe. DropDownList;Sendregion#region列出奇偶校验位无);奇校验);偶校验);if (ht. ContainsKey("cbxParity)cbxParity. ToStringO);elsecbxParity. SelectedIndex=O;cbxParity.DropDownStyle=ComboBoxStyle. DropDownList;#endregion#regionC0M 口重新加载清除当前串口号中的所有串口名称Methods. ActivePorts ();if (ht. ContainsKey (z/cbxCOMPort,zcbxCOMPortz,. ToString () /zcbxCOMPortz/. ToString ();elsecbxCOMPort. SelectedIndex=O;cbxCOMPort. DropDownStyle=ComboBoxStyle. DropDownList;#endregion# r eg i on初始化计数器tbSendCount. Text二0;tbSendCount. ReadOnly=true;tbReceivedCount. Text二0;tbReceivedCount. Readonly=true;Sendregion# r eg ion初始化当前时间toolstripStatusLabel3. Text=I)ateTime. Now. ToStringO ;#endregionr eg i on初始化串口状态toolStripStatusLabell. ForeColor=Color. Blue;精心整理if(!isSetProperty) 串口未设置那么设置串口属性 SetPortProperty();isSetProperty=true;) try ( sp. Open ();btnOpenCom. Text二关闭串口;DisplayPortState (PortState.翻开);)catch(Exception) (串口翻开失败后,串口属性设置标志位设为falseisSetProperty=false;MessageBox. Show(串口无效或已被占用!,错误提示);)#endregion#region初始化间隔时间if(ht. ContainsKey(tbSpaceTime)tbSpaceTime. Text=ht tbSpaceTime ToStringO ;elsetbSpaceTime. Text=1000;Sendregion#r eg i on初始化按16进制显示状态if (ht. ContainsKey (cbl6Display")&&ht cbl6Display". ToString0 =,True,/) cbl6Display. Checked=true;elsecbl6Display. Checked=false;Sendregion#region初始化按16进制发送状态if (ht. ContainsKey (cbl6Send)&&ht cbl6Send. ToStringO二二True") cbl6Send. Checked=true;elsecbl6Send. Checked=false;#endregion#region初始化发送区文本if (ht. ContainsKey (tbSendDatal6)&&ht. ContainsKey ("tbSendDataStr") (tbSendDatal6=ht z/tbSendDatal6,J. ToStringO ;tbSendDataStr=htz,tbSendDataStr,l. ToStringO ;if(cbl6Send. Checked)tbScndData. Text=httbScndDatal61. ToStringO ; elsetbSendData. Text=httbScndDataStr ToStringO ; )SendregiontbSendData. Focus ();)显示当前时间privatevoidtimeri Tick (objectsender, EventArgse) (toolStripStatusLabel3. Text=I)atcTimc. Now. ToStringO ;)点击翻开串口按钮privatevoidbtnOpenCom Click(objectsender, EventArgse)if (!sp. IsOpen)串口没有翻开时 (if(!i sSetProper ty) 串口未设置那么设置串口属性 (SetPortProperty();i sSetProperty=true;) try ( sp. Open ();btnOpenCom. Text二关闭串口;DisplayPortState (PortState.翻开);)catch(Exception) (串口翻开失败后,串口属性设置标志位设为false isSetProperty=false;MessageBox. Show(串口无效或已被占用!,错误提示); ) )else 串口已经翻开( try(sp. Close ();isSetProperty=false;btnOpenCom. Text翻开串口;DisplayPortState (PortState.关闭);)catch(Exception) (MessageBox. Show(关闭串口时发生错误,错误提示);) )发送串口数据privatevoidbtnSend Click(objectsender, EventArgse) (if ) 检测发送数据是否为空 (MessageBox. Show (请输入要发送的数据!,错误提示); return;)if(sp. IsOpen)(DataSend ();) else (MessageBox. Show(串口未翻开!,错误提示);) )点击端口号选择下拉框按钮privatevoidcbxCOMPort SelectedlndexChanged (objectsender, EventArgse)精心整理AgainOpenPort();)点击波特率选择下拉框按钮privatevoidcbxBaudRate SelectedlndexChanged(objectsender, IwentArgse) (AgainOpenPort();)点击数据位选择下拉框按钮privatevoidcbxDataBits SelectedlndexChanged(objectsender, IsvcntArgse) ( "AgainOpenPort();)点击停止位选择下拉框按钮privatevoidcbxStopBits SelectedlndexChanged(objectsender, EventArgse) ( "AgainOpenPort();)点击校验位选择下拉框按钮privatevoidcbxParity SelectedlndexChanged(objectsender, EventArgse)(AgainOpenPort();)点击数据接收区清空按钮privatevoidbtnClearReceived Click (objectsender, EventArgse) (receivedDatas. Clear ();tbReceivedData. Text二;)点击是否按16进制显示接收数据privatevoideb16Display_CheckedChanged(objectsender, EventArgse) ( "if (cbl6Display. Checked)tbReceivedData. Textilethods. ByteTol6Str (receivedDatas. ToArray ();elsetbReceivedData. Text二Encoding-Default. GetString(receivedDatas.ToArray ();)点击是否按16进制发送数据privatevoideb16Send_CheckedChanged(objectsender,EventArgse) ( "if (cbl6Send. Checked) (tbSendData. Text=tbSendDatal6;)else(tbSendData. Text=tbSendDataStr;)发送文本框键盘按键检测privatevoidtbSendData KeyPress(objectsender, KeyPressEventArgse) ( "if(cbl6Send. Checked) (正那么匹配stringpattern=/,0-9a-fA-F I b ;b:退格键if (m. Success)