none
VB2005 兩台電腦用RS232進行資料傳輸會掉資料 RRS feed

  • 問題

  • 各位大大

    我的開發環境是
    VB2005
    .net framework 2.0

    我練習了一個RS232的傳輸程式

    兩台電腦透過這個程式介面,用RS232傳輸方式進行資料傳輸

    在RS232的設定如下

     PortName = Com2
     BaudRate = 9600
     DataBits = 8
     Parity = IO.Ports.Parity.None
     StopBits = IO.Ports.StopBits.One

    當我的BaudRate設為9600時,資料傳輸都很正常,但是當我把BaudRate調高到115200時,就會掉資料

    因此想請教各位大大,有什麼樣的方式,可以避免掉資料問題

    Imports System.IO.Ports
    Imports System.Text
    Public Class Form1
    
    	Public Sub Com_Port()
    		ComboBox1.SelectedItem = "COM2"
    		ComboBox2.SelectedItem = "115200"
    		ComboBox3.SelectedItem = "NONE"
    		ComboBox4.SelectedItem = "8"
    		ComboBox5.SelectedItem = "1"
    
    	End Sub
    	Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    		Call Com_Port()
    		Call Button1_Click(sender, e)
    		Me.SerialPort1.ReceivedBytesThreshold = 1
    	End Sub
    
    	Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    		If SerialPort1.IsOpen = False Then
    			SerialPort1.PortName = ComboBox1.SelectedItem
    			SerialPort1.BaudRate = Val(ComboBox2.SelectedItem)
    			SerialPort1.DataBits = Val(ComboBox4.SelectedItem)
    			If ComboBox3.SelectedItem = "NONE" Then
    				SerialPort1.Parity = IO.Ports.Parity.None
    			ElseIf ComboBox3.SelectedItem = "OOD" Then
    				SerialPort1.Parity = IO.Ports.Parity.Odd
    			ElseIf ComboBox3.SelectedItem = "EVEN" Then
    				SerialPort1.Parity = IO.Ports.Parity.Even
    			ElseIf ComboBox3.SelectedItem = "MARK" Then
    				SerialPort1.Parity = IO.Ports.Parity.Mark
    			Else
    				SerialPort1.Parity = IO.Ports.Parity.Space
    			End If
    
    
    			If ComboBox5.SelectedItem = "1" Then
    				SerialPort1.StopBits = IO.Ports.StopBits.One
    			ElseIf ComboBox5.SelectedItem = "1.5" Then
    				SerialPort1.StopBits = IO.Ports.StopBits.OnePointFive
    			Else
    				SerialPort1.StopBits = IO.Ports.StopBits.Two
    			End If
    
    			SerialPort1.Open()
    			Button1.Enabled = False
    			Button2.Enabled = True
    		Else
    			MsgBox(ComboBox1.SelectedItem & "已開啟!")
    
    		End If
    
    
    	End Sub
    
    	Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    
    		If SerialPort1.IsOpen = False Then
    
    			MsgBox(ComboBox1.SelectedItem & "已關閉!")
    		Else
    			SerialPort1.Close()
    			Button1.Enabled = True
    			Button2.Enabled = False
    		End If
    
    	End Sub
    
    	Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    		If SerialPort1.IsOpen = False Then
    
    			MsgBox(ComboBox1.SelectedItem & "已關閉,將無法輸入。")
    		Else
    			SerialPort1.Write(TextBox1.Text)
    		End If
    
    	End Sub
    	Private Sub AddRecieve(ByVal sender As System.Object, ByVal e As System.EventArgs)
    		Dim buffer(SerialPort1.BytesToRead) As Byte
    		Dim str As String = ""
    		SerialPort1.Read(buffer, 0, SerialPort1.BytesToRead)
    		str &= New ASCIIEncoding().GetString(buffer) & vbCrLf
    		TextBox2.Text &= str & vbCrLf
    		Timer1.Interval = 30
    		Timer1.Enabled = True
    	End Sub
    
    	Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    		Me.Invoke(New EventHandler(AddressOf AddRecieve))
    	End Sub
    
    	Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
    		TextBox2.Clear()
    	End Sub
    
    	Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    		TextBox2.Text &= vbCrLf
    		Timer1.Enabled = False
    	End Sub
    End Class

    2012年2月13日 上午 09:41

解答

  • 你的第一個錯誤應該是 BytesToRead 取得的數量已經大於 你的buffer 陣列的大小.

    另外一個是, 你可以試著改寫成[Serial Port 系列(11) 基本篇 -- 利用執行緒讀取資料]

    這樣的方式去讀讀看, 並在 Read 前加入適當的Sleep,或是將資料先行切割在傳送

    另一篇的問題, 請你將上述的回應寫到該討論緒中即可, 其它我會處理.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 Super Saiyan 2012年2月14日 上午 08:10
    2012年2月14日 上午 08:02
    版主

所有回覆

  • 會掉資料有很多原因

    (1) 受干擾,在你的狀況這發生機率應該不是很大

    (2) RS232 的通訊晶片不夠好,撐不住這麼快

    .....

    不過我有幾個建議:

    (1) 用第三方軟體監控是否真的有掉資料 , 參考璉大的文 [[推薦]通訊必備監聽軟體 AccessPort]

    (2) Forms.Timer 沒啥必要,  不需要這樣寫

    (3) 在你 Form1的Load 事件委派函式中的 Call Button1_Click(sender, e) 這種寫法是不適當的, 你寧可另外寫一個獨立的Method來呼叫或是改用button.Performclick, 當你用 Call Button1_Click(sender, e) 那個 sender 和 e 所帶的內容會是錯的

    (4) 我在自己的Blog上有寫一系列關於 Serialport 的文 (雖然還有一堆沒寫完) , 建議你重頭看, 瞭解其內容, 如果你肯花點時間去瞭解, 效用會比光抄Code來的大, [.Net 海角點部落 Serial Port]


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2012年2月13日 上午 09:56
    版主
  • 發送、接收緩衝區調大。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2012年2月13日 下午 12:09
  • 感謝 Bill Chung 回覆

    關於您寫 Serialport 的文章寫得很詳細。

    我用AccessPort測試正常。

    另外看到AccessPort中在右下角有TX與RX的資訊

    因此想請教在SerialPort1中是否也可以讀取相關的資訊

    另外,我還有遇到一個問題是傳輸時遇到中文字

    傳送端都可以正常顯示,但是接收端會顯示成亂碼?

    2012年2月14日 上午 02:46
  • (1) TX , RX 燈號可以做到類似的效果, 只能說類似, 因為我也不曉得AccessPort 的作者是監控哪一部份. 比方你可以用 Thread 去監看 BytesToRead 和 BytesToWrite, 然後用其變化值調整.

    (2) 中文字的問題, 應該是你在編解碼的地方不正確, 請詳閱 MSDN 文件庫的 [Encoding 類別]

    (3) 若是Accessport 看起來正常, 或許如心冷大所言, 調整發送接收緩衝區,  或是在接收的部份利用各種技巧確認完整性.

    順帶一提 [VB.Net 物件消失問題] 目前狀況如何?


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。



    2012年2月14日 上午 05:55
    版主
  • 感謝 Bill 大大的回覆

    我把Call Button1_Click(sender, e) 的寫法改成另外寫一個副程式來呼叫

    把Forms.Timer都拿掉

    另外我還把ReadBufferSize和WriteBufferSize都調到8192



    中午過後測試大資料的傳輸

    記事本的大小約80KB的資料量

    接收時會在下面一行中發生警告

    SerialPort1.Read(buffer, 0, SerialPort1.BytesToRead)


    另外我用同樣的資料量透過Accessport來傳送 ,發送端則會有當機的情況

    接收端為我寫的程式則顯示幾行就沒訊息了

    我是用C:\Windows\ocmsn.log    的記事本當作資料進行傳輸

    我把程式的傳送與接收分開測試

    1.傳送時用我的程式傳送,Accessport接收,傳送跟接收內容都一樣

    2.而傳送用Accessport,用我的程式接收。我的程式只接到幾行,Accessport端的電腦則當機

    3.而我用我的程式在兩台電腦傳送跟接收,則接收的資料有很多沒有接收到

    因此,我想應該是在接收部分的程式有問題


    VB.Net 物件消失問題  問題VB2005的軟體重開後就解決了,但此問題結案該用什麼答案?

    2012年2月14日 上午 07:47
  • 你的第一個錯誤應該是 BytesToRead 取得的數量已經大於 你的buffer 陣列的大小.

    另外一個是, 你可以試著改寫成[Serial Port 系列(11) 基本篇 -- 利用執行緒讀取資料]

    這樣的方式去讀讀看, 並在 Read 前加入適當的Sleep,或是將資料先行切割在傳送

    另一篇的問題, 請你將上述的回應寫到該討論緒中即可, 其它我會處理.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 Super Saiyan 2012年2月14日 上午 08:10
    2012年2月14日 上午 08:02
    版主
  • Bill 大大

    您說的沒錯,我後來在警告的地方發現上面的Buffer大小只有  buffer(256)

    可是我下面的buffer大小buffer(4096),才會出現錯誤

    而會出現掉字,那是我的錯覺,因為我把txt檔的文字複製貼到TextBox時

    是沒有完全複製過去的,只複製了上半段,所以跟原檔比較起來少掉了一千多行

    2012年2月14日 上午 08:10
  • 我覺得是 FAQ ...

    先看看相關討論:

    http://social.msdn.microsoft.com/Search/zh-TW/?Refinement=112&query=SerialPort%20MemoryStream


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2012年2月14日 下午 03:03