当前位置:文档之家› 用C#一步步写串口通信分析解析

用C#一步步写串口通信分析解析

我们来看具体的实现步骤。

公司要求实现以下几个功能:1):实现两台计算机之前的串口通信,以16进制形式和字符串两种形式传送和接收。

2):根据需要设置串口通信的必要参数。

3):定时发送数据。

4):保存串口设置。

看着好像挺复杂,其实都是纸老虎,一戳就破,前提是你敢去戳。

我尽量讲的详细一些,争取说到每个知识点。

在编写程序前,需要将你要测试的COM口短接,就是收发信息都在本地计算机,短接的方式是将COM口的2、3号针接起来。

COM 口各针的具体作用,度娘是这么说的:COM口。

记住2、3针连接一定要连接牢固,我就是因为接触不良,导致本身就不通,白白花掉了一大半天时间调试代码。

下面给出主要的操作界面,如下:顺便,我将所有控件对应的代码名字也附上了,相信对初学者来说,再看下面的代码会轻松很多。

控件名字命名的方法是“控件名+作用”的形式,例如“打开串口”的开关按钮,其名字是btnSwitch (btn就是button的简写了)。

我认为这种命名控件的方式比较好,建议大家使用,如果你有好的命名方式,希望你能告诉我!下面我们将各个功能按照从主到次的顺序逐个实现。

(我分块给出代码实现,详细代码见链接:《C#串口通信工具》)一、获取计算机的COM口总个数,将它们列为控件cbSerial的候选项,并将第一个设为cbSerial的默认选项。

这部分是在窗体加载时完成的。

请看代码:(很多信息代码的注释里讲的很清楚,我就不赘述了。

)[csharp]view plaincopyprint?1.//检查是否含有串口2. string[] str = SerialPort.GetPortNames();3. if (str == null)4. {5. MessageBox.Show("本机没有串口!", "Error");6. return;7. }8.9. //添加串口项目10. foreach (string s in System.IO.Ports.SerialPort.GetPortNames())11. {//获取有多少个COM口12. cbSerial.Items.Add(s);13. }14.15. //串口设置默认选择项16. cbSerial.SelectedIndex = 0; //设置<span style="font-size:18px; "><strong>cbSerial的默认选项</strong></span>二、“串口设置”这面我没代码编程,直接从窗体上按照串口信息设置就行。

我们仅设置它们的默认选项,但这里我用到了ini文件,暂时不讲,我们先以下面形式设置默认。

[csharp]view plaincopyprint?1. cbBaudRate.SelectedIndex = 5;2. cbDataBits.SelectedIndex = 3;3. cbStop.SelectedIndex = 0;4. cbParity.SelectedIndex = 0;5. radio1.Checked = true; //发送数据的“16进制”单选按钮(这里我忘了改名,现在看着很不舒服!)6. rbRcvStr.Checked = true;三、打开串口在发送信息之前,我们需要根据选中的选项设置串口信息,并设置一些控件的属性,最后将串口打开。

[csharp]view plaincopyprint?1. private void btnSwitch_Click(object sender, EventArgs e)2. {3.<span style="white-space:pre"> </span>//sp1是全局变量。

SerialPort sp1 = new SerialPort();4. if (!sp1.IsOpen)5. {6. try7. {8. //设置串口号9. string serialName = cbSerial.SelectedItem.T oString();10. sp1.PortName = serialName;11.12. //设置各“串口设置”13. string strBaudRate = cbBaudRate.T ext;14. string strDateBits = cbDataBits.T ext;15. string strStopBits = cbStop.Text;16. Int32 iBaudRate = Convert.ToInt32(strBaudRate);17. Int32 iDateBits = Convert.ToInt32(strDateBits);18.19. sp1.BaudRate = iBaudRate; //波特率20. sp1.DataBits = iDateBits; //数据位21. switch (cbStop.Text) //停止位22. {23. case "1":24. sp1.StopBits = StopBits.One;25. break;26. case "1.5":27. sp1.StopBits = StopBits.OnePointFive;28. break;29. case "2":30. sp1.StopBits = StopBits.Two;31. break;32. default:33. MessageBox.Show("Error:参数不正确!", "Error");34. break;35. }36. switch (cbParity.T 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. tsSpNum.T ext = "串口号:" + sp1.PortName + "|";58. tsBaudRate.Text = "波特率:" + sp1.BaudRate + "|";59. tsDataBits.Text = "数据位:" + sp1.DataBits + "|";60. tsStopBits.Text = "停止位:" + sp1.StopBits + "|";61. tsParity.T ext = "校验位:" + sp1.Parity + "|";62.63. //设置必要控件不可用64. cbSerial.Enabled = false;65. cbBaudRate.Enabled = false;66. cbDataBits.Enabled = false;67. cbStop.Enabled = false;68. cbParity.Enabled = false;69.70. sp1.Open(); //打开串口71. btnSwitch.T ext = "关闭串口";72. }73. catch (System.Exception ex)74. {75. MessageBox.Show("Error:" + ex.Message, "Error");76. return;77. }78. }79. else80. {81. //状态栏设置82. tsSpNum.T ext = "串口号:未指定|";83. tsBaudRate.T ext = "波特率:未指定|";84. tsDataBits.T ext = "数据位:未指定|";85. tsStopBits.T ext = "停止位:未指定|";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进制数据时,如何将文本框中的字符数据在内存中以同样的形式表现出来,例如我们输入16进制的“eb 90”显示到内存中,也就是如下形式:或输入我们想要的任何字节,如上面的“12 34 56 78 90”.内存中的数据时16进制显示的,而我们输入的数据时字符串,我们需要将字符串转换为对应的16进制数据,然后将这个16进制数据转换为字节数据,用到的主要方法是:Convert.ToInt32 (String, Int32);Convert.ToByte (Int32);这是我想到的,如果你有好的方法,希望你能告诉我。

下面看代码:[csharp]view plaincopyprint?1. private void btnSend_Click(object sender, EventArgs e)2. {3. if (!sp1.IsOpen) //如果没打开4. {5. MessageBox.Show("请先打开串口!", "Error");6. return;7. }8.9. String strSend = txtSend.T ext;10. if (radio1.Checked == true) //“16进制发送”按钮11. {12. //处理数字转换,目的是将输入的字符按空格、“,”等分组,以便发送数据时的方便(此处转的比较麻烦,有高见者,请指点!)13. string sendBuf = strSend;14. string sendnoNull = sendBuf.Trim();15. string sendNOComma = sendnoNull.Replace(',', ' '); //去掉英文逗号16. string sendNOComma1 = sendNOComma.Replace(',', ' '); //去掉中文逗号17. string strSendNoComma2 = sendNOComma1.Replace("0x", "");//去掉0x18. strSendNoComma2.Replace("0X", ""); //去掉0X19. string[] strArray = strSendNoComma2.Split(' ');20.21.<span style="white-space:pre"> </span>//strArray数组中会出现“”空字符的情况,影响下面的赋值操作,故将<span style="background-color: rgb(255, 255, 255); ">byteBufferLength相应减小</span>22. int byteBufferLength = strArray.Length;23. for (int i = 0; i <<span style="background-color: rgb(255, 255, 255); ">strArray.Length</span><span style="background-color: rgb(255, 255, 255); ">; i++ )</span>24. {25. if (strArray[i]=="")26. {27. byteBufferLength--;28. }29. }30.31. byte[] byteBuffer = new byte[byteBufferLength];32. int ii = 0;<span style="white-space:pre"> </span>//用于给<span style="background-color: rgb(255, 255, 255); ">byteBuffer赋值</span>33. for (int i = 0; i < strArray.Length; i++) //对获取的字符做相加运算34. {35.36. Byte[] bytesOfStr = Encoding.Default.GetBytes(strArray[i]);37.38. int decNum = 0;39. if (strArray[i] == "")40. {41. continue;42. }43. else44. {45. decNum = Convert.ToInt32(strArray[i], 16); //atrArray[i] ==12时,temp == 1846. }47.48. try //防止输错,使其只能输入一个字节的字符,即只能在txtSend里输入“eb 90”等字符串,不能输入“123 2345”等超出字节范围的数字49. {50. byteBuffer[ii] = Convert.ToByte(decNum);51. }52. catch (System.Exception ex)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.T ext); //写入数据65. }66. }五、数据的接收亮点来了,看到这里,如果你还没吐(可能是我的代码比较拙劣!),那么下面的知识点对你也不成问题。

相关主题