logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

RS232 w C++: Problem z funkcją WriteFile() w aplikacji terminala COM

zbigel 12 Mar 2008 19:07 2373 2
REKLAMA
  • #1 4901461
    zbigel
    Poziom 12  
    Posty: 82
    Pomógł: 6
    Ocena: 11
    Witam. Chce stworzyć aplikację która będzie działała jak terminal portu COM, czyli możliwe będzie wysyłanie i odbieranie danych. Stworzyłem taki program (kod zamieszczam poniżej). Odbiór i nadawanie umieszczone są w oddzielnych wątkach. Problem jest taki, że po uruchomieniu programu odbiór znaków (danych) działa poprawnie, natomiast nadawanie nie działa w ogóle. Wygląda to tak jakby funkcja WriteFile() zawieszała się. Dodam jeszcze, że kiedy wykomentuje linię WaitCommEvent() w wątku odbioru to wtedy wszystko jest ok (no oczywiście poza tym że cały czas wywoływana jest funkcja WriteFile()). Czy ktoś wie w czym może być problem.
    Pozdrawiam.


    #include <windows.h> 
    #include <stdio.h> 
    #include <iostream.h>
    #include <conio.h>
    
    
    
    //////////////////////////////////////////////////////////////////////
    DWORD WINAPI watek1(PVOID hCom){
    
    	cout<<"Watek1"<<endl<<flush;
    	
    	
    		BOOL fSuccess; 
    		DWORD eventMask,error,ilosc;
    		eventMask=EV_RXCHAR;
    		COMSTAT stats;
    		
    		char znaki[20];
    
    		SetCommMask(hCom,eventMask);
    	
     while(znaki[0]!='q') 
       {  
    		
    		WaitCommEvent(hCom,&eventMask,NULL);
    		ClearCommError(hCom,&error,&stats);
    		cout<<"Bufor:"<<stats.cbInQue<<endl<<flush;
            fSuccess = ReadFile( hCom, znaki, stats.cbInQue, &ilosc, 0); 
    		*(znaki+ilosc)=NULL;
            if (!fSuccess) 
            { 
                printf ("ReadFile failed with error %d.\n", GetLastError()); 
                return 5; 
            } 
           
    		cout<<znaki<<endl<<flush;    
       } 
    
     cout<<"Koniec watku 1"<<endl;
    	return 0;
    }
    
    
    
    /////////////////////////////////////////////////////////////////////////////
    DWORD WINAPI watek2(PVOID hCom){
    
    	cout<<"Watek2"<<endl<<flush;
    
    
    		BOOL fSuccess; 
    		char znak='w';
    		DWORD ilosc;
    		
    
       while (znak!='q'){
    	   znak=getch();
    	   cout<<znak<<endl;
    	
    	fSuccess = WriteFile( hCom, &znak, 1, &ilosc, 0);
    	if (!fSuccess) 
       { 
          printf ("SetCommState failed with error %d.\n", GetLastError()); 
          return 3; 
       }
    	
       }
    
    
    cout<<"Koniec watku 2"<<endl;
    
    	return 0;
    }
    
    
    
    
    ////////////////////////////////////////////////////////////////////////////////
    int main() 
    { 
    	
        HANDLE hCom;      //uchwyt portu 
        DCB dcb;         //konfiguracja portu 
        BOOL fSuccess;      //flaga pomocnicza 
        
       //otwarcie portu COM1 z prawami RW 
        hCom = CreateFile( TEXT("COM2"), GENERIC_READ | GENERIC_WRITE, 
            0,    // exclusive access 
            NULL, // default security attributes 
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
        
        if (hCom == INVALID_HANDLE_VALUE) 
        { 
            printf("CreateFile failed with error %d.\n", GetLastError()); 
            return 1; 
        } 
    
       //pobranie aktualnych ustawien portu 
        fSuccess = GetCommState(hCom, &dcb); 
        if (!fSuccess) 
        { 
          printf ("GetCommState failed with error %d.\n", GetLastError()); 
          return 2; 
        } 
        
       //ustawienie naszej konfiguracji 
       dcb.BaudRate = CBR_9600;     // predkosc transmisji 
       dcb.ByteSize = 8;             // ilosc bitow danych 
       dcb.Parity = NOPARITY;        // brak bitu parzystosci 
       dcb.StopBits = ONESTOPBIT;    // dwa bity stopu 
    
    	dcb.fDtrControl = DTR_CONTROL_ENABLE; 
    
        dcb.fRtsControl = RTS_CONTROL_DISABLE; 
    
       fSuccess = SetCommState(hCom, &dcb); 
    
       if (!fSuccess) 
       { 
          printf ("SetCommState failed with error %d.\n", GetLastError()); 
          return 3; 
       }
     //////////////////////////////////////////////////////////////////////  
    
      
    
    
    	DWORD watek1_id,watek2_id;
    	HANDLE w1,w2;
    
    w1=CreateThread(NULL,0,watek1,(PVOID)hCom,0,&watek1_id);
    w2=CreateThread(NULL,0,watek2,(PVOID)hCom,0,&watek2_id);
    
    
    WaitForSingleObject(w1,INFINITE);
    WaitForSingleObject(w2,INFINITE);
    
    CloseHandle(w1);
    CloseHandle(w2);
    
      CloseHandle(hCom);
       return 0; 
    }


    Kod proszę umieszczać w znacznikach code - krzychoocpp
  • REKLAMA
  • #2 4902726
    x3r
    Poziom 18  
    Posty: 126
    Pomógł: 32
    Ocena: 2
    Z reguły operacji we/wy na porcie szeregowym (i nie tylko) nie wykonuje się równolegle. Poczytaj na google o event driven serial communication (celowo napisałem po angielsku bo znajdziesz w tym języku więcej źródeł). Jak oprzesz implementację o model zdarzeniowy program będzie na pewno dużo wydajniejszy i z pewnością poprawny.

    pozdrawiam
  • #3 4907357
    zbigel
    Poziom 12  
    Posty: 82
    Pomógł: 6
    Ocena: 11
    Witam.
    No faktycznie operacji wej/wyj nie robi się równolegle. Rozwiązałem ten problem przez włączenie funkcji nakładanego wejścia i wyjścia (OVERLAPPED). Poniżej zamieszczam kod. Nie jest on elegancki zresztą jak poprzedni, ale są to wersje robocze:D
    Pomogła mi stronka
    http://home.elka.pw.edu.pl/~jszewins/index.php
    zakładk hobby, a dalej programowanie RS232

    
    
    #include <windows.h> 
    #include <stdio.h> 
    #include <iostream.h>
    #include <conio.h>
    
    
    
    //////////////////////////////////////////////////////////////////////
    DWORD WINAPI watek1(PVOID hCom){
    
    	cout<<"Watek1"<<endl<<flush;
    	
    	
    		BOOL fSuccess; 
    		DWORD eventMask,error,ilosc;
    		COMSTAT stats;
    		OVERLAPPED ovrlap;
    		char znaki[20];
    		
    		memset(&ovrlap,0,sizeof(OVERLAPPED));
    		ovrlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    
    		GetCommMask(hCom,&eventMask);
    		eventMask|=EV_RXCHAR;
    		SetCommMask(hCom,eventMask);
    	
     while(znaki[0]!='q')
       {  
    		WaitCommEvent(hCom,&eventMask,&ovrlap);
    		WaitForSingleObject(ovrlap.hEvent, INFINITE);
    		if (!(eventMask&&EV_RXCHAR)) continue;
    		ClearCommError(hCom,&error,&stats);
    		cout<<"Bufor:"<<stats.cbInQue<<endl<<flush;
            fSuccess = ReadFile( hCom, znaki, stats.cbInQue, &ilosc, &ovrlap); 
    		*(znaki+ilosc)=NULL;
            if (!fSuccess) 
            { 
                printf ("ReadFile failed with error %d.\n", GetLastError()); 
                return 5; 
            } 
    
    		cout<<znaki<<endl<<flush;    
       } 
    
     cout<<"Koniec watku 1"<<endl;
    	return 0;
    }
    
    
    
    /////////////////////////////////////////////////////////////////////////////
    DWORD WINAPI watek2(PVOID hCom){
    
    	cout<<"Watek2"<<endl<<flush;
    
    
    		BOOL fSuccess; 
    		char znk='w';
    		DWORD ilosc;
    		OVERLAPPED ovrlap;
    
    		memset(&ovrlap,0,sizeof(OVERLAPPED));
    		ovrlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    		
       while (znk!='q'){
    	   znk=getch();
    	   cout<<znk<<endl;
    	
    	fSuccess = WriteFile( hCom, &znk, 1, &ilosc, &ovrlap);
    	WaitForSingleObject(ovrlap.hEvent, INFINITE);
    
    	
       }
    cout<<"Koniec watku 2"<<endl;
    
    	return 0;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    int main() 
    { 
    	
        HANDLE hCom;      //uchwyt portu 
        DCB dcb;         //konfiguracja portu 
        BOOL fSuccess;      //flaga pomocnicza 
        
       //otwarcie portu COM1 z prawami RW 
        hCom = CreateFile( TEXT("COM2"), GENERIC_READ | GENERIC_WRITE, 
            0,    // exclusive access 
            NULL, // default security attributes 
            OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 
        
        if (hCom == INVALID_HANDLE_VALUE) 
        { 
            printf("CreateFile failed with error %d.\n", GetLastError()); 
            return 1; 
        } 
    
       //pobranie aktualnych ustawien portu 
        fSuccess = GetCommState(hCom, &dcb); 
        if (!fSuccess) 
        { 
          printf ("GetCommState failed with error %d.\n", GetLastError()); 
          return 2; 
        } 
        
       //ustawienie naszej konfiguracji 
       dcb.BaudRate = CBR_9600;     // predkosc transmisji 
       dcb.ByteSize = 8;             // ilosc bitow danych 
       dcb.Parity = NOPARITY;        // brak bitu parzystosci 
       dcb.StopBits = ONESTOPBIT;    // dwa bity stopu 
    
    	dcb.fDtrControl = DTR_CONTROL_ENABLE; 
    
        dcb.fRtsControl = RTS_CONTROL_DISABLE; 
    
       fSuccess = SetCommState(hCom, &dcb); 
    
       if (!fSuccess) 
       { 
          printf ("SetCommState failed with error %d.\n", GetLastError()); 
          return 3; 
       }
     //////////////////////////////////////////////////////////////////////  
    
      
    
    
    	DWORD watek1_id,watek2_id,watek3_id;
    	HANDLE w1,w2,w3;
    
    w1=CreateThread(NULL,0,watek1,(PVOID)hCom,0,&watek1_id);
    w2=CreateThread(NULL,0,watek2,(PVOID)hCom,0,&watek2_id);
    }
    
    
    
    WaitForSingleObject(w1,INFINITE);
    WaitForSingleObject(w2,INFINITE);
    
    CloseHandle(w1);
    CloseHandle(w2);
    
    
     CloseHandle(hCom);
      return 0; 
    } 
    
    
REKLAMA