用控制元件串口做了個小程式,收到資料后發送回傳資料,除錯中發現當收到資料后觸發第一次串口事件后,讀完資料后會觸發第二次時間,詭異的是第二次里緩沖區里位元組是null,后來把代碼簡化到只有接受資料并在文本框里顯示還是這樣,不知道這是咋回事
uj5u.com熱心網友回復:
困擾了我好幾晚上了
uj5u.com熱心網友回復:
發一下關鍵代碼uj5u.com熱心網友回復:
別在乎觸發了幾次,你的目標是管他觸發了幾次么?不是你的目標是,對方發的資料我都收了
uj5u.com熱心網友回復:
using System.Collections.Generic;using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace chuankoueven
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
}
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Parity = System.IO.Ports.Parity.None;
serialPort1.DataBits = 8;
serialPort1.BaudRate = 115200;
serialPort1.StopBits = System.IO.Ports.StopBits.One;
serialPort1.Open();
}
private void button2_Click(object sender, EventArgs e)
{
serialPort1.Close();
}
private void serialPort1_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
byte[] a = new byte[serialPort1.BytesToRead];
serialPort1.Read(a, 0, serialPort1.BytesToRead);
}
uj5u.com熱心網友回復:
隨然能從程式里解決但是這不正常,想弄清原因,uj5u.com熱心網友回復:
沒啥不正常,你以為的解決,其實是沒解決。因為你不明白,本來觸發了幾次就不代表接收了幾次,收到的多少命令。
我們只關心命令是什么,資料是什么,不關心收到了幾次。
如果這個基本觀念你不樹立起來,當你自以為解決了他,但實際上你會發現問題會越來越多,越來越離譜
uj5u.com熱心網友回復:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
SerialDataReceivedEventHandler sdr;
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Parity = System.IO.Ports.Parity.None;
serialPort1.DataBits = 8;
serialPort1.BaudRate = 115200;
serialPort1.StopBits = System.IO.Ports.StopBits.One;
serialPort1.Open();
serialPort1.ReceivedBytesThreshold = 0;
sdr=new SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
serialPort1.DataReceived += sdr
}
private void button2_Click(object sender, EventArgs e)
{
serialPort1.DataReceived -= sdr
serialPort1.Close();
}
private void serialPort1_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
byte[] a = new byte[serialPort1.BytesToRead];
serialPort1.Read(a, 0, serialPort1.BytesToRead);
}
uj5u.com熱心網友回復:
你這個也會觸發兩次uj5u.com熱心網友回復:
你沒看懂問題,我說的是沒有資料發送過來缺被觸發了,一個長資料分幾次接受也很正常,但是前提是有資料觸發uj5u.com熱心網友回復:
e有這個問題
serialPort1.ReceivedBytesThreshold = 0;
uj5u.com熱心網友回復:
你這個也會觸發兩次
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
SerialDataReceivedEventHandler sdr;
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Parity = System.IO.Ports.Parity.None;
serialPort1.DataBits = 8;
serialPort1.BaudRate = 115200;
serialPort1.StopBits = System.IO.Ports.StopBits.One;
serialPort1.Open();
serialPort1.ReceivedBytesThreshold = 0;
sdr=new SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
serialPort1.DataReceived += sdr
}
private void button2_Click(object sender, EventArgs e)
{
serialPort1.DataReceived -= sdr
serialPort1.Close();
}
private void serialPort1_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
byte[] a = new byte[serialPort1.BytesToRead];
serialPort1.Read(a, 0, serialPort1.BytesToRead);
}
不會
uj5u.com熱心網友回復:
沒啥不正常,你以為的解決,其實是沒解決。
因為你不明白,本來觸發了幾次就不代表接收了幾次,收到的多少命令。
我們只關心命令是什么,資料是什么,不關心收到了幾次。
如果這個基本觀念你不樹立起來,當你自以為解決了他,但實際上你會發現問題會越來越多,越來越離譜
別瞎BB
uj5u.com熱心網友回復:
別瞎BB
知道一個serialPort1.ReceivedBytesThreshold = 0;就代表你解決問題了么,如果你能不被硬體工程師叼得話,在回來BB
uj5u.com熱心網友回復:
嘿嘿,請問那位BB的,你知道ReceivedBytesThreshold默認值是1么,你設定不設定他都一樣么?uj5u.com熱心網友回復:
原因是if (e.EventType == System.IO.Ports.SerialData.Eof) 收到了eof
但是還是我說的,我們其實不關心觸發幾次,如果100ms發送一次,那么對方發100次,只會觸發80次呢。如果對付每個指令都發個eof呢?
so,不需要關心他,我們只需要保證,無論觸發多次,無論對方是不是發eof,我都能準確分辨出那100條指令就成。這是我們個核心,這才是不被硬體工程師叼的前提
uj5u.com熱心網友回復:
沒啥不正常,你以為的解決,其實是沒解決。
因為你不明白,本來觸發了幾次就不代表接收了幾次,收到的多少命令。
我們只關心命令是什么,資料是什么,不關心收到了幾次。
如果這個基本觀念你不樹立起來,當你自以為解決了他,但實際上你會發現問題會越來越多,越來越離譜
別瞎BB
嘿嘿,請問那位BB的,你知道ReceivedBytesThreshold默認值是1么,你設定不設定他都一樣么?
注意措辭,小心小黑屋。
uj5u.com熱心網友回復:
別瞎BB
知道一個serialPort1.ReceivedBytesThreshold = 0;就代表你解決問題了么,如果你能不被硬體工程師叼得話,在回來BB
serialPort1.ReceivedBytesThreshold = 0是設定只要收到結束符就觸發資料事件,防止資料重復,在幾百個終端運行的代碼,你用1試試
uj5u.com熱心網友回復:
幾百個終端?????????一個串口,你就幾百個終端了?serialPort1.ReceivedBytesThreshold = 0
人家說的,我就是不想觸發資料,另外1是微軟默認設定的,你告訴我,微軟當時咋想的,這種不負責任的代碼,咋公布出來的
uj5u.com熱心網友回復:
serialPort1.ReceivedBytesThreshold = 0是設定只要收到結束符就觸發資料事件其實設不設都是這個效果,微軟msdn明確告訴你,只要收到eof就會觸發(無論你設沒設,無論你的快取有啥)
https://docs.microsoft.com/zh-cn/dotnet/api/system.io.ports.serialport.receivedbytesthreshold?view=netframework-4.8
注解
如果收到ReceivedBytesThreshold字符, 則會引發事件,而不考慮內部輸入緩沖區中的位元組數和屬性的值。DataReceived Eof
uj5u.com熱心網友回復:
你管這個干什么,組包拆包就好了,這種你不能確定每次都是一次給你發完uj5u.com熱心網友回復:
樓主的鉆研精神應該鼓勵:)uj5u.com熱心網友回復:
沒任何資料 難道你不做判斷?
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int len = sp.BytesToRead;
if (len != 0)
{
byte[] data = new byte[len];
sp.Read(data, 0, data.Length);
DataReceived(data);
}
}
DataReceived是你處理資料的方法,
當然如果你能保證你每次都讀到的是"正確"的資料,
否則組包是不可避免的.
uj5u.com熱心網友回復:
樓主太糾結觸發次數了。接受處理的程式非常不完善。
下面給一個用于工程實際的標準代碼
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort ComDevice = ( SerialPort )sender;
byte[ ] buffer = new byte[serialPort1.ReadBufferSize];
serialPort1.Read(buffer, 0, buffer.Length);
for ( int i = 0 ; i < buffer.Length ; i++ )//用資料長度進行判斷,而不是什么觸發次數
{
if ( buffer[i] > 31 && buffer[i] < 126 )//只處理可視位元組,依照專案實際修改
{
serialPort1Buffer[iBufferIndex1] = buffer[i];
iBufferIndex1++;
if ( iBufferIndex1 > 255 ) iBufferIndex1 = 0;
}
else if ( buffer[i] == 0x0D )//資料幀的結束標識,依照專案實際修改
{
iBufferIndex1 = 0;
g_strSerialPort1 = "";
g_strSerialPort1 = System.Text.Encoding.ASCII.GetString(serialPort1Buffer,0,17);
g_strSerialPort1.Substring(0,17);//本專案接受的資料是17位的條碼。
string msg = "串口1接受到資料:[" + g_strSerialPort1 + "]"+iBufferIndex1.ToString()+"\r\n";
this.BeginInvoke(changeNetMessage, msg);
g_bserialPort1New = true;
textBoxSerialPort1.Text = g_strSerialPort1;//資料顯示
}
else
{
}
}
}
uj5u.com熱心網友回復:
檢查對方給你發的資料!uj5u.com熱心網友回復:
樓主太糾結觸發次數了。
接受處理的程式非常不完善。
下面給一個用于工程實際的標準代碼
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort ComDevice = ( SerialPort )sender;
byte[ ] buffer = new byte[serialPort1.ReadBufferSize];
serialPort1.Read(buffer, 0, buffer.Length);
for ( int i = 0 ; i < buffer.Length ; i++ )//用資料長度進行判斷,而不是什么觸發次數
{
if ( buffer[i] > 31 && buffer[i] < 126 )//只處理可視位元組,依照專案實際修改
{
serialPort1Buffer[iBufferIndex1] = buffer[i];
iBufferIndex1++;
if ( iBufferIndex1 > 255 ) iBufferIndex1 = 0;
}
else if ( buffer[i] == 0x0D )//資料幀的結束標識,依照專案實際修改
{
iBufferIndex1 = 0;
g_strSerialPort1 = "";
g_strSerialPort1 = System.Text.Encoding.ASCII.GetString(serialPort1Buffer,0,17);
g_strSerialPort1.Substring(0,17);//本專案接受的資料是17位的條碼。
string msg = "串口1接受到資料:[" + g_strSerialPort1 + "]"+iBufferIndex1.ToString()+"\r\n";
this.BeginInvoke(changeNetMessage, msg);
g_bserialPort1New = true;
textBoxSerialPort1.Text = g_strSerialPort1;//資料顯示
}
else
{
}
}
}
uj5u.com熱心網友回復:
serialPort1.ReceivedBytesThreshold = 0是設定只要收到結束符就觸發資料事件
其實設不設都是這個效果,微軟msdn明確告訴你,只要收到eof就會觸發(無論你設沒設,無論你的快取有啥)
https://docs.microsoft.com/zh-cn/dotnet/api/system.io.ports.serialport.receivedbytesthreshold?view=netframework-4.8
注解
如果收到ReceivedBytesThreshold字符, 則會引發事件,而不考慮內部輸入緩沖區中的位元組數和屬性的值。DataReceived Eof
uj5u.com熱心網友回復:
原因是
if (e.EventType == System.IO.Ports.SerialData.Eof) 收到了eof
但是還是我說的,我們其實不關心觸發幾次,如果100ms發送一次,那么對方發100次,只會觸發80次呢。如果對付每個指令都發個eof呢?
so,不需要關心他,我們只需要保證,無論觸發多次,無論對方是不是發eof,我都能準確分辨出那100條指令就成。這是我們個核心,這才是不被硬體工程師叼的前提
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/124802.html
標籤:C#
上一篇:C#與高精度智能盤面表
