我已经创建了一个从串口接收数据的应用程序,我可以很好地接收DataReceived事件的数据。
设备不发送只是字节,但它发送的帧看起来像"#" + 16字节数据+&#34 ;;"其中#是STX和;是ETX。
如何正确实施?我只想在正确接收到这样的帧时处理数据。 DataReceived事件不会帮助我实现这一点,因为它会触发每个字节,而不是一帧数据。
答案 0 :(得分:1)
一些示例代码。通过将打开的SerialPort对象传递给其构造函数来初始化类。您需要订阅其DataReceived事件以接收数据。使用ErrorReceived进行诊断。如果您有一个事件,则在UI线程上引发事件。未经测试的代码,应该在球场。
public ref class SerialProtocol {
private:
array<Byte>^ buffer;
bool gotStx, warnStx;
int bufcnt;
SerialPort^ port;
System::Threading::SynchronizationContext^ context;
const int framesize = 16;
const Byte STX = 2;
const Byte ETX = 3;
public:
SerialProtocol(SerialPort^ Port) :
buffer(gcnew array<Byte>(framesize)),
bufcnt(0), gotStx(false), warnStx(false),
context(System::Threading::SynchronizationContext::Current),
port(Port) {
Port->DataReceived += gcnew SerialDataReceivedEventHandler(this, &SerialProtocol::DataReceivedHandler);
}
event ErrorReceivedHandler^ ErrorReceived;
event DataReceivedHandler^ DataReceived;
private:
void DataReceivedHandler(Object^ sender, SerialDataReceivedEventArgs^ e) {
while (port->BytesToRead > 0) {
Byte b = port->ReadByte();
if (!gotStx) {
// Need to see STX as start of frame now
gotStx = b == STX;
if (!gotStx && warnStx) OnProtocolViolated(ProtocolViolation::BadStx);
warnStx = false;
bufcnt = 0;
}
else if (bufcnt == buffer->Length) {
// Got the frame data, need to see ETX now
gotStx = false;
warnStx = b == ETX;
if (b == ETX) OnDataReceived();
else OnProtocolViolated(ProtocolViolation::BadEtx);
}
else {
// Busy receiving frame data
buffer[bufcnt++] = b;
}
}
}
void OnProtocolViolatedHelper(Object^ state) {
ErrorReceived(safe_cast<ProtocolViolation>(state));
}
void OnDataReceivedHelper(Object^ state) {
DataReceived(safe_cast<array<Byte>^>(state));
}
protected:
virtual void OnProtocolViolated(ProtocolViolation error) {
// Fires the ErrorReceived event
if (context == nullptr) ErrorReceived(error);
else context->Post(gcnew System::Threading::SendOrPostCallback(this, &SerialProtocol::OnProtocolViolatedHelper), error);
}
virtual void OnDataReceived() {
// Fires the DataReceived event
if (context == nullptr) DataReceived(buffer);
else {
// Keep the buffer threadsafe
array<Byte>^ data = buffer;
buffer = gcnew array<Byte>(framesize);
context->Post(gcnew System::Threading::SendOrPostCallback(this, &SerialProtocol::OnDataReceivedHelper), data);
}
}
};