Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [VC++] Porta seriale e thread

    Ciao a tutti,
    non so se questo è il posto giusto dove postere questo messaggio, se no scusatemi.
    Arrivo subito al punto, sto realizzando un programma con il Microsoft Visual C++ 2008 Express Edition che dialoga con una scheda mediante seriale.
    Dato che non ne sapevo niente di come comunica il VC++ con seriale, ho cercato un pò in rete e alla fine trovato dei tutorial, ma ora mi si pone un problema.
    Il codice realizzato è il seguente:

    codice:
    #include<iostream>
    #include "stdafx.h"
    #include "windows.h"
    #include "conio.h"
    using namespace std;
    
    BOOL setComm(HANDLE hComm)
    {
        DCB dcb;
        BOOL res;
    
        FillMemory(&dcb, sizeof(dcb), 0);
        res = GetCommState(hComm, &dcb); 
        if (!res)
            return FALSE;
    	
        dcb.ByteSize = 8;
        dcb.StopBits = TWOSTOPBITS;
        dcb.BaudRate = CBR_57600;
        dcb.Parity = NOPARITY;
        dcb.fAbortOnError = 0; 
        
        res = SetCommState(hComm, &dcb);
       
        if (!res)
            return FALSE;
    
        DWORD err = GetLastError();
        if ( err)
          cout << "Errore " << err << endl; 
    
        return TRUE;
    }
    
    void state(HANDLE hComm)
    {
        DCB dcb;
        BOOL res;
    
        FillMemory(&dcb, sizeof(dcb), 0);
        res = GetCommState(hComm, &dcb); 
    
        DWORD err = GetLastError();
        if ( err)
         cout << "Errore ricevuto " << err << endl;
    
        SetLastError(0);
    }
    
    BOOL write(HANDLE hComm, char * buf)
    {
      DWORD nNumberOfBytesToWrite = strlen(buf);
      DWORD NumberOfBytesWritten;
      LPOVERLAPPED lpOverlapped = NULL;
      BOOL res = WriteFile(
                 hComm, 
                 buf, 
    	nNumberOfBytesToWrite, 
    	&NumberOfBytesWritten, 
    	lpOverlapped 
    	);
       if (res)
        cout << "Scrittura OK " << endl;
       else
        {
          DWORD err = GetLastError();
          cout << "Errore in Scrittura " << err;
        }
    
    return res;
    }
    
    
    int main(int argc, char* argv[])
    {
        char gszPort[] = "COM1";
    
        HANDLE hComm;
        hComm = CreateFile( gszPort,
            GENERIC_READ | GENERIC_WRITE,
            0,
            0,
            OPEN_EXISTING,
            0, 
            0);
    
        if (hComm == INVALID_HANDLE_VALUE)
        {
    	cout << "Errore nell'apertura della porta " << endl;
        }
        else
        {
    	char comando;
    	char* com = &comando;
    	cout << "inserisci un comando ";
    	cin >> comando;
    	cout << endl;
    	cout << "comando inserito " << comando << endl;
    	if (comando == 't' || comando == 'v')
    	{	
      	cout << "il comando inserito può essere eseguito" << endl;
    
    	// qui devo modificare
    	char c;
    	char CR[] = {13,10,0};
    	DWORD nNumberOfBytesToRead = 1;
    	DWORD NumberOfBytesRead=0;
    	LPOVERLAPPED lpOverlapped = NULL; 
    	BOOL bResult;
    
                 bResult = setComm(hComm);
    
    	// questo deve essere modificato
    	write(hComm, com);
    	//write(hComm, CR);
    	//write(hComm, CR);
    
               for(;;)
    	{
    	nNumberOfBytesToRead = 1;
    	bResult = ReadFile(
       	   hComm,
    	   &c,
    	   nNumberOfBytesToRead,
    	   &NumberOfBytesRead,
    	   lpOverlapped
    	 );
    	            
                  if (NumberOfBytesRead>0)
    	  cout << c;
    	    //printf("%c", c);
               }
               }
            else
              {
    	cout << "il comando inserito non appartiene ai comandi che possono essere eseguiti" << endl;
    		}
    
    	CloseHandle(hComm);
            }
           cout << endl;
           getch();
           return 0;
    }
    Con la seriale riesco a comunicare ma, come dice anche il tutorial, il programma va in "wait", quindi si blocca tutto.
    Il tutorial suggeriva di "threadare" la lettura e scrittura su seriale.
    Ho provato a lavorare su questo punto ma trovo delle difficoltà, mi potete dare qualche suggerimento o dove posso trovare materiale?
    Grazie mille
    Ciccio

  2. #2
    In che senso trovi delle difficoltà? Cosa non ti è chiaro?
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Quello che ho capito è che per usare i thread devo scrivere una cosa del genere:

    codice:
    DWORD WINAPI ThreadProc (LPVOID lpParameter)
    {
      ...
    
      qui scrivo la funzione che deve essere "threaderata" di nome "ThreadProc"
      ...
    }
    
    int main (int argc, char* argv[])
    {
      ...
    
      scrivo il programma e per far eseguiere la funzione ThreadProc scrivo:
    
      DWORD ID1;
      HANDLE funz = CreateThread(NULL, 0, ThreadProc, &Param, 0, &ID1);
    
      ...
    }
    Giusto?
    Ora mi chiedo se le funzioni che devo threaderare sono le funzioni di scrittura e lettura su seriale, che hanno parametri in ingresso, così come le ho scritte nel programma, come si legano le cose?
    Devo scrivere una cose del genere:

    codice:
    DWORD WINAPI write (LPVOID lpParameter)
    {
     BOOL write(HANDLE hComm, char * buf)
     {
      DWORD nNumberOfBytesToWrite = strlen(buf);
      DWORD NumberOfBytesWritten;
      LPOVERLAPPED lpOverlapped = NULL;
      BOOL res = WriteFile(
                 hComm, 
                 buf, 
    	nNumberOfBytesToWrite, 
    	&NumberOfBytesWritten, 
    	lpOverlapped 
    	);
       if (res)
        cout << "Scrittura OK " << endl;
       else
        {
          DWORD err = GetLastError();
          cout << "Errore in Scrittura " << err;
        }
    
       return res;
      }
    
    }
    Non credo che funzioni così.
    Non riesco a capire come conciliare le cose.
    Grazie
    Ciccio

  4. #4
    codice:
    struct writeParams
    {
        HANDLE hComm;
        char * buf;
    };
    
    BOOL write(HANDLE hComm, char * buf)
     {
      DWORD nNumberOfBytesToWrite = strlen(buf);
      DWORD NumberOfBytesWritten;
      LPOVERLAPPED lpOverlapped = NULL;
      BOOL res = WriteFile(
                 hComm, 
                 buf, 
    	nNumberOfBytesToWrite, 
    	&NumberOfBytesWritten, 
    	lpOverlapped 
    	);
       if (res)
        cout << "Scrittura OK " << endl;
       else
        {
          DWORD err = GetLastError();
          cout << "Errore in Scrittura " << err;
        }
    
       return res;
      }
    
    DWORD WINAPI WriteThreadProc (LPVOID lpParameter)
    {
        writeParams * wp=(writeParams *)lpParameter;
        return (DWORD) write(wp->hComm,wp->buf);
    }
    
    int main (int argc, char* argv[])
    {
        //...
        writeParams wp;
        wp.hComm=quello che ci devi mettere;
        wp.buf=quello che ci devi mettere;
        HANDLE hWriteThread = CreateThread(NULL, 0, WriteThreadProc, &wp, 0, NULL);
        //...
    }
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Ti ringrazio per l'aiuto.
    Ora penso che dovrò fare la stessa cosa anche con la funzione di lettura.
    Grazie mille
    Ciccio

  6. #6
    Di niente, ciao!
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Scusatemi ragazzi ma ho un altro problema su questo programma.
    Se vedete nel codice, pongo alla fine il comando:

    codice:
    CloseHandle(hComm);
    questo dovrebbe essere il comando di chiusura della porta COM, giusto?
    O sto prendendo una cantonata?

    Mi è sorto il dubbio perchè se avvio il programma e do un comando questo me lo esegue e ottengo il risultato atteso, se lo riavvio il programma me lo esegue ma non mi da nessun risultato.
    Ho la sensazione che la porta COM rimanga aperta dopo che il programma è terminato, infatti devo resettare la scheda in maniera hardware.
    Avete qualche suggerimento?
    Grazie
    Ciccio

  8. #8
    Prima della chiusura dell'handle attendi che i thread abbiano terminato il loro lavoro con la API WaitForMultipleObjects.
    codice:
        //...
        HANDLE threadHandles[2];
        writeParams wp;
        //...
        threadHandles[0] = CreateThread(NULL, 0, WriteThreadProc, &wp, 0, NULL);
        //...
        readParams rp;
        //...
        threadHandles[1] = CreateThread(NULL, 0, ReadThreadProc, &rp, 0, NULL);
        //...
        WaitForMultipleObjects(2,threadHandles,TRUE,INFINITE);
        CloseHandle(threadHandles[0]);
        CloseHandle(threadHandles[1]);
        CloseHandle(hComm);
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Ciao MItaly,
    ti ringrazio dei suggerimenti, ma avrei ancora bisogno del tuo aiuto e di quello di altri...

    Trascurando il fatto che ieri sera il programma funzionava e questa mattina non aveva proprio voglia di andare...
    Ho creato un thread solo per la scrittura e, fino a ieri sera, tutto funzionava.
    Questa mattina ho fatto rigirare il programma e si bloccava, non mi dava ne scrittura ne lettura.
    Ho messo questo pezzo di codice:

    codice:
    ...
    HANDLE threadHandles[1];
    ...
    threadHandles[0] = CreateThread(NULL, 0, WriteThreadProc, &wp, 0, NULL);
    WaitForMultipleObjects(1,threadHandles,TRUE,INFINITE);
    ...
    e in questo modo riuscivo a inviare il comando e a leggerne la risposta.
    Penso che sia tutto un problema di sincronizzazione con la seriale.
    Ho provato a creare un thread per la funzione di lettura, e ho scritto:

    codice:
    BOOL read(HANDLE hComm, char read_c)
    {
       DWORD nNumberOfBytesToRead = 1;
       DWORD NumberOfBytesRead;
       LPOVERLAPPED lpOverlapped = NULL;
    
       BOOL res1 = ReadFile(
    	hComm,
    	&read_c,
    	nNumberOfBytesToRead,
    	&NumberOfBytesRead,
    	lpOverlapped
    	);
       return res1;
    }
    
    struct readParams
    {
        HANDLE hComm;
        char read_c;
    };
    
    DWORD WINAPI ReadThreadProc (LPVOID lpParameter)
    {
        readParams * rp=(readParams *)lpParameter;
        return (DWORD) read(rp->hComm, rp->read_c);
    }
    e dove mi serve:

    codice:
    for(;;)
    {
       rp.read_c=c;
       threadHandles[1] = CreateThread(NULL, 0, ReadThreadProc, &rp, 0, NULL);
    			
       if (NumberOfBytesRead>0)
          cout << c;
    			
       int keydown = _kbhit();
       if (keydown)
         break;
    }
    ma dopo la lettura del buffer non esce dal for.
    Non esce dal for anche se non utilizzo il thread di lettura e scrivo:

    codice:
    for(;;)
       {
    				
         nNumberOfBytesToRead = 1;
         bResult = ReadFile(
    	hComm,
    	&c,
    	nNumberOfBytesToRead,
    	&NumberOfBytesRead,
    	lpOverlapped
    	);
    
         if (NumberOfBytesRead>0)
    	cout << c;
    			
         int keydown = _kbhit();
    	if (keydown)
       	   break;
        }
    Sinceramente non so proprio che fare.
    Avete dei suggerimenti?
    Grazie
    Ciccio

  10. #10
    Ciao a tutti,
    il problema legato all'uscita da quel for l'ho risolto, era legato al _kbhit() che non funzionava a dovere.
    Grazie
    Ciccio

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.