2016-06-12 14 views
0

Ich modifizierte serielle Loopback-Code von jemand anderem in C (Codeblocks/Mingw) unter Windows-Plattform geschrieben. Ich kann die Daten korrekt senden. Ich habe dies verifiziert, indem ich die Terminalsoftware geöffnet habe. Aber ich kann die Daten nicht empfangen. Ich erhalte den Fehler der Fehlermeldung, der vom Eingabepuffer 998 für ReadFile() in dem folgenden Code liest. Nicht sicher, was der Fehler ist. Ich verwende zwei CP210x USB zu seriellen Modulen und verbunden TxD zu RxD von einem zum anderen.Nicht in der Lage, serielle Daten zu empfangen

#include <windows.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <commdlg.h> 
//#include <windef.h> 
#include <time.h> 

int nread,nwrite; 

void myDelay(unsigned int mseconds) 
{ 
    clock_t goal = mseconds + clock(); 
    while (goal > clock()); 
} 

int main(int argc, char* argv[]) 
{ 
    HANDLE hSerial; 
    COMMTIMEOUTS timeouts; 
    COMMCONFIG dcbSerialParams; 
    char *words, *buffRead, *buffWrite; 
    DWORD dwBytesWritten, dwBytesRead; 

    if(argc<3) 
    { 
     printf("Enter the com port as command line parameter and t for transmitter and r for receiver\n"); 
     printf("Example: Serial.exe com4 t\n"); 
     return(1); 
    } 
    hSerial = CreateFile(argv[1],GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 

    if (hSerial == INVALID_HANDLE_VALUE) 
    { 
     if (GetLastError() == ERROR_FILE_NOT_FOUND) 
     { 
      printf(" serial port does not exist \n"); 
     } 
     else 
     { 
      printf(" some other error occured\n"); 
     } 

     return(1); 
    } 


    if (!GetCommState(hSerial, &dcbSerialParams.dcb)) 
    { 
     printf("error getting state \n"); 
     return(1); 
    } 

    dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb); 

    // Set various serial port parameters. 

    dcbSerialParams.dcb.BaudRate = CBR_9600; 
    dcbSerialParams.dcb.ByteSize = 8; 
    dcbSerialParams.dcb.StopBits = ONESTOPBIT; 
    dcbSerialParams.dcb.Parity = NOPARITY; 

    dcbSerialParams.dcb.fBinary = TRUE; 
    dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE; 
    dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE; 
    dcbSerialParams.dcb.fOutxCtsFlow = FALSE; 
    dcbSerialParams.dcb.fOutxDsrFlow = FALSE; 
    dcbSerialParams.dcb.fDsrSensitivity= FALSE; 
    dcbSerialParams.dcb.fAbortOnError = TRUE; 

    if (!SetCommState(hSerial, &dcbSerialParams.dcb)) 
    { 
     printf(" error setting serial port state \n"); 
     return(1); 
    } 


    GetCommTimeouts(hSerial,&timeouts); 
    timeouts.ReadIntervalTimeout = 50; 
    timeouts.ReadTotalTimeoutConstant = 50; 
    timeouts.ReadTotalTimeoutMultiplier = 10; 
    timeouts.WriteTotalTimeoutConstant = 50; 
    timeouts.WriteTotalTimeoutMultiplier= 10; 

    if(!SetCommTimeouts(hSerial, &timeouts)) 
    { 
     printf("error setting port state \n"); 
     return(1); 
    } 

    while(1) 
    { 
     // Use a delay of 500 msec 
     myDelay(500); 
     if(!strcmp(argv[2],"t")) 
     { 

      printf("Write Mode\n"); 
      //****************Write Operation*********************// 
      words = "This is a string to be written to serial port COM1"; 
      nwrite = strlen(words); 

      buffWrite = words; 
      dwBytesWritten = 0; 

      if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL)) 
      { 
       printf("error writing to output buffer \n"); 
       return(1); 
      } 

     } 


//***************Read Operation******************// 

     else 
     { 
      dwBytesRead = 0; 
      nread = strlen(words); 

      if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL)) 
      { 
       printf("error reading from input buffer %d\n", GetLastError()); 
       continue; 
      } 
      printf("Data read from read buffer is \n %s \n",buffRead); 

     } 
    } 
    CloseHandle(hSerial); 
    return(0); 

} 
+1

Fehler 998 ist ERROR_NOACCESS „Unzulässiger Zugriff auf Speicherstelle“. Informiert Sie mit 100% Sicherheit, dass Sie einen schlechten Zeiger auf ReadFile() übergeben. Sie sind, Sie initialisierten nie * buffRead *. Eine viel bessere Deklaration ist 'BYTE buffRead [4096];' Und übergeben Sie einen korrekten Wert für die Puffergröße, die 4096 sein wird. Die printf() -Anweisung ist ebenfalls falsch, Sie erhalten keine ordnungsgemäß nullterminierte Zeichenkette. –

+0

gearbeitet. Habe nicht bemerkt, dass Speicher nicht zugewiesen ist. Wenn Sie dies als Antwort schreiben, kann ich dies als Antwort markieren. Jetzt funktioniert es für mich. Auch einige Änderungen, die ich im Empfangsbereich gemacht habe, um eine Müllanzeige zu vermeiden. Einige weitere Änderungen, die ich als Teil der Sanierung Code tun ' else { if (dwBytesRead) { for (count = 0; count Rajesh

Antwort

0

Lesen und Schreiben zu COM-Port einander machen Ihre Lektüre fast alle Tage Timeout blockiert, wenn der FIFO-Speicher abläuft. Es könnte auch einige Daten in den FIFOs geben, also ... Wenn Sie zu große Datenmengen senden und empfangen, ist der Datenverlust auf diese Weise wahrscheinlicher.

Hier kleines altes Beispiel für nicht Gewinde COM-Port-Zugriff

//--------------------------------------------------------------------------- 
//--- port class ver: 1.0 ------------------------------------------------ 
//--------------------------------------------------------------------------- 
#ifndef _port_h 
#define _port_h 
//--------------------------------------------------------------------------- 
class port 
     { 
public: HANDLE  hnd; 
     AnsiString error; 
     DWORD  rlen,wlen,err; 
     DCB   rs232_state; 
     COMMPROP  properties; 
     COMMTIMEOUTS timeouts; 
     COMSTAT  stat; 
     port(); 
     ~port(); 
     int open(AnsiString name); 
     void close(); 
     int get_stat();  // err,stat 
     int get_timeouts(); // timeouts 
     int set_timeouts(); 
     int get_properties(); // properties 
     int get_rs232_state(); // rs232_state 
     int set_rs232_state(); 
     void rst_rs232_state(); 
     void out(BYTE data) { WriteFile(hnd,&data,1,&wlen,NULL); } 
     void in (BYTE *data) { ReadFile (hnd, data,1,&rlen,NULL); } 
     void in (char *data) { ReadFile (hnd, data,1,&rlen,NULL); } 
     void out(BYTE *data,DWORD len) { WriteFile(hnd,data,len,&wlen,NULL); } 
     void in (BYTE *data,DWORD len) { ReadFile (hnd,data,len,&rlen,NULL); } 
     }; 
//--------------------------------------------------------------------------- 
port::port() 
     { 
     rlen=0; 
     wlen=0; 
     err =0; 
     error=""; 
     hnd=NULL; 
     rst_rs232_state(); 
     } 
//--------------------------------------------------------------------------- 
port::~port() 
     { 
     close(); 
     } 
//--------------------------------------------------------------------------- 
int port::open(AnsiString name) 
     { 
     close(); 
     rlen=0; 
     wlen=0; 
     hnd=CreateFile(name.c_str(),GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,NULL); 
     if (hnd==NULL) return 0; 
     get_timeouts(); 
     get_properties(); 
     get_rs232_state(); 

     timeouts.ReadIntervalTimeout; 
     timeouts.ReadTotalTimeoutMultiplier; 
     timeouts.ReadTotalTimeoutConstant; 
     timeouts.WriteTotalTimeoutMultiplier; 
     timeouts.WriteTotalTimeoutConstant; 

     properties.wPacketLength; 
     properties.wPacketVersion; 
     properties.dwServiceMask; 
     properties.dwReserved1; 
     properties.dwMaxTxQueue; 
     properties.dwMaxRxQueue; 
     properties.dwMaxBaud; 
     properties.dwProvSubType; 
     properties.dwProvCapabilities; 
     properties.dwSettableParams; 
     properties.dwSettableBaud; 
     properties.wSettableData; 
     properties.wSettableStopParity; 
     properties.dwCurrentTxQueue; 
     properties.dwCurrentRxQueue; 
     properties.dwProvSpec1; 
     properties.dwProvSpec2; 
     properties.wcProvChar[1]; 

     return 1; 
     } 
//--------------------------------------------------------------------------- 
void port::close() 
     { 
     if (hnd==NULL) return; 
     CloseHandle(hnd); 
     hnd=NULL; 
     } 
//--------------------------------------------------------------------------- 
int port::get_stat() 
     { 
     if (ClearCommError(hnd,&err,&stat)) return 1; 
     error=GetLastError(); 
     return 0; 
     } 
//--------------------------------------------------------------------------- 
int port::get_timeouts() 
     { 
     if (GetCommTimeouts(hnd,&timeouts)) return 1; 
     error=GetLastError(); 
     get_stat(); 
     return 0; 
     } 
//--------------------------------------------------------------------------- 
int port::set_timeouts() 
     { 
     if (SetCommTimeouts(hnd,&timeouts)) return 1; 
     error=GetLastError(); 
     get_stat(); 
     return 0; 
     } 
//--------------------------------------------------------------------------- 
int port::get_properties() 
     { 
     if (GetCommProperties(hnd,&properties)) return 1; 
     error=GetLastError(); 
     get_stat(); 
     return 0; 
     } 
//--------------------------------------------------------------------------- 
int port::get_rs232_state() 
     { 
     if (GetCommState(hnd,&rs232_state)) return 1; 
     error=GetLastError(); 
     get_stat(); 
     return 0; 
     } 
//--------------------------------------------------------------------------- 
int port::set_rs232_state() 
     { 
     if (SetCommState(hnd,&rs232_state)) return 1; 
     error=GetLastError(); 
     get_stat(); 
     return 0; 
     } 
//--------------------------------------------------------------------------- 
void port::rst_rs232_state() 
     { 
     rs232_state.BaudRate = CBR_9600; 
     rs232_state.ByteSize = 8; 
     rs232_state.Parity  = NOPARITY; 
     rs232_state.StopBits = ONESTOPBIT; 
     rs232_state.fOutxCtsFlow= FALSE; 
     rs232_state.fOutxDsrFlow= FALSE; 
     rs232_state.fOutX  = FALSE; 
     rs232_state.fInX  = FALSE; 
     rs232_state.fBinary  = FALSE; 
     rs232_state.fRtsControl = RTS_CONTROL_DISABLE; 
     } 
//---------------------------------------------------------------------------//--------------------------------------------------------------------------- 
//---------------------------------------------------------------------------//--------------------------------------------------------------------------- 
//--------------------------------------------------------------------------- 
#endif 
//--------------------------------------------------------------------------- 

Es ist in C++/VCL so umschreiben nur AnsiString-char* oder jeden String-Typen Sie bekommen und auch die Datei-Routinen zu Ihnen ändern. Wenn Sie keinen Zugriff auf Klassen haben, überschreiben Sie C. Die Verwendung ist einfach:

Sie sollten Threads verwenden, um dies zu beheben, da ohne die Threads die Kommunikation blockiert. Wie dem auch sei, ohne Gewinde für Loop-Back sollten Sie:

  1. Satz beide COM-Ports auf dem gleichen Protokoll
  2. immer zuerst, dann senden erhalten
  3. Set klein genug Timeout (nicht zu lange zu blockieren)
  4. erwarten Datenverlust und Timeouts (und behandeln als solche ... nicht blockieren, indem sie das senden)
  5. senden nur BYTES nicht alle COM-Ports haben große FIFOs auf dem Weg ...

Um sicherer machen das Lesen Innengewinde zu sein ... wie:

volatile bool _stop=false; // set this to true when you want to exit 
unsigned long __stdcall thread_com(LPVOID p) 
     { 
     char q; 
     for (;!_stop;) 
     { 
     com.in (&q); // recv ... 
     if (q<32) q=`.`; // data loss due to timeout if not sending `0..31` of coarse 
     Sleep(1); // just not to burn CPU ... 
     } 
     } 

HANDLE thread_com_hnd=CreateThread(0,0,thread_com,NULL,0,0); // do this only after COM port is initialized 
+0

Ich war auf der Suche nach sehr einfachen C-Code für empfangen/senden und ich bin nicht vertraut mit Threading usw. Dieser Code war hauptsächlich für Verständnis Zweck. Trotzdem werde ich das im Hinterkopf behalten, falls ich weitere Änderungen anwende. – Rajesh