Fehlersuche: serielle schnittstelle nur auslesen
-
Hallo1
Ich weiß nicht mehr weiter, ich möchte Daten, die von einem Datenlogger an die serielle Schnittstelle gesendet werden, aufnehmen. Mein Programmcode zeigt aber wieder mal Fehler anb und ich weiß nicht wo der Haken liegt. Vielleicht kann mir ja jemand dabei helfen. Vielen Dank.
Hier der Code von mir:#include <windows.h>
int main (void)
{
DCB dcb;
DWORD iBytesReceived;
int nRead;
unsigned char bBuffer[1000];HANDLE hCom = CreateFile ("COM1", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING,
0, NULL);dcb.DCBlength = sizeof(DCB); // Laenge des Blockes MUSS gesetzt sein!
GetCommState (hCom, &dcb); // COM-Einstellungen holen und aendern
dcb.BaudRate = 9600; // Baudrate
dcb.ByteSize = 8; // Datenbits
dcb.Parity = NOPARITY; // Parität
dcb.StopBits = ONESTOPBIT; // Stopbits
SetCommState (hCom, &dcb); // COM-Einstellungen speichernnRead = 1;
ReadFile (hCom, &bBuffer, nRead, &iBytesReceived, NULL);CloseHandle (hCom); // COM1 schließen
return (0);
}
-
Benutze bitte die C++ Tags, damit man deinen Code auch lesen kann.
#include <windows.h> int main (void) { DCB dcb; DWORD iBytesReceived; int nRead; unsigned char bBuffer[1000]; HANDLE hCom = CreateFile ("COM1", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); dcb.DCBlength = sizeof(DCB); // Laenge des Blockes MUSS gesetzt sein! GetCommState (hCom, &dcb); // COM-Einstellungen holen und aendern dcb.BaudRate = 9600; // Baudrate dcb.ByteSize = 8; // Datenbits dcb.Parity = NOPARITY; // Parität dcb.StopBits = ONESTOPBIT; // Stopbits SetCommState (hCom, &dcb); // COM-Einstellungen speichern nRead = 1; ReadFile (hCom, &bBuffer, nRead, &iBytesReceived, NULL); CloseHandle (hCom); // COM1 schließen return (0); }Schon viel besser, gell?
-
dieses Code-Schnipsel war nur fürs Senden geeignet, einfach WriteFile durch ReadFile (und die paar Parameter) ersetzten, geht nicht. Senden geht ja zu jedem Zeitpunkt, beim Empfangen muß man WARTEN. Du wartest nicht, sondern versuchst, ein Zeichen auszulesen und beendest das Programm. Hier ist das passende Empfangsprogramm zu dem von Dir veränderten Beispiel:
// DOS32-Programm zum Senden/Empfangen von Bytes über COM (9600-8N1) // Alle empfangenen Bytes werden zurückgesendet. // OS: W95, W98, W98SE, WinME, WinNT, Win2000, WinXP // Note: Keine Fehlerbehandlung implementiert! #include <windows.h> #include <stdio.h> #define COM_BUFFER_SIZE 256 // Read- und Write-Buffer-Size #define BD_RATE CBR_9600 // 9600 Baud #define HELP_STRING TEXT("Aufruf mit: progname <COM-Port-Nummer>\r\n") // Hauptprogramm: Aufruf mit: progname <COM-Port-Nummer> int main (int argc, char **argv) { DCB dcb; DWORD iBytesWritten; BOOL bRet = true; DWORD dwRead = 0; DWORD dwSetMask = EV_RXCHAR | EV_ERR; DWORD dwEvtMask; OVERLAPPED o; COMMTIMEOUTS ct; unsigned char InString[COM_BUFFER_SIZE + 1]; TCHAR szCOM[6]; if (argc == 2 && // progname + COM-Port-Nummer ? atoi (argv[1]) > 0 && atoi (argv[1]) < 5) // COM1 ... COM4? wsprintf (szCOM, TEXT("COM%s"), argv[1]); // String "basteln" ... else { printf (TEXT("\r\nERROR:\t %s"), HELP_STRING); return (1); // und tschüß ... } memset (&o, 0, sizeof (OVERLAPPED)); // Struktur mit 0en füllen o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // einen Event setzten HANDLE hCom = CreateFile (szCOM, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hCom == INVALID_HANDLE_VALUE) { // Fehlerausgabe: LPVOID lpMsgBuf; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: CreateFile", MB_OK | MB_ICONINFORMATION); LocalFree (lpMsgBuf); return (1); // und tschüß ... } dcb.DCBlength = sizeof(DCB); // Laenge des Blockes MUSS gesetzt sein! GetCommState (hCom, &dcb); // COM-Einstellungen holen und aendern dcb.BaudRate = BD_RATE; // Baudrate dcb.ByteSize = 8; // Datenbits dcb.Parity = NOPARITY; // Parität dcb.StopBits = ONESTOPBIT; // Stopbits SetCommState (hCom, &dcb); // COM-Einstellungen speichern GetCommTimeouts (hCom, &ct); // Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächsten Bytes ct.ReadIntervalTimeout = 1000 / BD_RATE * (dcb.ByteSize + (dcb.Parity == NOPARITY ? 0 : 1) + (dcb.StopBits == ONESTOPBIT ? 1 : 2)) * 2; ct.ReadTotalTimeoutMultiplier = 0; // [ms] wird mit Read-Buffer-Size multipliziert ct.ReadTotalTimeoutConstant = 50; // wird an ReadTotalTimeoutMultiplier angehängt ct.WriteTotalTimeoutMultiplier = 0; ct.WriteTotalTimeoutConstant = 0; SetCommTimeouts (hCom, &ct); // Zwischenspeicher des serial-Drivers einstellen (für read und write): SetupComm (hCom, COM_BUFFER_SIZE, COM_BUFFER_SIZE); SetCommMask (hCom, dwSetMask); // Empfangssignale definieren do // in Endlos-Schleife auf Empfangssignale warten: { WaitCommEvent (hCom, &dwEvtMask, &o); // Event mit Empfangssignalen verknüpfen if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event { if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen: { bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead, NULL); if (!bRet) { // Fehlerausgabe: LPVOID lpMsgBuf; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: ReadFile", MB_OK | MB_ICONINFORMATION); LocalFree (lpMsgBuf); } else { // Ausgabe (oder Verarbeitung) der empfangenen Bytes: InString[dwRead] = '\0'; // in "zero-ended"-String verwandeln printf (TEXT("\r\n\tRxD (%d Byte(s)): %s"), dwRead, InString); WriteFile (hCom, &InString, dwRead, &iBytesWritten, NULL); // Senden der Bytes } } if (dwEvtMask & EV_ERR) { MessageBox (NULL, "Error empfangen", "Error: ReadFile", MB_OK); break; // Schleifen-Abbruch } } } while (1); CloseHandle (hCom); // COM schließen CloseHandle (o.hEvent); // Event-Handle zurückgeben return (0); }Das Zurücksenden kannst Du ja durch Speichern o.ä. ersetzten.
Blackbird
PS: Marc++us, was ist denn mit den Userdaten passiert?
-
Danke erst mal für die Fehlerbeseitigungen!
Aber wie wird es gemacht, damit sich kein DOS-Fenster öffnet, sondern ein Windows-Fenster, wo dann die eingelesenen Werte dastehen? Da bin ich total unkundig drin. Ich weiß, dass wenn ich eine WIN32-Anwendung erstelle und dort die Einstellung "MFC in einer gemeinsam genutzten DLL verwenden" vornehme, dann die Windows-Fenster erzeugen kann, aber dann hört es auch schon auf.mfg portfan (oder auch nicht fan)
-
MFC? Dann wäre das hier das falsche Board.
Außerdem ist das ja in Deiner Eingangsfrage so nicht rauszulesen gewesen.Mit VC++6.0:
- einfach ein Projekt mit "WIN32_Anwendung" erstellen,
- eine WinMain-Funktion einbauen, die eine Callback-Funktion hat,
- die Callback-Funktion schreiben,
- ein Edit-Fenster erstellen,
- einen COM-Read-Thread schreiben und alle Zeichen an das Edit-Fenster senden.In der MSDN gibt es zu allen schon Beispiele, kombinieren mußt Du es dann so, wie Du es brauchst.
Aber das hat fast alles nichts mit serieller Communications zu tun.
Blackbird