Hallo zusammen, ich habe ein Programm in C++ erstellt, welches Daten zum Mikrocontroller sendet und von dort empfängt. Leider funktioniert es nicht so wie es soll. Auf dem Controller läuft ein Beispielprogramm von Atmel. Ich habe ReadFile und die WriteFile in eine Schleife gesetzt. Wie muss ich szBuff belegen(WriteFile), muss es ein ASCii-Wert sein? Woher weiß ich, das ein Wert auf dem Controller ankommt? Wieso funktioniert das Programm nicht? Hier das Programm: #include "stdafx.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "windows.h" int i = 1; HANDLE hSerial; COMMTIMEOUTS timeouts; DCB dcbSerialParams; char szBuff[4096]; DWORD dwBytesRead; DWORD dwBytesWrite; int n = 4096; int _tmain(int argc, _TCHAR* argv[]) { hSerial = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(hSerial==INVALID_HANDLE_VALUE){ if(GetLastError()==ERROR_FILE_NOT_FOUND){ //serial port does not exist. Inform user. printf("Serial Port does not exist!\n"); } //some other error occurred. Inform user. printf("Some other error occurred!\n"); } ////////////////////////////// if (!GetCommState(hSerial, &dcbSerialParams)) { //error getting state } dcbSerialParams.BaudRate=CBR_9600; dcbSerialParams.ByteSize=8; dcbSerialParams.StopBits=ONESTOPBIT; dcbSerialParams.Parity=NOPARITY; if(!SetCommState(hSerial, &dcbSerialParams)){ //error setting serial port state } /////////////////////////////// timeouts.ReadIntervalTimeout=50; timeouts.ReadTotalTimeoutConstant=50; timeouts.ReadTotalTimeoutMultiplier=10; timeouts.WriteTotalTimeoutConstant=50; timeouts.WriteTotalTimeoutMultiplier=10; if(!SetCommTimeouts(hSerial, &timeouts)){ //error occureed. Inform user printf("Timeout!!\n"); } ////////////////////////////////// while(i = 10000) { if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL)){ //error occurred. Report to user. printf("Error by readfile!!\n"); } //////////////////////////////// if(!WriteFile(hSerial, szBuff, n, &dwBytesWrite, NULL)){ //error occurred. Report to user. printf("Error by writefile!!\n"); } } /////////////////////////////// CloseHandle(hSerial); //////////////////////////////// system("pause"); return 0; } Vielen Dank für eure Hilfe. Grüße datatom
Hallo, z.B. weil i = 1 ist und daher die Befehle nach while garnicht ausgeführt werden. Ohne Anspruch auf Vollständigkeit. Gruss Reinhard
> Auf dem Controller läuft ein Beispielprogramm von Atmel.
Danke, für die Info. Soooo genau wollte ich es gar nicht wissen.
Ansonsten:
- Das Programm ist miserabel formatiert und nicht in [c]-Tags gesetzt
- Es steht nirgends, was es tun soll und woran du siehst, daß
es sich falsch verhält.
Aus einem offensichtlich falschen Programm das heraus zu lesen,
was sich jemand dabei gedacht haben könnte, ist ziemlich
sinnlos.
- Compilerwarnungen wurden offenbar ignoriert
- Fehlermeldungen werden mies ausgegeben (statt "Error by
writefile!!\n" könnte man die Fehlerbeschreibung holen, dann
müsste man hier nicht raten)
Soweit reicht es mir schon, nicht weiter lesen zu wollen.
Klaus Wachtler schrieb:
> wieso ist i 1? Es wird doch auf 1000 gesetzt...
Sorry, war in Pascal gedacht, aber richtig wird es dadurch auch nicht.
Gruss Reinhard
Stimmt, besser wird es auch nicht. Wäre i==10000 gemeint, würde das Programm auch keinen Sinn machen. Mit i<10000 auch nicht, wenn das Inkrementieren fehlt.
Hi Thomas Meine Vorredner haben ja schon mal ein paar Hinweise betreffend der Struktur und Lesbarkeit gegeben. Auch ein Hinweis auf ein Beispielprogramm muß nicht mehr beackert werden. Daher mal etwas zur Sache: Zuerst, damit ich weiß, die Kommunikation läuft, brauch ich eine Möglichkeit, dies zu testen. 2. PC und entsprechendes Programm oder wenn's bereits eine Kommunikation mit einem µC gibt, diese wieder hervorkramen oder die brutale Tour mit Brücke von TX nach RX. Auf dem µC sendest du im Polling, Empfangen in einer ISR. Damit habe ich gute Erfahrungen gemacht. C ist nicht mein Ding, aber das Assemblertutorial hat mir hier sehr geholfen. Für C soll es ja auch eines geben. Da speziell bei hohen Baudraten die Bytes nicht verloren gehen sollten, ist ein Ringpuffer angebracht. Mit einem Doppelregister holst du dir die Basisadresse des Buffers und addierst einen Schreibzeiger drauf. Dorthin speicherst du in der ISR den empfangenen Wert. Anschließend erhöhst du unter Berücksichtigung der Buffergrenze deinen Schreibzeiger oder setzt ihn auf 0. Im Polling, d.h. im laufenden Programm vergleichst du einfach einen Lesezeiger mit Schreibzeiger. Sind diese ungleich, bearbeitest du den Wert, der unter der Basisadresse + Lesezeiger steht, erhöhst den Lesezeiger in gleicher weise wie den Schreibzeiger und gut ist. Die Buffergröße lege ich ca. 2,5mal so hoch an, wie ich Daten hintereinander empfange. Bei knappen Speicher solltest du auch mit 1,5 fachem Wert auskommen. Ach ja, innerhalb einer Programmschleife verzichte auf irgendwelche Warte oder Pausenzeiten...... vielleicht an der ein oder anderen Stelle ein NOP aber alles andere ist nicht nötig. Grueß oldmax
So, ich habe das C++Programm nun geändert. Das mit der Variablen i war eine kleine Unachtsamkeit meinerseits:-) Es ist nun auch formatiert. Die Fehlerbehandlung bleibt erstmal in der einfachen Form, weil es zum Entwickeln so reicht und zum Glück auch keine Syntaxfehler und Warnungen vorhanden sind, siehe im Anhang die Datei Konsole.gif. Ich weiß allerdings auch nicht, wie ich in C++ die Fehlercodes abfragen kann :-( Im Anhang befindet das C-Programm, die Headerdatei und zwei dazugehörige readme-Dateien, was auf dem Controller abläuft. Es ist ein Beispielprogramm von Atmel: AVR®32 AT32UC3 Series Software Framework: USART Driver. http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4192 Der Controller ist ein UC3B (AT32UC3B0256). Zwischen dem Mikrocontroller und dem PC ist ein USB/RS232-Adapter (ATEN UC-232A) und zwei Kabel RxD und TxD, überkreuzt. Ich habe nun folgende Probleme: ReadFile und WriteFile dauern ca. jeweils 30 Sekunden. Warum ist die Verbindung so langsam? Woher weiß ich, dass die Verbindung zwischen PC und Controller funktioniert? Was oldmax im Beitrag vorher geschrieben hat, verstehe ich nicht:-( Wie kann ich, wenn die Verbindung klappt, Daten senden, z.B. die Zahl 64000? Das Controllerprogramm sendet die Daten die kommen, wieder zum PC zurück. Vielen Dank für die Hilfe:-) Grüße Datatom Hier noch einmal das C++Programm // SerielleSchnittstelle.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "windows.h" int i = 1; HANDLE hSerial; COMMTIMEOUTS timeouts; DCB dcbSerialParams; char szBuff[4096]; DWORD dwBytesRead; DWORD dwBytesWrite; int n = 4096; int _tmain(int argc, _TCHAR* argv[]) { hSerial = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(hSerial==INVALID_HANDLE_VALUE) { if(GetLastError()==ERROR_FILE_NOT_FOUND) { //serial port does not exist. Inform user. printf("Fehler bei CreateFile. Serial Port existiert nicht!\n"); } //some other error occurred. Inform user. printf("Fehler bei CreateFile. Sonstiger Fehler!\n"); } else { printf("Kein Fehler bei CreateFile!\n"); } ////////////////////////////// if (!GetCommState(hSerial, &dcbSerialParams)) { //error getting state printf("Fehler bei GetCommState!\n"); } else { printf("Kein Fehler bei GetCommState!\n"); } dcbSerialParams.BaudRate=CBR_9600; dcbSerialParams.ByteSize=8; dcbSerialParams.StopBits=ONESTOPBIT; dcbSerialParams.Parity=NOPARITY; if(!SetCommState(hSerial, &dcbSerialParams)) { //error setting serial port state printf("Fehler bei GetCommState beim Parameter belegen!\n"); } else { printf("Kein Fehler bei GetCommState beim Parameter belegen!\n"); } /////////////////////////////// timeouts.ReadIntervalTimeout=50; timeouts.ReadTotalTimeoutConstant=50; timeouts.ReadTotalTimeoutMultiplier=10; timeouts.WriteTotalTimeoutConstant=50; timeouts.WriteTotalTimeoutMultiplier=10; if(!SetCommTimeouts(hSerial, &timeouts)) { //error occureed. Inform user printf("Fehler bei Timeout!\n"); } else { printf("Kein Fehler bei Timeout!\n"); } ////////////////////////////////// while(i < 10000) { if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL)) { //error occurred. Report to user. printf("Fehler bei ReadFile!\n"); } else { printf ("Kein Fehler bei ReadFile!\n"); } //////////////////////////////// szBuff[0] = 0x02; szBuff[1] = 0x01; szBuff[2] = 0x05; if(!WriteFile(hSerial, szBuff, n, &dwBytesWrite, NULL)) { //error occurred. Report to user. printf("Fehler bei WriteFile!\n"); } else { printf ("Kein Fehler bei WriteFile!\n"); } i++; } /////////////////////////////// CloseHandle(hSerial); //////////////////////////////// system("pause"); return 0; }
Anmerkung zum Screenshot: Der stellt Text dar. Windows kann den Text in die Zwischenablage kopieren, und den Text kann man dann aus der Zwischenablage hier in das Fenster einfügen. Ein Graphikscreenshot ist hier völlig nutzlos. Das Kopieren in die Zwischenablage geht so: Text mit der Maus markieren (lässt er sich nicht markieren, Rechtsklick und im Kontextmenü "markieren" auswählen). Um den markierten Text in die Zwischenablage zu befördern, die Eingabetaste drücken. Desweiteren sollte Dir aufgefallen sein, daß das von Dir hochgeladene Bild sehr viel weißen Rand enthält - ist das Raum für persönliche Anmerkungen? Wenn man Screenshots mit MSPAINT in eine Datei speichern will, vor dem Einfügen aus der Zwischenablage die Bildgröße ("Bildattribute") auf einen sehr kleinen Wert (1x1 reicht) stellen. Beim Einfügen erscheint dann die Frage, ob das auf die Größe der eingefügten Daten vergrößert werden soll. Zur eigentlichen Frage: Den Fehlercode einer fehlgeschlagenen Operation gibt die Win32-API-Funktion GetLastError zurück.
Rufus t. Firefly schrieb: > Zur eigentlichen Frage: > > Den Fehlercode einer fehlgeschlagenen Operation gibt die > Win32-API-Funktion GetLastError zurück. Kleine Ergänzung GetLastError http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx und wie man daraus einen mehr oder weniger aussagekräftigen Text erzeugt: http://msdn.microsoft.com/en-us/library/ms680582(v=VS.85).aspx > ReadFile und WriteFile dauern ca. jeweils 30 Sekunden. Warum ist die > Verbindung so langsam? Welchen Wert hat n beim Empfangen und Senden? http://msdn.microsoft.com/en-us/library/aa363437(VS.85).aspx bzw. http://msdn.microsoft.com/en-us/library/aa363190(v=VS.85).aspx ReadIntervalTimeout gibt an wie viele Millisekunden zw. zwei Bytes vergehen dürfen hier 50 ReadTotalTimeoutMultiplier wird mit der Anzahl der Bytes multipliziert die empfangen werden sollen hier 4096 * 10 dazu wird ReadTotalTimeoutConstant addiert...
Hallo, vielen Dank für die Antworten. Ich habe wegen der Fehlerbehandlung das Beispiel http://msdn.microsoft.com/en-us/library/ms680582%28v=VS.85%29.aspx angewandt. Leider kommt es bei der Zeile MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); zu folgenden Fehler: GetProcessId failed with Error 6: Das Handle ist ungültig. Was bedeutet diese Fehlermeldung? Dann habe ich den Wert n von 4096 auf gesetzt. ReadFile und WriteFile laufen nun wesentlich schneller. Die Frage ist nun, wie niedrig darf der Wert sein, so dass trotzdem alle Bytes gesendet und empfangen werden können?
Das Beispiel erzeugt diesen Fehler, um zu demonstrieren, wie so ein Fehlercode ausgewertet ist. Hast Du überhaupt verstanden, was Du da tun willst?
Ja habe ich. Den Fehler habe ich selber ausgelöst. Ich habe den Controller vom P abgezogen und dann kam der Fehler beim CreateFile. Die Frage hätte ich nicht stellen sollen:-( Jetzt bleibt nur noch die zweite Frage aus dem vorletzten Beitrag: > Dann habe ich den Wert n von 4096 auf 8 gesetzt. ReadFile und WriteFile > laufen nun wesentlich schneller. Die Frage ist nun, wie niedrig darf der > Wert sein, so dass trotzdem alle Bytes gesendet und empfangen werden > können?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.