加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

VB.NET串口通信例子

发布时间:2020-12-17 00:15:31 所属栏目:大数据 来源:网络整理
导读:尊重原创:http://www.jb51.cc/article/p-pzqjyvzp-bkr.html 这是我3年前的一个例子,最近翻出来回忆一下。 串口是计算机上一种非常通用设备通信的协议。大多数计算机包含两个基于RS232的串口,现在配电脑好像只有一个。串口同时也是仪器仪表设备通用的通信

尊重原创:http://www.52php.cn/article/p-pzqjyvzp-bkr.html


这是我3年前的一个例子,最近翻出来回忆一下。

串口是计算机上一种非常通用设备通信的协议。大多数计算机包含两个基于RS232的串口,现在配电脑好像只有一个。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据。串口通信在工控领域用途很广。

串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。

典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配:
a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。
b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。
c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。

串口通信还有一个参数是单工、半双工和双工。

如果在通信过程的任意时刻,信息只能由一方A传到另一方B,则称为单工。

如果在任意时刻,信息既可由A传到B,又能由B传A,但只能由一个方向上的传输存在,称为半双工传输。

如果在任意时刻,线路上存在A到B和B到A的双向信号传输,则称为全双工。

电话线就是二线全双工信道。 由于采用了回波抵消技术,双向的传输信号不致混淆不清。双工信道有时也将收、发信道分开,采用分离的线路或频带传输相反方向的信号,如回线传输。

在调试时可以用串口助手和windows的超级终端,不要带电插拔串口,容易烧毁。

在VB.NET中提供了IO.Ports类,是我们的编程变得很简单,下面是我的例子:

Form1.vb

[vb] view plain copy
  1. ?ImportsSystem.IO.Ports
  2. PublicClassForm1
  3. DimWithEventsRS232AsSerialPort
  4. DelegateSubSetTextCallback(ByValInputStringAsString)'声明一个代理
  5. PrivateSubForm1_Load(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.Load
  6. ForEachspAsStringInSerialPort.GetPortNames()
  7. cmbCom.Items.Add(sp)
  8. Next
  9. cmbCom.Sorted=True
  10. cmbCom.SelectedIndex=0
  11. EndSub
  12. PrivateSubbtnStart_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesbtnStart.Click
  13. DimmBaudRateAsInteger
  14. DimmParityAsIO.Ports.Parity
  15. DimmDataBitAsInteger
  16. DimmStopBitAsIO.Ports.StopBits
  17. DimmPortNameAsString
  18. mPortName=cmbCom.SelectedItem.ToString
  19. mBaudRate=9600
  20. mParity=Parity.None
  21. mDataBit=8
  22. mStopBit=StopBits.One
  23. RS232=NewIO.Ports.SerialPort(mPortName,mBaudRate,mParity,mDataBit,mStopBit)
  24. IfNotRS232.IsOpenThen
  25. RS232.Open()
  26. btnSend.Enabled=True
  27. RS232.ReceivedBytesThreshold=1'设置引发事件的门限值
  28. Else
  29. MsgBox("通讯端口打开错误!",MsgBoxStyle.Critical)
  30. EndIf
  31. EndSub
  32. PrivateSubRS232_DataReceived(ByValsenderAsObject,ByValeAsSystem.IO.Ports.SerialDataReceivedEventArgs)HandlesRS232.DataReceived
  33. DimInByte()AsByte,ReadCountAsInteger,strReadAsString
  34. IfRS232.BytesToRead<=0ThenExitSub
  35. ReDimInByte(RS232.BytesToRead-1)
  36. ReadCount=RS232.Read(InByte,RS232.BytesToRead)
  37. strRead=""
  38. IfReadCount=0Then
  39. ExitSub
  40. Else
  41. ForEachbDataAsByteInInByte
  42. strRead+=bData.ToString&vbCrLf'若有数据则加到接收文本框
  43. DisplayText(strRead)
  44. Next
  45. EndIf
  46. EndSub
  47. '*************************************************
  48. '代理子程序
  49. '处理上述通信端口的接收事件
  50. '由于欲将数据显示到接收文本框中,因此必须检查
  51. '是否由另外得Thread所调用的,若是,则必须先
  52. '建立代理对象
  53. 'Invoke用于在拥有控件基础窗口控制代码的线程上
  54. '运行代理
  55. '*************************************************
  56. PrivateSubDisplayText(ByValcomDataAsString)
  57. '如果调用txtReceive的另外的线程,返回true
  58. IfMe.txtReceive.InvokeRequiredThen
  59. '利用代理类型建立对象,并指定代理的函数
  60. DimdAsNewSetTextCallback(AddressOfDisplayText)
  61. Me.Invoke(d,NewObject(){comData})'以指定的自变量列表调用函数
  62. Else'相同的线程
  63. 'showstring(comData)'将收到的数据填入接收文本框中
  64. Me.txtReceive.Text+=comData
  65. EndIf
  66. EndSub
  67. PrivateSubbtnClose_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesbtnClose.Click
  68. IfRS232IsNothingOrElseNotRS232.IsOpenThen'尚未打开
  69. MsgBox("通讯端口尚未打开",MsgBoxStyle.CriticalOrMsgBoxStyle.OkCancel)
  70. Else
  71. RS232.Close()
  72. btnStart.Enabled=False
  73. btnClose.Enabled=False
  74. RS232=Nothing
  75. EndIf
  76. EndSub
  77. PrivateSubbtnEnd_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesbtnEnd.Click
  78. IfNotRS232IsNothingThen
  79. IfRS232.IsOpenThenRS232.Close()
  80. EndIf
  81. End
  82. EndSub
  83. PrivateSubbtnSend_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesbtnSend.Click
  84. DimbDataOut(0)AsByte
  85. Try
  86. bDataOut(0)=CType(Me.txtSend.Text,Byte)'将类型转换为字节
  87. RS232.Write(bDataOut,1)
  88. CatchexAsException
  89. MessageBox.Show("输入数值错误:"+ex.ToString,"错误通知:",MessageBoxButtons.OK,MessageBoxIcon.Exclamation)
  90. EndTry
  91. EndSub
  92. PrivateSubcmbCom_KeyPress(ByValsenderAsObject,ByValeAsSystem.Windows.Forms.KeyPressEventArgs)HandlescmbCom.KeyPress
  93. e.KeyChar=ChrW(0)'禁止用户在其中输入任何文字
  94. EndSub
  95. PrivateSubButton1_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesButton1.Click
  96. Me.Hide()
  97. Form2.Show()
  98. EndSub
  99. EndClass
Form2.vb
[vb] view plain copy
  1. ?'**************************************************************
  2. '时间:2008-11-08
  3. '作者:lincyang
  4. '实际应用中,串行通信的数据可能一次发送大量的数据,
  5. '发送之前就必须将数据先编码,
  6. '将其编成我们需要的字节数组数据,
  7. '才能将这些数据以字节的方式发送出去
  8. '目前操作系统使用的字符数据是Unicode:所有的字符均使用
  9. '两个字节来表示一个字符
  10. '**************************************************************
  11. ImportsSystem.IO.Ports
  12. ImportsSystem.Text
  13. PublicClassForm2
  14. DimRS232AsSerialPort
  15. PrivateSubForm2_Load(ByValsenderAsSystem.Object,mStopBit)
  16. IfNotRS232.IsOpenThen
  17. RS232.Open()
  18. btnSend.Enabled=True
  19. Timer1.Interval=100
  20. Timer1.Enabled=True
  21. Else
  22. MsgBox("通讯端口打开错误!",MsgBoxStyle.Critical)
  23. EndIf
  24. EndSub
  25. PrivateSubTimer1_Tick(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesTimer1.Tick
  26. DimInByte()AsByte,ReadCountAsInteger
  27. IfRS232.BytesToRead<=0ThenExitSub
  28. ReDimInByte(RS232.BytesToRead-1)
  29. ReadCount=RS232.Read(InByte,RS232.BytesToRead)
  30. IfReadCount=0Then
  31. ExitSub
  32. Else
  33. ForEachbDataAsByteInInByte
  34. Me.txtReceive.Text+=bData.ToString&vbCrLf'若有数据则加到接收文本框
  35. Next
  36. EndIf
  37. EndSub
  38. PrivateSubbtnClose_Click(ByValsenderAsSystem.Object,MsgBoxStyle.CriticalOrMsgBoxStyle.OkCancel)
  39. Else
  40. RS232.Close()
  41. btnStart.Enabled=False
  42. btnClose.Enabled=False
  43. Timer1.Enabled=False
  44. RS232=Nothing
  45. EndIf
  46. EndSub
  47. PrivateSubbtnSend_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesbtnSend.Click
  48. DimbDataOut()AsByte,BufAsString
  49. DimiSentCountAsInteger
  50. DimEncode1AsEncoding=Encoding.ASCII'声明编码对象,使用ASCII
  51. Try
  52. Buf=txtSend.Text.Trim()
  53. bDataOut=Encode1.GetBytes(Buf)'将字符串转换为字节数组
  54. iSentCount=bDataOut.GetLength(0)'发送总字节数
  55. '显示出总字节数
  56. lblSentCount.Text="总传输量:"&iSentCount.ToString&"字节"
  57. RS232.Write(bDataOut,iSentCount)
  58. CatchexAsException
  59. MessageBox.Show("输入数值错误:"+ex.ToString,"错误通知",MessageBoxIcon.Exclamation)
  60. EndTry
  61. EndSub
  62. PrivateSubbtnEnd_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesbtnEnd.Click
  63. IfNotRS232IsNothingThen
  64. IfRS232.IsOpenThenRS232.Close()
  65. EndIf
  66. End
  67. EndSub
  68. PrivateSubcmbCom_KeyPress(ByValsenderAsObject,ByValeAsSystem.Windows.Forms.KeyPressEventArgs)HandlescmbCom.KeyPress
  69. e.KeyChar=ChrW(0)'禁止用户在其中输入任何文字
  70. EndSub
  71. EndClass

开发环境是VB2008,源码下载 猛击这里!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读