Probleme mit USB
-
Hallo zusammen,
ich habe heute morgen ein hitex StarterKit bekommen (muss was zu embedded sytems machen). Habe da auch eine USB Software einspielen können, so dass sich das Borad am PC nun als HID Device anmeldet, funktioniert auch alles super. Jetzt habe ich angefangen über C++ auf das Ding zuzugreifen, bin auch schon relativ weit gekommen, dafür, dass ich eigentlich keine Ahnung hab

Hab es geschafft per CreateFile das Handle des Devices wiederzubekommen und allerhand Daten auszulesen (manufaturer String, Product String, Capabilities, VID, PID).
Jetzt würde ich aber gerne mit dem Gerät kommunizieren. Eigenlich müsste es, es hat einen Potentiometer, die ganze Zeit Daten senden, über den Wert des Meters. Wie frage ich diese Daten ab.
Dazu kommt noch, dass das Borad 8 LEDs drauf hat, die ich auch gerne per C++ ein und ausschalten würde.Usage 1 unsigned short UsagePage 65280 unsigned short InputReportByteLength 5 unsigned short OutputReportByteLength 2 unsigned short FeatureReportByteLength 0 unsigned short Reserved ... unsigned short [17] NumberLinkCollectionNodes 1 unsigned short NumberInputButtonCaps 1 unsigned short NumberInputValueCaps 1 unsigned short NumberInputDataIndices 4 unsigned short NumberOutputButtonCaps 1 unsigned short NumberOutputValueCaps 0 unsigned short NumberOutputDataIndices 1 unsigned short NumberFeatureButtonCaps 0 unsigned short NumberFeatureValueCaps 0 unsigned short NumberFeatureDataIndices 0 unsigned shortSo sehen meine Capabilities aus.
Woher weiss ich denn jetzt, was ich per WriteFile senden muss, um eine LED einzuschalten ?
Über eure Hilfe würde ich mich sehr freuen.
Grüße Nils
PS: http://www.c-plusplus.net/forum/viewtopic.php?t=54095&start=0
Diesen Thread hab ich gefunden, aber er hat mich leider nur bis zu diesem Punkt, an dem ich jetzt stehe geführt.
-
Ich würde mal sagen, die Ansteuerung der LEDs hängt vom Board ab, nicht von Deinem Programm. Wie man die LEDs schaltet, läßt sich meist aus dem Schaltplan ersehen.
-
Hmmm ... hab gedacht irgendwie muss man sich die Reports besorgen und da kann man dass dann auslesen. Die Software, die dabei war gibt nur an, das als Output (LED) eine acht Bit Zahl rausgeht.
Das es mit dem Schaltplan zusammenhängt glaube ich eher nicht, denke eher dass der Controller auf dem Board die Daten dann umsetzt, so wie er sie empfängt.
-
Nils_Langner schrieb:
Hmmm ... hab gedacht irgendwie muss man sich die Reports besorgen und da kann man dass dann auslesen. Die Software, die dabei war gibt nur an, das als Output (LED) eine acht Bit Zahl rausgeht.
Das es mit dem Schaltplan zusammenhängt glaube ich eher nicht, denke eher dass der Controller auf dem Board die Daten dann umsetzt, so wie er sie empfängt.
So wirds wohl sein also lies dir die Doku durch, da dir keiner helfen kann wenn du nur sagst du hast ein board. Damit kann man ja nichts anfangen, da das Komunizieren i.d.R auf das Board ankommt.
-
Das Schreiben kann nicht schwer sein, denn Dein Output-Report besteht doch nur aus zwei Byte. Da sollten sich die 8 Bits für die LEDs schnell ausfindig machen lassen. Also einfach schnell mal drei Bytes reservieren, das erste Byte nullen und mit den restlichen zwei Bytes experimentieren.
Du kannst Dir natürlich auch die eine vorhandene HIDP_BUTTON_CAPS-Struktur genauer ansehen.

Das Lesen ist sicherlich auch nicht weiter wild. Du besorgst Dir einfach 6 Bytes an Speicher, nullst das erste Byte und rufst ReadFile auf. Zack, hast Du schon einen fertigen Report.
-
@topzel:
sorry aber in der boardbeschreibung steht sowas nicht dabei. meine c kenntnisse sind noch nicht so ausgeprägt, dass ich den code auf dem microcontroller lesen könnte.
also wenn es was hilft: KEIL MCB2140 Board mit einem LPC2418 Arm Controller.
ich werde mal versuchen mir die HIDP_BUTTON_CAPS-Struktur genauer anzusehen.
-
Nils_Langner schrieb:
Die Software, die dabei war gibt nur an, das als Output (LED) eine acht Bit Zahl rausgeht.
Das es mit dem Schaltplan zusammenhängt glaube ich eher nicht, denke eher dass der Controller auf dem Board die Daten dann umsetzt, so wie er sie empfängt.
Dann wäre es das einfachste, die Software zu entschlüsseln und heruaszufinden, wie die Daten vom Controller übernommen und ausgegeben werden. Dazu muß man C natürlich können (wenn das Programm in C geschrieben ist).
-
Nils_Langner schrieb:
Jetzt würde ich aber gerne mit dem Gerät kommunizieren. Eigenlich müsste es, es hat einen Potentiometer, die ganze Zeit Daten senden, über den Wert des Meters. Wie frage ich diese Daten ab.
Dazu kommt noch, dass das Borad 8 LEDs drauf hat, die ich auch gerne per C++ ein und ausschalten würde.ich schätze mal, das geht irgendwie mit 'ReadFile' und 'WriteFile' aber welches format die daten haben muss irgendwo in der doku zu dem dingens stehen...
-
So ... ich hab mir jetzt ne Funktion gestrickt, die Daten auslesen soll ... Geht auch ganz gut, zumindest bekomme ich mit, wenn die 160 Byte im Buffer voll sind.
unsigned long usbInterface::read( BYTE output[160] ) { unsigned long BytesRead; if ( connected ) { ReadFile( DeviceHandle, output, 160, &BytesRead, NULL ); return BytesRead; } return 0; }Aber irgendwie bekomme ich immer nur das gleiche zurück, auch wenn ich LEDs einschalte, Knöpfe drücke oder am Potenziometer rumspiele.
#define BUFFERSIZE 160 ... BYTE* test = new BYTE[BUFFERSIZE]; unsigned long bytesRead = 0; while ( true ) { bytesRead = myInterface.read( test ); if ( bytesRead == BUFFERSIZE ) { printf( "Möglicher Buffer überlauf \n"); } printf("ReadFile : 0x%X - ", test ); printf("Bytesread: %i \n", bytesRead ); }so rufe ich das ganze auf.
Kann es sein, dass ích gar keine Bytes zurückbekomme, sondern sowas wie wide char Bytes? Habe sowas mal gelesen, bin aber nicht so ganz durchgestiegen. Interpretiert mein C++ vielleicht die führenden Nullen falsch und schneidet deswegen ab?
Ach als Ausgabe bekomme ich:
ReadFile: 0x375F58 - BytesRead 5PS: Wenn jemanand noch einem Anfänger helfen will
... Wie bekomm ich die 160 aus der Buffersize auch in dieusbInterface::read( BYTE output[160] )rein?
-
-
Du bekommst nicht 160 Bytes vom Gerät, sondern lediglich 5 (siehe InputReportByteLength). Das Gerät ist eben so.
-
Wenn Du einen Input-Report haben willst, solltest Du den Buffer nicht "output" nennen. Das versteht sonst kein normal denkender Mensch.
-
Willst Du einen Input-Report erhalten, mußt Du einen Puffer der Größe InputReportByteLength + 1 bereitstellen.
-
Das erste Byte muß vor dem ReadFile-Aufruf von Dir initialisiert werden. Da Du hier nicht mit ReportIDs arbeitest, setzt Du dieses Byte einfach auf 0.
Irgendwie ist mir, als hätte ich das alles schonmal gesagt. Aber ich wiederhole mich gern noch mehrmals.
// Irgendwie in dieser Art unsigned long usbInterface::read(BYTE* input, DWORD cb) { unsigned long BytesRead; if ( connected ) { if(ReadFile( DeviceHandle, input, cb, &BytesRead, NULL )) { return BytesRead; } } return 0; } BYTE* test = new BYTE[caps.InputReportByteLength + 1]; *test = 0; unsigned long bytesRead = 0; while ( true ) { bytesRead = myInterface.read(test, caps.InputReportByteLength + 1); for(unsigned long x = 0; x < bytesRead; ++x) { printf("%02X ", test[x]); } printf("\n"); }
-
-
so, hab noch was im C Code com Controller gefunden, was ich denke Interessant sein könnte:
BYTE InReport[4]; /* HID Input Report */ /* Bit0..2: Buttons */ /* Bit3..7: Reserved */ /* Byte 1..3: Analog value */ BYTE OutReport; /* HID Out Report */ /* Bit0..7: LEDs */ #define LPC2000_ADC_API unsigned int ADC_channel_values[8]; unsigned int ADC_get_channel( unsigned char channel ); /* * Get HID Input Report -> InReport */ void GetInReport (void) { DWORD key; unsigned int iVal; key = IOPIN0; /* Read Pin Data */ InReport[0] = 0x00; InReport[1] = 0x00; // Read analog value iVal = ADC_get_channel(1); InReport[2] = (BYTE) (iVal & 0xFF) ; InReport[3] = (BYTE) (iVal>>8) ; if ((key & S2) == 0) InReport[0] |= 0x01; /* Check if S2 is pressed */ #ifndef MCB2140 if ((key & S3) == 0) InReport[0] |= 0x02; /* Check if S3 is pressed */ if ((key & S4) == 0) InReport[0] |= 0x04; /* Check if S4 is pressed */ #endif } /* * Set HID Output Report <- OutReport */ void SetOutReport (void) { if (OutReport & 0x01) IOSET1 = LED1; else IOCLR1 = LED1; if (OutReport & 0x02) IOSET1 = LED2; else IOCLR1 = LED2; if (OutReport & 0x04) IOSET1 = LED3; else IOCLR1 = LED3; if (OutReport & 0x08) IOSET1 = LED4; else IOCLR1 = LED4; if (OutReport & 0x10) IOSET1 = LED5; else IOCLR1 = LED5; if (OutReport & 0x20) IOSET1 = LED6; else IOCLR1 = LED6; if (OutReport & 0x40) IOSET1 = LED7; else IOCLR1 = LED7; if (OutReport & 0x80) IOSET1 = LED8; else IOCLR1 = LED8; } /* END USER CODE INCLUDE */hoffe ich zumindest. Kann mir da vll jemand helfen es zu interpretieren?
-
Ah, wie ich gerade sehe, kannst Du Dir das "+ 1" sparen. Der Treiber rechnet das Byte für den Report-Identifier gleich in die Gesamtlänge der Reports mit ein. War mir entfallen.
Damit sind dann wohl alle Fragen beantwortet.
-
Ja im Moment sind wiorklich alle fragen behoben, ich bekomme ne schöne Bytefolge zurück, die ich sogar interpretieren kann.
Vielen Dank
-
so, also falls es jemanden interessiert:
unsigned long usbInterface::write( BYTE* output ) { unsigned long BytesWritten; if ( connected ) { WriteFile( DeviceHandle, output, Capabilities.OutputReportByteLength, &BytesWritten, NULL ); return BytesWritten; } return 0; }so sieht meine Funktion aus um Daten zu schreiben und so um sie aufzurufen:
BYTE writeData[] = { 0x00, 0x03 }; myInterface.write( writeData );das ganze schaltet die LED 1 und 3 ein. und das tollste ist, es funktioniert
