用C一步步写串口通信_第1页
用C一步步写串口通信_第2页
用C一步步写串口通信_第3页
用C一步步写串口通信_第4页
用C一步步写串口通信_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、      我们来看具体的实现步骤。   公司要求实现以下几个功能:1):实现两台计算机之前的串口通信,以16进制形式和字符串两种形式传送和接收。2):根据需要设置串口通信的必要参数。3):定时发送数据。4):保存串口设置。      看着好像挺复杂,其实都是纸老虎,一戳就破,前提是你敢去戳。我尽量讲的详细一些,争取说到每个知识点。      在编写程序前,需要将你要测试的COM口短接,就是收发信息都在本地计算机,短接的方式是将COM口的2、3号针接起来。COM口各针的具体作

2、用,度娘是这么说的:COM口。记住2、3针连接一定要连接牢固,我就是因为接触不良,导致本身就不通,白白花掉了一大半天时间调试代码。下面给出主要的操作界面,如下:顺便,我将所有控件对应的代码名字也附上了,相信对初学者来说,再看下面的代码会轻松很多。控件名字命名的方法是“控件名+作用”的形式,例如“打开串口”的开关按钮,其名字是btnSwitch  (btn就是button的简写了)。我认为这种命名控件的方式比较好,建议大家使用,如果你有好的命名方式,希望你能告诉我!下面我们将各个功能按照从主到次的顺序逐个实现。(我分块给出代码实现,详细代码见链接:C#串口通信工具)一、获取计算机的CO

3、M口总个数,将它们列为控件cbSerial的候选项,并将第一个设为cbSerial的默认选项。这部分是在窗体加载时完成的。请看代码:(很多信息代码的注释里讲的很清楚,我就不赘述了。)csharp view plaincopyprint?1. /检查是否含有串口  2.            string str = SerialPort.GetPortNames();  3.   

4、60;        if (str = null)  4.              5.                MessageBox.Show("本机没有串口!&quo

5、t;, "Error");  6.                return;  7.              8.   9.         &

6、#160;  /添加串口项目  10.            foreach (string s in System.IO.Ports.SerialPort.GetPortNames()  11.            /获取有多少个COM口  12. 

7、60;              cbSerial.Items.Add(s);  13.              14.   15.            /串口设置默认选择项&

8、#160; 16.            cbSerial.SelectedIndex = 0;         /设置<span style="font-size:18px; "><strong>cbSerial的默认选项</strong></span>  二

9、、“串口设置”这面我没代码编程,直接从窗体上按照串口信息设置就行。我们仅设置它们的默认选项,但这里我用到了ini文件,暂时不讲,我们先以下面形式设置默认。csharp view plaincopyprint?1.  cbBaudRate.SelectedIndex = 5;  2.  cbDataBits.SelectedIndex = 3;  3.  cbStop.SelectedIndex = 0;  4.  cbPari

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

11、ate void btnSwitch_Click(object sender, EventArgs e)  2.           3. <span style="white-space:pre">  </span>/sp1是全局变量。 SerialPort sp1 = new SerialPort()

12、;  4.             if (!sp1.IsOpen)  5.               6.                

13、; try  7.                   8.                     /设置串口号  9.     

14、;                string serialName = cbSerial.SelectedItem.ToString();  10.                     

15、;sp1.PortName = serialName;  11.   12.                     /设置各“串口设置”  13.               &

16、#160;     string strBaudRate = cbBaudRate.Text;  14.                     string strDateBits = cbDataBits.Text;  15.  

17、60;                  string strStopBits = cbStop.Text;  16.                     Int32

18、 iBaudRate = Convert.ToInt32(strBaudRate);  17.                     Int32 iDateBits = Convert.ToInt32(strDateBits);  18.   19.   &

19、#160;                 sp1.BaudRate = iBaudRate;       /波特率  20.                 

20、    sp1.DataBits = iDateBits;       /数据位  21.                     switch (cbStop.Text)     

21、0;      /停止位  22.                       23.                  

22、0;      case "1":  24.                             sp1.StopBits = StopBits.One;  25.

23、                            break;  26.                   &#

24、160;     case "1.5":  27.                             sp1.StopBits = StopBits.OnePointFive; 

25、60;28.                             break;  29.                  &

26、#160;      case "2":  30.                             sp1.StopBits = StopBits.Two;  3

27、1.                             break;  32.                   

28、;      default:  33.                             MessageBox.Show("Error:参数不正确!", "Error"); 

29、; 34.                             break;  35.                 

30、60;     36.                     switch (cbParity.Text)             /校验位  37.    

31、                   38.                         case "无":  39

32、.                             sp1.Parity = Parity.None;  40.              &

33、#160;              break;  41.                         case "奇校验":  42. 

34、60;                           sp1.Parity = Parity.Odd;  43.               &

35、#160;             break;  44.                         case "偶校验":  45.  

36、60;                          sp1.Parity = Parity.Even;  46.                

37、             break;  47.                         default:  48.      &#

38、160;                      MessageBox.Show("Error:参数不正确!", "Error");  49.              

39、0;              break;  50.                       51.   52.       

40、0;             if (sp1.IsOpen = true)/如果打开状态,则先关闭一下  53.                       54.    

41、;                     sp1.Close();  55.                       56.  

42、60;                  /状态栏设置  57.                     tsSpNum.Text = "串口号:" 

43、+ sp1.PortName + "|"  58.                     tsBaudRate.Text = "波特率:" + sp1.BaudRate + "|"  59.  &#

44、160;                  tsDataBits.Text = "数据位:" + sp1.DataBits + "|"  60.              

45、;       tsStopBits.Text = "停止位:" + sp1.StopBits + "|"  61.                     tsParity.Text = 

46、"校验位:" + sp1.Parity + "|"  62.   63.                     /设置必要控件不可用  64.          

47、60;          cbSerial.Enabled = false;  65.                     cbBaudRate.Enabled = false;  66.   &

48、#160;                 cbDataBits.Enabled = false;  67.                     cbStop.Enabled 

49、= false;  68.                     cbParity.Enabled = false;  69.   70.               

50、      sp1.Open();     /打开串口  71.                     btnSwitch.Text = "关闭串口"  72.     

51、;              73.                 catch (System.Exception ex)  74.           &#

52、160;       75.                     MessageBox.Show("Error:" + ex.Message, "Error");  76.      &

53、#160;              return;  77.                   78.             

54、0; 79.             else  80.               81.                 /状态栏设置 

55、 82.                 tsSpNum.Text = "串口号:未指定|"  83.                 tsBaudRate.Text = "波特率

56、:未指定|"  84.                 tsDataBits.Text = "数据位:未指定|"  85.                 tsStopBits.Text&#

57、160;= "停止位:未指定|"  86.                 tsParity.Text = "校验位:未指定|"  87.                 

58、;/恢复控件功能  88.                 /设置必要控件不可用  89.                 cbSerial.Enabled = true;  90.  &#

59、160;              cbBaudRate.Enabled = true;  91.                 cbDataBits.Enabled = true;  92.   

60、              cbStop.Enabled = true;  93.                 cbParity.Enabled = true;  94.   95.  

61、               sp1.Close();    /关闭串口  96.                 btnSwitch.Text = "打开串口"  97

62、.               98.           四、发送信息因为这里涉及到字符的转换,难点在于,在发送16进制数据时,如何将文本框中的字符数据在内存中以同样的形式表现出来,例如我们输入16进制的“eb 90”显示到内存中,也就是如下形式:        或输入我们想要的任何字节,如上面的“12 3

63、4 56 78 90”.内存中的数据时16进制显示的,而我们输入的数据时字符串,我们需要将字符串转换为对应的16进制数据,然后将这个16进制数据转换为字节数据,用到的主要方法是:Convert.ToInt32  (String, Int32);Convert.ToByte  (Int32);这是我想到的,如果你有好的方法,希望你能告诉我。下面看代码:csharp view plaincopyprint?1.  private void btnSend_Click(object sender, EventArgs&#

64、160;e)  2.           3.             if (!sp1.IsOpen) /如果没打开  4.               5.  

65、60;              MessageBox.Show("请先打开串口!", "Error");  6.                 return;  7.    &

66、#160;          8.   9.             String strSend = txtSend.Text;  10.             if (rad

67、io1.Checked = true) /“16进制发送” 按钮   11.               12.                 /处理数字转换,目的是将输入的字符按空格、“,”等分组,以便发送数据时的方便(此处转

68、的比较麻烦,有高见者,请指点!)  13.                 string sendBuf = strSend;  14.                 string sendnoNu

69、ll = sendBuf.Trim();  15.                 string sendNOComma = sendnoNull.Replace(',', ' ');    /去掉英文逗号  16.    &#

70、160;            string sendNOComma1 = sendNOComma.Replace(',', ' '); /去掉中文逗号  17.                 string

71、 strSendNoComma2 = sendNOComma1.Replace("0x", "");   /去掉0x  18.                 strSendNoComma2.Replace("0X", "");  

72、0;/去掉0X  19.                 string strArray = strSendNoComma2.Split(' ');  20.   21. <span style="white-space:pre">    &

73、#160; </span>/strArray数组中会出现“”空字符的情况,影响下面的赋值操作,故将<span style="background-color: rgb(255, 255, 255); ">byteBufferLength相应减小</span>  22.                 i

74、nt byteBufferLength = strArray.Length;  23.                 for (int i = 0; i <<span style="background-color: rgb(255, 255, 255); 

75、;">strArray.Length</span><span style="background-color: rgb(255, 255, 255); "> i+ )</span>  24.                   25.   

76、;                  if (strArrayi="")  26.                       27.  &

77、#160;                      byteBufferLength-;  28.                      

78、60;29.                                  30.                &

79、#160;31.                 byte byteBuffer = new bytebyteBufferLength;  32.                 int ii =&#

80、160;0;<span style="white-space:pre">   </span>/用于给<span style="background-color: rgb(255, 255, 255); ">byteBuffer赋值</span>  33.             &

81、#160;   for (int i = 0; i < strArray.Length; i+)        /对获取的字符做相加运算  34.                   35.  

82、                   36.                     Byte bytesOfStr = Encoding.Default.GetBytes(str

83、Arrayi);  37.                       38.                     int decNum 

84、;= 0;  39.                     if (strArrayi = "")  40.                

85、0;      41.                            continue;  42.             

86、;          43.                     else  44.                 

87、;      45.                          decNum = Convert.ToInt32(strArrayi, 16); /atrArrayi = 12时,temp = 18&#

88、160;  46.                       47.                         

89、     48.                    try    /防止输错,使其只能输入一个字节的字符,即只能在txtSend里输入 “eb 90”等字符串,不能输入“123 2345”等超出字节范围的数字  49.     

90、;                 50.                        byteBufferii = Convert.ToByte(decNum); &

91、#160;        51.                      52.                    

92、;catch (System.Exception ex)  53.                      54.                    &#

93、160;   MessageBox.Show("字节越界,请逐个字节输入!", "Error");  55.                        return;  56.      

94、0;               57.   58.                    ii+;      59.      

95、             60.                 sp1.Write(byteBuffer, 0, byteBuffer.Length);  61.         

96、0;     62.             else        /以字符串形式发送时   63.               64.    &#

97、160;            sp1.WriteLine(txtSend.Text);    /写入数据  65.               66.           五、数

98、据的接收亮点来了,看到这里,如果你还没吐(可能是我的代码比较拙劣!),那么下面的知识点对你也不成问题。这里需要用到 委托 的知识,我是搞C/C+出身,刚碰到这个知识点还真有点不适应。为了不偏离主题,关于委托,我仅给出两条比较好的链接,需要的网友可以去加深学习:C#委托、订阅委托事件。       在窗体加载时就订阅上委托是比较好的,所以在Form1_Load中添加以下代码:csharp view plaincopyprint?1. Control.CheckForIllegalCrossThreadCalls = false

99、;    /意图见解释  2. sp1.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived); /订阅委托        注意,因为自.net 2.0以后加强了安全机制,,不允许在winform中直接跨线程(事件触发需要产生一个线程处理)访问控件的属性,第一条代码的意图是说在这个类中我们强制不检查跨线程的调用是否合法。处理这种问题的解决方案有很多,具体可参阅以下内

100、容:解决方案。      好了,订阅委托之后,我们就可以处理接收数据的事件了。csharp view plaincopyprint?1. void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)  2.          3.         

101、0;  if (sp1.IsOpen)     /此处可能没有必要判断是否打开串口,但为了严谨性,我还是加上了  4.              5.                byte byteRead&

102、#160;= new bytesp1.BytesToRead;    /BytesToRead:sp1接收的字符个数  6.                if (rdSendStr.Checked)             &#

103、160;            /'发送字符串'单选按钮  7.                  8.               

104、     txtReceive.Text += sp1.ReadLine() + "rn" /注意:回车换行必须这样写,单独使用"r"和"n"都不会有效果  9.                    sp1.DiscardInB

105、uffer();                      /清空SerialPort控件的Buffer   10.                  11.  

106、0;             else                                    

107、        /'发送16进制按钮'  12.                  13.                   

108、60;try  14.                      15.                        Byte 

109、receivedData = new Bytesp1.BytesToRead;        /创建接收字节数组  16.                        sp1.Read(receivedData, 0, 

110、;receivedData.Length);         /读取数据                         17.            

111、;            sp1.DiscardInBuffer();                                  /

112、清空SerialPort控件的Buffer  18.                        string strRcv = null;  19.   20.          

113、60;             for (int i = 0; i < receivedData.Length; i+) /窗体显示  21.                  

114、60;       22.                            23.               &

115、#160;            strRcv += receivedDatai.ToString("X2");  /16进制显示  24.                      

116、60;   25.                        txtReceive.Text += strRcv + "rn"  26.           

117、;           27.                    catch (System.Exception ex)  28.           &#

118、160;          29.                        MessageBox.Show(ex.Message, "出错提示");  30.     

119、60;                  txtSend.Text = ""  31.                      32.  

120、                33.              34.            else  35.      &#

121、160;       36.                MessageBox.Show("请打开某个串口", "错误提示");  37.              38. &#

122、160;               为了友好和美观,我将当前时间也显示出来,又将显示字体的颜色做了修改:csharp view plaincopyprint?1. <span style="white-space:pre">      </span>/输出当前时间  2.      

123、           DateTime dt = DateTime.Now;  3.                 txtReceive.Text += dt.GetDateTimeFormats('f')0.ToString() 

124、+ "rn"  4.                 txtReceive.SelectAll();  5.                 txtReceive.SelectionColor =&#

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

126、容(网上资源都不错,因人而异,就不加链接了)。使用Inifile读写ini文件,这里我用到了两个主要方法:csharp view plaincopyprint?1. /读出ini文件  2. a:=inifile.Readstring('节点','关键字',缺省值);/ string类型   3. b:=inifile.Readinteger('节点','关键字',缺省值);/ integer类型   4. c:=inif

127、ile.Readbool('节点','关键字',缺省值);/ boolean类型   5. 其中缺省值为该INI文件不存在该关键字时返回的缺省值。   6. /写入INI文件:   7. inifile.writestring('节点','关键字',变量或字符串值);   8. inifile.writeinteger('节点','关键字',变量或整型值); &

128、#160; 9. inifile.writebool('节点','关键字',变量或True或False);   请看代码:csharp view plaincopyprint?1. /using 省写了  2. namespace INIFILE  3.   4.     class Profile  5.      

129、; 6.         public static void LoadProfile()  7.           8.             string strPath = AppDomain.Cur

130、rentDomain.BaseDirectory;  9.             _file = new IniFile(strPath + "Cfg.ini");  10.             G_BAUDRATE = _

131、file.ReadString("CONFIG", "BaudRate", "4800");    /读数据,下同  11.             G_DATABITS = _file.ReadString("CONFIG", "DataBits", &qu

132、ot;8");  12.             G_STOP = _file.ReadString("CONFIG", "StopBits", "1");  13.             G_PARITY&

133、#160;= _file.ReadString("CONFIG", "Parity", "NONE");  14.            15.           16.   17.       &

134、#160; public static void SaveProfile()  18.           19.             string strPath = AppDomain.CurrentDomain.BaseDirectory;  20. 

135、0;           _file = new IniFile(strPath + "Cfg.ini");  21.             _file.WriteString("CONFIG", "BaudRate",

136、0;G_BAUDRATE);            /写数据,下同  22.             _file.WriteString("CONFIG", "DataBits", G_DATABITS);  23.    

137、60;        _file.WriteString("CONFIG", "StopBits", G_STOP);  24.             _file.WriteString("CONFIG", "G_PARITY", G_PARITY);

138、60; 25.           26.   27.         private static IniFile _file;/内置了一个对象  28.   29.         public static str

139、ing G_BAUDRATE = "1200"/给ini文件赋新值,并且影响界面下拉框的显示  30.         public static string G_DATABITS = "8"  31.         public static strin

140、g G_STOP = "1"  32.         public static string G_PARITY = "NONE"      33.       34.   _file声明成了内置对象,可以方便各函数的调用。下面是“保存设

141、置”的部分代码:csharp view plaincopyprint?1. private void btnSave_Click(object sender, EventArgs e)  2.           3.               4.   &

142、#160;         /设置各“串口设置”  5.             string strBaudRate = cbBaudRate.Text;  6.             strin

143、g strDateBits = cbDataBits.Text;  7.             string strStopBits = cbStop.Text;  8.             Int32 iBaudRate =

144、0;Convert.ToInt32(strBaudRate);  9.             Int32 iDateBits = Convert.ToInt32(strDateBits);  10.   11.   12.             

145、Profile.G_BAUDRATE = iBaudRate+""       /波特率  13.             Profile.G_DATABITS = iDateBits+""       /数据位  14

146、.             switch (cbStop.Text)            /停止位  15.               16.    

147、60;            case "1":  17.                     Profile.G_STOP = "1"  18.  

148、60;                  break;  19.                 case "1.5":  20.      

149、;               Profile.G_STOP = "1.5"  21.                     break;  22.  

150、60;             /防止过多刷屏,下面省写了  23.           24.               25.       &#

151、160;     switch (cbParity.Text)             /校验位  26.               27.          

152、;       case "无":  28.                     Profile.G_PARITY = "NONE"  29.                     break;  30.                   31.              &#

温馨提示

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

评论

0/150

提交评论