用C一步步写串口通信

上传人:痛*** 文档编号:149363382 上传时间:2022-09-07 格式:DOC 页数:25 大小:277.51KB
收藏 版权申诉 举报 下载
用C一步步写串口通信_第1页
第1页 / 共25页
用C一步步写串口通信_第2页
第2页 / 共25页
用C一步步写串口通信_第3页
第3页 / 共25页
资源描述:

《用C一步步写串口通信》由会员分享,可在线阅读,更多相关《用C一步步写串口通信(25页珍藏版)》请在装配图网上搜索。

1、 我们来看具体的实现步骤。 公司要求实现以下几个功能:1):实现两台计算机之前的串口通信,以16进制形式和字符串两种形式传送和接收。2):根据需要设置串口通信的必要参数。3):定时发送数据。4):保存串口设置。 看着好像挺复杂,其实都是纸老虎,一戳就破,前提是你敢去戳。我尽量讲的详细一些,争取说到每个知识点。 在编写程序前,需要将你要测试的COM口短接,就是收发信息都在本地计算机,短接的方式是将COM口的2、3号针接起来。COM口各针的具体作用,度娘是这么说的:COM口。记住2、3针连接一定要连接牢固,我就是因为接触不良,导致本身就不通,白白花掉了一大半天时间调试代码。下面给出主要的操作界面,

2、如下:顺便,我将所有控件对应的代码名字也附上了,相信对初学者来说,再看下面的代码会轻松很多。控件名字命名的方法是“控件名+作用”的形式,例如“打开串口”的开关按钮,其名字是btnSwitch (btn就是button的简写了)。我认为这种命名控件的方式比较好,建议大家使用,如果你有好的命名方式,希望你能告诉我!下面我们将各个功能按照从主到次的顺序逐个实现。(我分块给出代码实现,详细代码见链接:C#串口通信工具)一、获取计算机的COM口总个数,将它们列为控件cbSerial的候选项,并将第一个设为cbSerial的默认选项。这部分是在窗体加载时完成的。请看代码:(很多信息代码的注释里讲的很清楚,

3、我就不赘述了。)csharpview plaincopyprint?1. /检查是否含有串口2. stringstr=SerialPort.GetPortNames();3. if(str=null)4. 5. MessageBox.Show(本机没有串口!,Error);6. return;7. 8. 9. /添加串口项目10. foreach(stringsinSystem.IO.Ports.SerialPort.GetPortNames()11. /获取有多少个COM口12. cbSerial.Items.Add(s);13. 14. 15. /串口设置默认选择项16. cbSerial

4、.SelectedIndex=0;/设置cbSerial的默认选项二、“串口设置”这面我没代码编程,直接从窗体上按照串口信息设置就行。我们仅设置它们的默认选项,但这里我用到了ini文件,暂时不讲,我们先以下面形式设置默认。csharpview plaincopyprint?1. cbBaudRate.SelectedIndex=5;2. cbDataBits.SelectedIndex=3;3. cbStop.SelectedIndex=0;4. cbParity.SelectedIndex=0;5. radio1.Checked=true;/发送数据的“16进制”单选按钮(这里我忘了改名,现

5、在看着很不舒服!)6. rbRcvStr.Checked=true;三、打开串口在发送信息之前,我们需要根据选中的选项设置串口信息,并设置一些控件的属性,最后将串口打开。csharpview plaincopyprint?1. privatevoidbtnSwitch_Click(objectsender,EventArgse)2. 3. /sp1是全局变量。SerialPortsp1=newSerialPort();4. if(!sp1.IsOpen)5. 6. try7. 8. /设置串口号9. stringserialName=cbSerial.SelectedItem.ToString

6、();10. sp1.PortName=serialName;11. 12. /设置各“串口设置”13. stringstrBaudRate=cbBaudRate.Text;14. stringstrDateBits=cbDataBits.Text;15. stringstrStopBits=cbStop.Text;16. Int32iBaudRate=Convert.ToInt32(strBaudRate);17. Int32iDateBits=Convert.ToInt32(strDateBits);18. 19. sp1.BaudRate=iBaudRate;/波特率20. sp1.Da

7、taBits=iDateBits;/数据位21. switch(cbStop.Text)/停止位22. 23. case1:24. sp1.StopBits=StopBits.One;25. break;26. case1.5:27. sp1.StopBits=StopBits.OnePointFive;28. break;29. case2:30. sp1.StopBits=StopBits.Two;31. break;32. default:33. MessageBox.Show(Error:参数不正确!,Error);34. break;35. 36. switch(cbParity.T

8、ext)/校验位37. 38. case无:39. sp1.Parity=Parity.None;40. break;41. case奇校验:42. sp1.Parity=Parity.Odd;43. break;44. case偶校验:45. sp1.Parity=Parity.Even;46. break;47. default:48. MessageBox.Show(Error:参数不正确!,Error);49. break;50. 51. 52. if(sp1.IsOpen=true)/如果打开状态,则先关闭一下53. 54. sp1.Close();55. 56. /状态栏设置57.

9、 tsSpNum.Text=串口号:+sp1.PortName+|;58. tsBaudRate.Text=波特率:+sp1.BaudRate+|;59. tsDataBits.Text=数据位:+sp1.DataBits+|;60. tsStopBits.Text=停止位:+sp1.StopBits+|;61. tsParity.Text=校验位:+sp1.Parity+|;62. 63. /设置必要控件不可用64. cbSerial.Enabled=false;65. cbBaudRate.Enabled=false;66. cbDataBits.Enabled=false;67. cbS

10、top.Enabled=false;68. cbParity.Enabled=false;69. 70. sp1.Open();/打开串口71. btnSwitch.Text=关闭串口;72. 73. catch(System.Exceptionex)74. 75. MessageBox.Show(Error:+ex.Message,Error);76. return;77. 78. 79. else80. 81. /状态栏设置82. tsSpNum.Text=串口号:未指定|;83. tsBaudRate.Text=波特率:未指定|;84. tsDataBits.Text=数据位:未指定|;

11、85. tsStopBits.Text=停止位:未指定|;86. tsParity.Text=校验位:未指定|;87. /恢复控件功能88. /设置必要控件不可用89. cbSerial.Enabled=true;90. cbBaudRate.Enabled=true;91. cbDataBits.Enabled=true;92. cbStop.Enabled=true;93. cbParity.Enabled=true;94. 95. sp1.Close();/关闭串口96. btnSwitch.Text=打开串口;97. 98. 四、发送信息因为这里涉及到字符的转换,难点在于,在发送16进

12、制数据时,如何将文本框中的字符数据在内存中以同样的形式表现出来,例如我们输入16进制的“eb 90”显示到内存中,也就是如下形式: 或输入我们想要的任何字节,如上面的“12 34 56 78 90”.内存中的数据时16进制显示的,而我们输入的数据时字符串,我们需要将字符串转换为对应的16进制数据,然后将这个16进制数据转换为字节数据,用到的主要方法是:Convert.ToInt32 (String, Int32);Convert.ToByte (Int32);这是我想到的,如果你有好的方法,希望你能告诉我。下面看代码:csharpview plaincopyprint?1. privatevo

13、idbtnSend_Click(objectsender,EventArgse)2. 3. if(!sp1.IsOpen)/如果没打开4. 5. MessageBox.Show(请先打开串口!,Error);6. return;7. 8. 9. StringstrSend=txtSend.Text;10. if(radio1.Checked=true)/“16进制发送”按钮11. 12. /处理数字转换,目的是将输入的字符按空格、“,”等分组,以便发送数据时的方便(此处转的比较麻烦,有高见者,请指点!)13. stringsendBuf=strSend;14. stringsendnoNull

14、=sendBuf.Trim();15. stringsendNOComma=sendnoNull.Replace(,);/去掉英文逗号16. stringsendNOComma1=sendNOComma.Replace(,,);/去掉中文逗号17. stringstrSendNoComma2=sendNOComma1.Replace(0x,);/去掉0x18. strSendNoComma2.Replace(0X,);/去掉0X19. stringstrArray=strSendNoComma2.Split();20. 21. /strArray数组中会出现“”空字符的情况,影响下面的赋值操作

15、,故将byteBufferLength相应减小22. intbyteBufferLength=strArray.Length;23. for(inti=0;istrArray.Length;i+)24. 25. if(strArrayi=)26. 27. byteBufferLength-;28. 29. 30. 31. bytebyteBuffer=newbytebyteBufferLength;32. intii=0;/用于给byteBuffer赋值33. for(inti=0;istrArray.Length;i+)/对获取的字符做相加运算34. 35. 36. BytebytesOfS

16、tr=Encoding.Default.GetBytes(strArrayi);37. 38. intdecNum=0;39. if(strArrayi=)40. 41. continue;42. 43. else44. 45. decNum=Convert.ToInt32(strArrayi,16);/atrArrayi=12时,temp=1846. 47. 48. try/防止输错,使其只能输入一个字节的字符,即只能在txtSend里输入“eb90”等字符串,不能输入“1232345”等超出字节范围的数字49. 50. byteBufferii=Convert.ToByte(decNum)

17、;51. 52. catch(System.Exceptionex)53. 54. MessageBox.Show(字节越界,请逐个字节输入!,Error);55. return;56. 57. 58. ii+;59. 60. sp1.Write(byteBuffer,0,byteBuffer.Length);61. 62. else/以字符串形式发送时63. 64. sp1.WriteLine(txtSend.Text);/写入数据65. 66. 五、数据的接收亮点来了,看到这里,如果你还没吐(可能是我的代码比较拙劣!),那么下面的知识点对你也不成问题。这里需要用到 委托 的知识,我是搞C/

18、C+出身,刚碰到这个知识点还真有点不适应。为了不偏离主题,关于委托,我仅给出两条比较好的链接,需要的网友可以去加深学习:C#委托、订阅委托事件。 在窗体加载时就订阅上委托是比较好的,所以在Form1_Load中添加以下代码:csharpview plaincopyprint?1. Control.CheckForIllegalCrossThreadCalls=false;/意图见解释2. sp1.DataReceived+=newSerialDataReceivedEventHandler(sp1_DataReceived);/订阅委托 注意,因为自.net 2.0以后加强了安全机制,,不允许

19、在winform中直接跨线程(事件触发需要产生一个线程处理)访问控件的属性,第一条代码的意图是说在这个类中我们强制不检查跨线程的调用是否合法。处理这种问题的解决方案有很多,具体可参阅以下内容:解决方案。 好了,订阅委托之后,我们就可以处理接收数据的事件了。csharpview plaincopyprint?1. voidsp1_DataReceived(objectsender,SerialDataReceivedEventArgse)2. 3. if(sp1.IsOpen)/此处可能没有必要判断是否打开串口,但为了严谨性,我还是加上了4. 5. bytebyteRead=newbytesp1

20、.BytesToRead;/BytesToRead:sp1接收的字符个数6. if(rdSendStr.Checked)/发送字符串单选按钮7. 8. txtReceive.Text+=sp1.ReadLine()+rn;/注意:回车换行必须这样写,单独使用r和n都不会有效果9. sp1.DiscardInBuffer();/清空SerialPort控件的Buffer10. 11. else/发送16进制按钮12. 13. try14. 15. BytereceivedData=newBytesp1.BytesToRead;/创建接收字节数组16. sp1.Read(receivedData,

21、0,receivedData.Length);/读取数据17. sp1.DiscardInBuffer();/清空SerialPort控件的Buffer18. stringstrRcv=null;19. 20. for(inti=0;ireceivedData.Length;i+)/窗体显示21. 22. 23. strRcv+=receivedDatai.ToString(X2);/16进制显示24. 25. txtReceive.Text+=strRcv+rn;26. 27. catch(System.Exceptionex)28. 29. MessageBox.Show(ex.Messa

22、ge,出错提示);30. txtSend.Text=;31. 32. 33. 34. else35. 36. MessageBox.Show(请打开某个串口,错误提示);37. 38. 为了友好和美观,我将当前时间也显示出来,又将显示字体的颜色做了修改:csharpview plaincopyprint?1. /输出当前时间2. DateTimedt=DateTime.Now;3. txtReceive.Text+=dt.GetDateTimeFormats(f)0.ToString()+rn;4. txtReceive.SelectAll();5. txtReceive.SelectionC

23、olor=Color.Blue;/改变字体的颜色做到这里,大部分功能就已实现了,剩下的工作就是些简单的操作设置了,有保存设置、定时发送信息、控制文本框输入内容等。六、保存设置这部分相对简单,但当时我没接触过,也花了点时间,现在想想,也不过如此。保存用户设置用ini文件是个不错的选择,虽然大部分都用注册表实现,但ini文件保存还是有比较广泛的使用。.ini 文件是Initialization File的缩写,也就是初始化文件。为了不偏离正题,也不过多说明,可参考相关内容(网上资源都不错,因人而异,就不加链接了)。使用Inifile读写ini文件,这里我用到了两个主要方法:csharpview p

24、laincopyprint?1. /读出ini文件2. a:=inifile.Readstring(节点,关键字,缺省值);/string类型3. b:=inifile.Readinteger(节点,关键字,缺省值);/integer类型4. c:=inifile.Readbool(节点,关键字,缺省值);/boolean类型5. 其中缺省值为该INI文件不存在该关键字时返回的缺省值。6. /写入INI文件:7. inifile.writestring(节点,关键字,变量或字符串值);8. inifile.writeinteger(节点,关键字,变量或整型值);9. inifile.write

25、bool(节点,关键字,变量或True或False);请看代码:csharpview plaincopyprint?1. /using省写了2. namespaceINIFILE3. 4. classProfile5. 6. publicstaticvoidLoadProfile()7. 8. stringstrPath=AppDomain.CurrentDomain.BaseDirectory;9. _file=newIniFile(strPath+Cfg.ini);10. G_BAUDRATE=_file.ReadString(CONFIG,BaudRate,4800);/读数据,下同11

26、. G_DATABITS=_file.ReadString(CONFIG,DataBits,8);12. G_STOP=_file.ReadString(CONFIG,StopBits,1);13. G_PARITY=_file.ReadString(CONFIG,Parity,NONE);14. 15. 16. 17. publicstaticvoidSaveProfile()18. 19. stringstrPath=AppDomain.CurrentDomain.BaseDirectory;20. _file=newIniFile(strPath+Cfg.ini);21. _file.W

27、riteString(CONFIG,BaudRate,G_BAUDRATE);/写数据,下同22. _file.WriteString(CONFIG,DataBits,G_DATABITS);23. _file.WriteString(CONFIG,StopBits,G_STOP);24. _file.WriteString(CONFIG,G_PARITY,G_PARITY);25. 26. 27. privatestaticIniFile_file;/内置了一个对象28. 29. publicstaticstringG_BAUDRATE=1200;/给ini文件赋新值,并且影响界面下拉框的显

28、示30. publicstaticstringG_DATABITS=8;31. publicstaticstringG_STOP=1;32. publicstaticstringG_PARITY=NONE;33. 34. _file声明成了内置对象,可以方便各函数的调用。下面是“保存设置”的部分代码:csharpview plaincopyprint?1. privatevoidbtnSave_Click(objectsender,EventArgse)2. 3. 4. /设置各“串口设置”5. stringstrBaudRate=cbBaudRate.Text;6. stringstrDat

29、eBits=cbDataBits.Text;7. stringstrStopBits=cbStop.Text;8. Int32iBaudRate=Convert.ToInt32(strBaudRate);9. Int32iDateBits=Convert.ToInt32(strDateBits);10. 11. 12. Profile.G_BAUDRATE=iBaudRate+;/波特率13. Profile.G_DATABITS=iDateBits+;/数据位14. switch(cbStop.Text)/停止位15. 16. case1:17. Profile.G_STOP=1;18. b

30、reak;19. case1.5:20. Profile.G_STOP=1.5;21. break;22. /防止过多刷屏,下面省写了23. 24. 25. switch(cbParity.Text)/校验位26. 27. case无:28. Profile.G_PARITY=NONE;29. break;30. 31. 32. Profile.SaveProfile();/保存设置33. 读取ini文件主要在加载窗体时执行:INIFILE.Profile.LoadProfile();/加载所有七、控制文本输入这里倒挺简单,只是注意一点。当我们控制输入非法字符时,可通过控制e.Handed的属

31、性值实现,注意这里的Handed属性是“操作过”的含义,而非“执行此处操作”之意,Handled是过去式,看字面意思,操作过的=是;,将这个操作的状态设为已处理过,自然就不会再处理了。具体参见MSDN:Handedcsharpview plaincopyprint?1. privatevoidtxtSend_KeyPress(objectsender,KeyPressEventArgse)2. 3. if(radio1.Checked=true)4. 5. /正则匹配6. stringpatten=0-9a-fA-F|b|0x|0X|;/“b”:退格键7. Regexr=newRegex(pa

32、tten);8. Matchm=r.Match(e.KeyChar.ToString();9. 10. 11. if(m.Success)/&(txtSend.Text.LastIndexOf()!=txtSend.Text.Length-1)12. 13. e.Handled=false;14. 15. else16. 17. e.Handled=true;18. 19. /endofradio1八、定时发送信息 这边看似很简单,但也有一点需要注意,当定时器生效时,我们要间隔访问“发送”按键的内容,怎么实现?还好MS给我们提供了必要的支持,使用Button的 PerformClick可以轻松

33、做到, PerformClick参见MSDN:PerformClickcsharpview plaincopyprint?1. privatevoidtmSend_Tick(objectsender,EventArgse)2. 3. /转换时间间隔4. stringstrSecond=txtSecond.Text;5. try6. 7. intisecond=int.Parse(strSecond)*1000;/Interval以微秒为单位8. tmSend.Interval=isecond;9. if(tmSend.Enabled=true)10. 11. btnSend.PerformClick();/产生“发送”的click事件12. 13. 14. catch(System.Exceptionex)15. 16. MessageBox.Show(错误的定时输入!,Error);17. 18. 19. 注意在一些情况下不要忘了让定时器失效,如在取消“定时发送数据和“关闭串口”时等。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!