![]() |
Wie kann ich mit Delphi Daten vom USB-Controller abfragen?
Liste der Anhänge anzeigen (Anzahl: 1)
Ok, ich hoffe, dass ich hier die richtige Rubrik getroffen habe...
Ich brauche eure Hilfe, weil ich wahrscheinlich den Wald vor lauter Bäumen nicht mehr sehe o_O... Ih bastel an einem System mit einem Microcontroller, der IR-Daten empfängt und diese via USB an einen PC überträgt. Auf dem PC läuft ein Delphiprogramm... Die Treiber und alles sind vorhanden und es funktioniert in soweit, dass ich vom dem Delphi-Programm aus eine Abfrage über bestimmte Daten, wie z.B. die Firmwareversion machen kann, der Microcontroller diese beantwortet und das Delphi-Programm es anzeigt. Nun ist es aber so, dass die IR-Daten, die ich übermitteln muss, nicht direkt auf Anhieb verfügbar sind... D.h. ich habe also vor einen Button zu drücken, der im Microcontroller das Empfangen von IR-Daten scharf schaltet (funktioniert auch)... Aber wenn er Daten empfangen hat, muss das Delphi-Programm das irgendwie mitbekommen... Eine Systembeschreibung als Bild (erklärt es vllt noch verständlicher) hänge ich an Nach der USB-Spezifikation ist es so, dass der Hostcontroller im PC ständig seine Schäfchen abfragt, ob neue Daten vorhanden sind... D.h. ein USB-Gerät kann keinen direkten Interrupt auslösen... Beispiel: Eine USB-Maus wird mehrere hundert Male in der Sekunde abgefragt, ob sie neue Daten hat, da sie nicht schreien kann "EY, der User berührt mich!"... Im Hintergrund muss dann irgendwo dieser Treiber laufen, der dann auf neue Daten reagiert und sie graphisch umsetzt... Aber er weiß ja nie, WANN der Benutzer die Maus bewegen wird... Wie kann ich denn nun mit Delphi auf den Host-Controller zugreifen um meine Daten abzufragen? Mit der Treiber DLL? Mit irgendeiner Windows Datei? Muss ich in einer Schleife immer wieder via USB den Controller selbst abfragen? Zum Anfang würde es mir reichen, dass das Delphi-Programm solange in einer Schleife wartet, bis der Controller Daten liefert und dann sagt "Neue Daten empfangen. Daten: ..." Vllt müsste ich im Hintergrund dann nur einen Timer laufen lassen, falls eine Minute nichts empfangen wurde, dass er den ganzen Kram abbricht... Btw: Gibt es in Delphi eine fertige Timer-Funktion, die man im Hintergrund laufen lassen kann und die einen Interrupt im Programm auslöst? Oder muss ich sowas mit einer while-Schleife umsetzen? INFOS: Die USB-DLL basiert auf ![]() Genauer auf die von Sprut: ![]() Auf ![]() Ich habe einfach noch ein Button dazu gebaut, dass momentan eben nur einen Code sendet, der das Starten des Microcontroller aktiviert. Bei Sprut ist auch die Funktion SendReceivePacket erklärt, die zur USB-Kommunikation verwendet wird. Code Beispiel: Auslesen der Firmware im Microcontroller
Delphi-Quellcode:
Meine Funktion gibt einfach eine andere Konstante (READ_IR) über den USB und verlangt keine Antwortbytes (RecvLength:=0;), wodurch im Microcontroller einfach nur eine Funktion gestartet wird.
procedure TForm1.Button3Click(Sender: TObject);
var selection : DWORD; send_buf : PBYTE; receive_buf : PBYTE; RecvLength : DWORD; CurrentCMD : BYTE; begin // Read Firmware version //instance ist warscheinlich 0, kann aber auch einen anderen Wert haben selection:=0; // sind USB-Devices vorhanden? if (_MPUSBGetDeviceCount(vid_pid)=0) then begin Memo1.lines.add('- Device not connected'); exit; end; //pipes anfordern //für die instance=0 //es kann aber passieren, da´ss instance<>0 !! //da ist noch nacharbeit nötig myOutPipe:= _MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0); myInPipe:= _MPUSBOpen(selection,vid_pid,out_pipe,MP_READ,0); //habe ich pipes bekommen? if ((myOutPipe = INVALID_HANDLE_VALUE) or (myInPipe = INVALID_HANDLE_VALUE)) then begin Memo1.lines.add('USB Error'); exit; end; //Firmwareversion auslesen send_buf[0]:=READ_VERSION; [b]// READ_VERSION: Eine hexadezimale Konstante, die vom PIC interpretiert werden kann, // worauf er in recieve_buf[3] und [2] seine Antwort hinein schreibt. (Ausgabe = 2.0)[/b] RecvLength:=4; [b]// Anzahl zu empfangener Bytes[/b] // HIER DAS IST DIE SCHLÜSSELFUNKTION ZUR ÜBERTRAGUNG ÜBER USB if(SendReceivePacket(send_buf,1,receive_buf,RecvLength,100,100) = 1) then begin if(receive_buf[0] = READ_VERSION) then begin Memo1.lines.add('Firmware version : '+ IntToStr(receive_buf[3])+'.'+IntToStr(receive_buf[2])); end; end else begin Memo1.lines.add('USB Error'); end; _MPUSBClose(myOutPipe); _MPUSBClose(myInPipe); myInPipe:= INVALID_HANDLE_VALUE; myOutPipe:=INVALID_HANDLE_VALUE; end; //Firmwareversion auslesen Wenn ihr mehr wissen braucht, einfach fragen! P.S. Wenn sich nun einer fragt, was ich vom ihm will: Natürlich verlange ich keine komplette Lösung, wie ich das Problem lösen kann, aber über Anregungen würde ich mich freuen... Ich beherrsche in Delphi nur Basics, also bin kein Delphi-Guru... Aber ich denke ich bin lernfähig ;)... DANKE im Voraus... |
Re: Wie kann ich mit Delphi Daten vom USB-Controller abfrage
Also einen Timer gibt es in Delphi
nennt Sich TTimer und ist in der KarteiKarte System ( zumindest in D5 ) |
Re: Wie kann ich mit Delphi Daten vom USB-Controller abfrage
Kannst Du den PIC einen Buffer verpassen, vielleicht 4000Bytes, der die ganzen Werte zwischenspeichert und du bedienst dich aus dem Buffer alle, sagen wir 20ms?
|
Re: Wie kann ich mit Delphi Daten vom USB-Controller abfrage
Liste der Anhänge anzeigen (Anzahl: 1)
@Daniel B:
Der PIC hat einen 64 Byte großen Puffer, daran kann ich leider nichts einstellen... :(... @Corpsman: Danke, ich werde die Information im Hinterkopf behalten... --- Inzwischen habe ich ein wenig weiter gearbeitet... Ich habe auf die Funktionen _MPUSBWrite und _MPUSBRead für de USB-Kommunikation zurück gegriffen... Gesendet wird mein Codewort READ_IR und der Pic reagiert darauf (mit einer leuchtenden LED) Dann habe ich eine While-Schleife dahinter gesetzt, die prüft, ob Daten angekommen sind... Und hey, das Programm springt nur raus, wenn auch welche gekommen sind. (Habe es getestet, in dem ich im PIC ein Delay eingebaut hat, dass erst nach einer Weile 2 Datenpackete in die Buffer schreibt, die vom Delphi-Programm ausgelesen werden -> receive_buf) Jedenfalls, jetzt wollte ich einen Timout einbauen, der in einem TLABEL oder einem TEDIT-Feld angezeigt wird. ABER Der macht das nicht... Guggst du:
Delphi-Quellcode:
//Rumtesten send_buf[0]:=READ_IR; // Wird vom Microcontroller erkannt und er schaltet seine Interrupts ein RecvLength:=4; // Anzahl der erwarteten Bytes ExpectedReceiveLength:= RecvLength; if(_MPUSBWrite(myOutPipe,send_buf,1,SentDataLength,100)<> 0) then begin Memo1.lines.add('gesendet'); // wird ausgegeben, PIC reagiert receive_buf[2] := 0; // Voreinstellung, damit er nicht vorzeitig aus der Schleife gekickt wird TimeCounter := 10; // 10 Sekunden Timeout // wenn der µC in den Buffer schreibt, ist der Wert 52 soweit erst mal fest while((receive_buf[2] <> 52) AND (TimeCounter > 0)) do begin // Habe ich etwas empfangen? Nein = 0, dann "warte" if(_MPUSBRead(myInPipe,receive_buf,ExpectedReceiveLength,RecvLength,100)=0) then begin Memo1.Lines.Add("Warte": IntToStr(TimeCounter)); // Ausgabe des Timers im Memofeld Label2.Caption := IntToStr(TimeCounter); // Ein Label, in dem der Timer angezeigt werden soll sleep(900); // 100ms werden schon in der _MPUSBRead-Funktion gewartet TimeCounter:=TimeCounter-1; end else Memo1.lines.add('Empfangen'); // funktioniert auch, wenn der PIC seine Daten gesendet hat end; if TimeCounter = 0 then Memo1.lines.add('TIMEOUT!'); // funktioniert auch, wenn der Timer abgelaufen ist Memo1.lines.add('Firmware version : '+ IntToStr(receive_buf[3])+'.'+IntToStr(receive_buf[2])); end; Die Zeit im Memofeld wird angezeigt, aber nicht im Label o_O... Und auch, wenn ich das Label durch ein TEdit ersetze und die Zuweisung
Delphi-Quellcode:
einbaue geht es nicht... -_-...
Edit1.Text := IntToStr(TimeCounter);
Jedoch, wenn "TIMEOUT!" ausgegeben wurde, setzt er das Label auf "1" o_O... WARUM macht der das? Und warum macht er nicht das, was er machen soll? Jemand eine Idee? Ich habe den Sleep-Befehl auch schon mal entfernt -> Ging auch nicht... Im Anhang ein Screenshot der GUI |
Re: Wie kann ich mit Delphi Daten vom USB-Controller abfrage
Hallo,
zur Kommunikation mit einem Mikrocontroller gibt es natürlich unabsehbar viele Möglichkeiten, und einige zig davon habe ich auch schon realisiert, daher ist meine Meinung: Wenn du schon in der glücklichen Lage bist, das Protokoll auf beiden Seiten beeinflussen zu können, dann ist die übersichtlichste und sauberste Lösung, IMMER eine Antwort zu fordern. Ich würde also Anfragen über USB senden, die der Chip immer beantworten muss, entweder mit Daten oder mit der Antwort "habe gerade keine Daten". Das ist weitaus einfacher als mit Interrupts bzw. Events zu arbeiten - möglich ist das schon, schliesslich können ja die Serial-Adapter auch Events auslösen bei Datenempfang. So aber gibt es nur die einfache Transaktion Senden -> Antwort auswerten. Daten im Chip zwischenzuspeichern, wie von jemandem empfohlen, ist nicht nur eine gute Idee, sondern eigentlich selbstverständlich. Man kann die Übertragung optimieren, indem man nach Datenempfang sofort wieder anfragt, nach "keine Daten" erst nach längerer Pause, dann werden zwischengespeicherte Daten schnell übertragen, der Bus aber nicht mehr las nötig belastet. Gruss Reinhard |
Re: Wie kann ich mit Delphi Daten vom USB-Controller abfrage
Der Hostcontroller ist fuer Programme nicht zugaenglich und das ist auch gut so. Das Polling findet in Hardware statt und daher ist auf Anwendungsebene davon garnichts zu sehen. Ein USB-Geraet schickt Daten wenn es welche zu schicken hat. In diesem Fall sicherlich wenn man auf der IR-Fernbedienung einen Knopf drueckt. Das API bietet doch eine Funktion zum Lesen von Daten mit Timeout. Da startet man einen Thread der auf die Daten wartet und mit dem Timeout wacht der Thread periodisch auf, damit man ihn vorzeitig beenden kann auch wenn keine Daten kommen.
So mache ich es in meiner HID-Komponente und es funktioniert hervorragend. |
Re: Wie kann ich mit Delphi Daten vom USB-Controller abfrage
Hi!
Zitat:
Ansonsten schaumal hier: ![]() Ciao, Frederic |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz