如果PC軟體寫入指令,然后讀出資料正常。但PC不送指令,下位機在其它時候發送了資料,如何讀出?
即PC寫入指令,上位機接收到指令后會回傳資料給PC,此時PC能正常接收到上位機發送的資料。
但,過一段時間后,上位機發送其它新資料給PC(發送時間不定),此時PC如何知道上位機發送了資料,然后去接收?
我試過定時多少ms不停的去讀資料,但這樣不能正常讀到發送的資料?
上位機有資料發送到PC,是否有什么狀態發生,然后去通知PC讀資料?
用Bus Hound或其它工具能正常抓到上位機發送的資料。
PC軟體如何才能正常合理接收資料?
uj5u.com熱心網友回復:
和讀串口差不多,首先你要找到設備名,有了設備名就可以象打開檔案一樣操作了.uj5u.com熱心網友回復:
PC發送一條指令后,能正常收到下位機上傳的資料。
寫用:FileStream.wirte()
讀用:BeginRead()
但在PC不發送指令的情況下,下位機上傳資料到PC?不知道何時去讀,一直回圈去讀?
uj5u.com熱心網友回復:
開個執行緒一直讀吧,回圈中Sleep(1)一下可以降低CPU占有率。uj5u.com熱心網友回復:
開執行緒一直讀是能讀到下位機發送的資料,但是,PC發不出指令了。
原來的方法是:
1.用FileStream.Write()寫資料。
2.用FileStream.BeginRead或FileStream.Read讀資料
即要呼叫讀后,寫的資料才實際寫到下拉機。
即只呼叫FileStream.Write(),在Bus Hound看不到有資料輸出,當呼叫Read后,Bus Hound有輸出資料,和回傳的資料了
但問題是子執行緒一直在呼叫FileStream.Read讀資料,所以現在程式執行到Read后一直停在那里,不下去了。
uj5u.com熱心網友回復:
Read沒有資料可讀時不會回傳嗎?為什么是FileStream.Read,操作物件為什么是FileStream?uj5u.com熱心網友回復:
執行緒回圈中讀取的時候,用Sleep讓出一些CPU,兩個cpp讀、寫FileStream用CriticalSection來控制,避免沖突。uj5u.com熱心網友回復:
USB HID不熟悉,所以用的C#寫的讀取USB HID設備的測驗軟體http://download.csdn.net/download/haiguozhe/8908701#comment改的。
public class DeviceInformation
{
public Boolean DeviceIsDetected;
public String myDevicePathName;
public HIDD_ATTRIBUTES DeviceAttributes;
public HIDP_CAPS Capabilities;
public IntPtr DeviceNotificationHandle;
public int NumberOfInputBuffers;
public Boolean ExclusiveAccess;
public FileStream FileStreamDeviceData;
public SafeFileHandle HidHandle;
public String HidUsage;
}
private void ReOpenDeviceFileStreamHandler(DeviceInformation findDevice)
{
//關閉句柄并用讀/寫模式重新打開
findDevice.HidHandle.Close();
findDevice.HidHandle = FileIO.CreateFile(findDevice.myDevicePathName, FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);
Debug.WriteLine("在函式ReOpenDeviceFileStreamHandler中" + this.MyDebugging.ResultOfAPICall("CreateFile"));
if (findDevice.HidHandle.IsInvalid)
{
findDevice.ExclusiveAccess = true;
Debug.WriteLine("此設備是一個系統" + findDevice.HidUsage + "." + "對于此設備,Windows 2000 和 Windows XP 才能使用 Input 和 Output reports功能.");
}
else
{
if (findDevice.Capabilities.InputReportByteLength > 0)
{
// Set the size of the Input report buffer.
Byte[] inputReportBuffer = null;
inputReportBuffer = new Byte[findDevice.Capabilities.InputReportByteLength];
findDevice.FileStreamDeviceData = new FileStream(findDevice.HidHandle, FileAccess.Read | FileAccess.Write, inputReportBuffer.Length, false);
}
// Flush any waiting reports in the input buffer. (optional)
_hidObject.FlushQueue(findDevice.HidHandle);
}
}
寫資料:
if (device.FileStreamDeviceData.CanWrite)
{
device.FileStreamDeviceData.Write(outputReportBuffer, 0, outputReportBuffer.Length);
success = true;
}
讀資料:
ar=device.FileStreamDeviceData.BeginRead(inputReportBuffer, 0, inputReportBuffer.Length, new AsyncCallback(GetInputReportData), inputReportBuffer);
如果現在單呼叫寫指令,然后呼叫讀指令,能正常送出指令和接識訓傳的指令,但如果不送指令,就收不到下位機的資料。
如果用子執行緒回圈呼叫讀,能正常讀出下位機發出的所有資料,但又不能送出指令。
uj5u.com熱心網友回復:
現在的問題是開子執行緒呼叫異步讀后:device.FileStreamDeviceData.BeginRead(inputReportBuffer, 0, inputReportBuffer.Length, new AsyncCallback(GetInputReportData), inputReportBuffer);
子執行緒一直在待命狀態,等待有資料來,然后處理讀資料。
此時呼叫write()后不能呼叫read或BeginRead,指令不能下發?
其實呼叫異步讀時,他本身就有另一個執行緒的。
下發指令時可否停止異步讀的執行緒,下發命令后,再重新打開讀?
uj5u.com熱心網友回復:
下發指令時可否停止異步讀的執行緒,下發命令后,再重新打開讀?————
可以掛起執行緒,下發后,再繼續執行緒。
你說device.FileStreamDeviceData.BeginRead會一直等待有資料才回傳,看看有沒有一個成員函式用來判斷是否有資料,有資料才讀。
uj5u.com熱心網友回復:
沒有,如果有,我就會定時查找有資料,然后再讀就行了。
1.不開執行緒情況 下,呼叫讀寫,能正常發出指令,且收到資料。
this.MyDeviceManagement.WriteReportToDevice(0, outdatas);
this.MyDeviceManagement.ReadReportFromDevice(0, ref inputdatas, 100);
private byte[] ReadAndWriteToDevice()
{
byte[] outdatas = new byte[16];
outdatas[0] = 0x55;
outdatas[1] = 0x2;
outdatas[2] = 0x1;
outdatas[3] = 0x00;
byte[] inputdatas = new byte[192];
byte[] inputs = new byte[8];
inputs[0] = 0xa1;
if (inputs != null && inputs.Length > 0)
{
outdatas = inputs;
}
//this.txtBytesReceived.Clear();
Application.DoEvents();
this.MyDeviceManagement.WriteReportToDevice(0, outdatas);
this.MyDeviceManagement.ReadReportFromDevice(0, ref inputdatas, 100);
//MyDeviceManagement.ReadReportFromDevice1();
Application.DoEvents();
return inputdatas;
}
2.開了執行緒,寫之前加入取消讀屬性,然后再呼叫第1步的寫,讀,程式會停在讀的位置
private void button2_Click(object sender, EventArgs e)
{
if (t1.ThreadState == ThreadState.Running)
{
MyDeviceManagement.CancelRead = true;
while (true)
{
System.Threading.Thread.Sleep(5);
if (t1.ThreadState == ThreadState.Stopped)
{
break;
}
}
}
MyDeviceManagement.CancelRead = false;
this.ReadAndWriteToDevice();
t1 = new Thread(MyDeviceManagement.ReadReportFromDevice1);
t1.Start();
}
這是子執行緒中判斷如果取消了,則中斷執行緒
while (true)
{
if (_cancelRead == true)
{
System.Threading.Thread.CurrentThread.Abort();
}
if (this._isStop)
break;
if (!_transferInProgress)
{
break;
}
System.Threading.Thread.Sleep(5);
}
不知道為什么呼叫Write后,不呼叫Read,指令出不去?
uj5u.com熱心網友回復:
你的代碼我看不懂,寫的時候應該是在某個表單單元,比如某個ButtonClick里。開一個子執行緒,在執行緒回圈中讀取。
執行緒回圈中讀取的時候,用Sleep主動讓出一些CPU。讀、寫FileStream用CriticalSection來控制,避免沖突。
uj5u.com熱心網友回復:
USB Slave 是被動回應的,通訊都先要由USB Host 發起,也就是要先讀。如果在執行緒中讀取USB資料,如果下位機資料沒有準備好,并且沒有使用異步讀取,則會阻塞,當下位機有資料時回傳。uj5u.com熱心網友回復:
@vc_dreamver可以使用異步讀取嗎,有沒有資料讀取函式都回傳的?
uj5u.com熱心網友回復:
就是子執行緒開了異步一下讀?主執行緒如何寫入指令呢?
一般怎么處理好一些?
1.正常發送指令,接收資料?
2.如何在不發送指令情況下,檢測有上位機資料到PC?
uj5u.com熱心網友回復:
@wyhkgd可不可以修改一下通訊協議。
首先,PC先發查詢指令,查詢有沒有資料準備上報,下位機應答,回傳是否有上報資料,及具體資料長度。
第二步再由PC讀取,下位機上傳。
一般與硬體通訊,我盡可能在一個執行緒里實作讀取與寫入,因為介面不一定是執行緒安全的。
uj5u.com熱心網友回復:
@ooolinux如果用ReadFile應該可以實作異步讀取,與串口類似吧,加回呼事件。
不過我覺得這樣不如修改一下通訊協議更簡單省事。
uj5u.com熱心網友回復:
如果只是PC發指令接收,已可以了,但在PC不發指令的情況下,要接收從下位機上傳來的資料。
用Bus Hound,PortHelper或其它USB工具都可以看到下位機上傳的資料的,肯定是有方法,只是我不知道而已。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/50698.html
