转 C# 串口编程遇到的问题以及解决方法
?? ? ?問題是這樣的,從相應的硬件設備每隔2秒便發送一個大小為15的字節數據,存的是16進制數據,每條數據以7E開頭以7E結尾。例如:7E 09 01 1A ... 7E。但是PC端在接受顯示的時候卻出現了問題,如前五個數據接受正常,接下來的都是以00填充,而剩下的10個數據卻出現在下條數據顯示的位置。如下所 示:?
?? ? ?7E 09 01 1A 5C 00 00 00 00 00 00 00 00 00 00 /// 03 06 1A 2C 3D 09 6C 32 12 7E 00 00 00 00 00 00/// ........
?? ? ?總之感覺錯位了,對了,先把PC端代碼貼一下吧: ? ? ?
?? ??
public?partial?class?Form1?:?Form
????{
????????///?<summary>
????????///?接受數據的串口類?
????????///?</summary>
????????SerialPort?spReceive;
????????delegate?void?ReceivData(byte[]?bytes);
????????public?Form1()
????????{
????????????Form1.CheckForIllegalCrossThreadCalls?=?false;
????????????InitializeComponent();
??????????
????????????spReceive?=new?SerialPort("COM5",?57600,?Parity.None,?8,?StopBits.One);?????????????
????????????spReceive.Open();
????????????
????????????//設置觸發 DataReceived事件的閥值,在調試中發現這個不起作用,不解~??????
????????????spReceive.ReceivedBytesThreshold?=15;????????????
????????????spReceive.DataReceived?+=new?System.IO.Ports.SerialDataReceivedEventHandler(spReceive_DataReceived);????????????
????????}
????????///?<summary>
????????///?更新接受到得數據到UI 界面顯示
????????///?</summary>
????????///?<param?name="bytes"></param>
????????public?void?UpdateReceiveToUI(byte[]?bytes)
????????{
????????????if?(txtReceive.InvokeRequired)
????????????{
????????????????ReceivData?dl?=?new?ReceivData(UpdateReceiveToUI);
????????????????object?arg?=?bytes;
????????????????txtReceive.Invoke(dl,?arg);
????????????}
????????????else
????????????????txtReceive.Text?+=?"/"?+?BitConverter.ToString(bytes);
????????}
????????///?<summary>
????????///?接收到串口數據觸發的事 件
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????public?void?spReceive_DataReceived(object?sender,?System.IO.Ports.SerialDataReceivedEventArgs?e)
????????{
????????????byte[]?recevied?=?new?byte[15];
????????????int?size?=?spReceive.Read(recevied,?0,?recevied.Length);
?? ? ? ? ? ?if?(size?>0)
?? ? ? ? ? ? ? ?UpdateReceiveToUI(recevied);
?? ? ? ? ? ?
????????}
?? ?}
?? ? ? 在調試的過程中,當我spReceive_DataReceived函數中的byte[]?recevied?=?new?byte[15];?后面在加上個初始化,如下:
?? ? ? for( int i=0; i<recevied.Lengthl;i++)
?? ? ? ? ? ? recevied[i]=11;
?? ?
?? ? ? 這個時候界面顯示的時候,凡是以00顯示的地方都被11替換了。這肯定了這些00是由于傳送的15個字節數組未被完全填充到我們定義的字節數組中,即 Read(byte [] bytes,int offset,int size)函數未一次性將字節數組填充完,而是分了兩次。但是在此過程中我使用的是SerialPort類的DataReceived事件,即沒收到一條 數據便會觸發,而這兒的現象仿佛是事件被觸發了多次。后來自己在SerialPort類的屬性里面找了下,突然發現了有個 ReceivedBytesThreshold屬性,從這個屬性可以看出我們可以控制接受多少個字節觸發一次DataReceived事件。于是,我便將 閥值設為15個字節,滿以為問題解決了,可是結果卻~
?? ? ? 囧啊,可是這個屬性也給了我們一些提示,也找到了問題的癥結所在。那就是,DataRecevied事件觸發的閥值,即接受到多少個字節數觸發一次偏小, 結果導致了我們一條大小為15個字節的數據觸發了兩次DataReceived事件。要解決這個問題,我們可以沿著這個思路走下去,那就是延遲 DataRecevied事件的觸發直到我們一條數據接受完畢。
?? ? ? 所以在spReceive_DataReceived事件函數中,我們做如下修改:
?? ? ? byte[] ?receiveBuffer=new byte[15]; ?
?? ? ? public void spReceive_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
?? ? ? {
?? ? ? ? ? ? ?int bytesRead = 0; ?
?? ? ? ? ? ? ?spReceive.ReceivedBytesThreshold = 100000; ? ? //延遲DataRecevied事件的再次觸發
?? ? ? ? ? ? ?
?? ? ? ? ? ? while (true)
?? ? ? ? ? ? {?
?? ? ? ? ? ? ? ? ??if (bytesRead >= 15) ? ? ?//這兒的15是我一條數據的大小
?? ? ? ? ? ? ? ? ?{?
?? ? ? ? ? ? ? ? ? ? ? ?byte[] bytes = new byte[bytesRead];?
?? ? ? ? ? ? ? ? ? ? ? ?Array.Copy(receiveBuffer, 0, bytes, 0, bytesRead); ? ? ??
?? ? ? ? ? ? ? ? ? ? ? ?Array.Clear(receiveBuffer, 0, bytesRead);?
?? ? ? ? ? ? ? ? ? ? ? ?UpdateReceiveToUI(bytes);
?? ? ? ? ? ? ? ? ? ? ? ?bytesRead = 0;?
?? ? ? ? ? ? ? ? ? ? ? ?break;?
?? ? ? ? ? ? ? ? ?}?
?? ? ? ? ? ? ? ? ?try
?? ? ? ? ? ? ? ? {
?? ? ? ? ? ? ? ? ? ?receiveBuffer[bytesRead] = (byte)spReceive.ReadByte();
?? ? ? ? ? ? ? ? ? ?++bytesRead;
?? ? ? ? ? ? ? ? }
?? ? ? ? ? ? ? ?catch (Exception ex1)
?? ? ? ? ? ? ? ?{
?? ? ? ? ? ? ? ? ? ?MessageBox.Show(ex1.Message);
?? ? ? ? ? ? ? ? ? ?break;
?? ? ? ? ? ? ? ?}?
?
?? ? ? ? ? ? ? ?bytesRead = 0;
?? ? ? ? ? ? ? ?spReceive.ReceivedBytesThreshold = 1; ??? ? ? ? ?//將延遲改回正常
?? ? ? ? ? ? }?
?? ? ? }?
?? ??
?? ? ? 經過上述的改動,便可以解決讀取串口數據沖突與丟失的問題了~不周之處,還望各位斧正~
總結
以上是生活随笔為你收集整理的转 C# 串口编程遇到的问题以及解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入Android 【六】 —— 界面构
- 下一篇: c# char unsigned_dll