Lettura dati seriale

di il
12 risposte

Lettura dati seriale

Buongiorno a tutti, sto cercando di creare un programmino che mi permetta di comunicare attraverso una porta seriale RS422. Sto utilizzando i file "Serial.h" e "Serial.cpp" trovati sul sito http://www.codeproject.com/Articles/992/Serial-library-for-C

ma non ho ben capito (nonostante sul link che ho postato sia spiegato) come fare a leggere tramite la seriale.

Ho notato che non è sufficiente utilizzare il comando "serial.Read()", altrimenti i dati non vengono letti correttamente, ma bisogna utilizzare il comando "serial.WaitEvent()" o cose simili.

Potreste spiegarmi meglio, magari con un piccolo esempio, come si possa leggere correttamente dalla seriale?Considerate che sono un novizio del c++.

Grazie a tutti

12 Risposte

  • Re: Lettura dati seriale

    Nessuno che sappia qualcosa in merito?
  • Re: Lettura dati seriale

    Ciao

    Non per scoraggiarti ma leggere da seriale in ambiente windows e in C++ senza l'uso di librerie esterne è abbastanza complesso.

    Ovviamente Windows mette a disposizione le API per fare I/O su seriale:
    http://msdn.microsoft.com/en-us/library/ff802693.asp

    Sotto Linux ti troveresti tutto un altro scenario; siccome la filosofia Linux è quella di "everything is a file" ti ritroveresti la seriale come un semplice file in /dev/TTY. Leggere e scrivere sulla seriale coincide con la lettura e scrittura su file (fopen() fwrite() fread() etc..etc..).

    Sotto Windows e in C#/Java è tutto un altro paio di maniche ovviamente

    Per fare pratica con la seriale ti consiglio di iniziare sotto Linux
  • Re: Lettura dati seriale

    Ancora lì stai? Già a Novembre abbiamo affrontato sto problema.
  • Re: Lettura dati seriale

    Beh non direi proprio "ancora lì". Il programma per poter comunicare tramite la seriale funziona. Riesco a scrivere ciò che voglio per inviarlo al microcontrollore.
    Il problema è solo sulla risposta: il controllore è stato impostato in modo tale che, non appena riceva qualche dato dalla seriale, lui risponda con determinati valori. Il problema è che la risposta che ricevo non è quella corretta, quindi deduco che il semplice comando "seral.Read()" non sia sufficiente. Però non trovo esempi sufficienti che mi dicano come fare per leggere bene tramite seriale.
  • Re: Lettura dati seriale

    Non mi ricordo se il tuo progetto era console o GUI cmq devi aspettarti un evento dalla classe CSerial che ti dice quand'è il momento di leggere dati. Poi la lettura la fai leggendo un buffer a tuo piacimento.
    Esempio in un mio programma.
    void CSerialPortManager::ReadData()
    {
    	DWORD dwBytesRead = 0;
    	BYTE buffer[101];
    	do
    	{
    		Read(buffer,sizeof(buffer),&dwBytesRead);
    		if (dwBytesRead > 0)
    		{
    			std::string data((char *)buffer,dwBytesRead);
    			data.erase(std::remove_if(data.begin(),data.end(),
    				[](const char & t)
    			{
    				return (t == _T('\r')) || (t == _T('\n'));
    			}
    			),data.end());
    
    			std::string::size_type pos = data.find_first_of(_T(' '));
    			if(pos != std::string::npos)
    			{
    				data = data.substr(++pos);
    				double volt = std::stod(data);
    				SetVoltage(volt * 0.0196363);
    			}
    		}
    	}
    	while (dwBytesRead == sizeof(buffer));
    }
    
    Lascia stare le cose che non capisci lì, ma concentrati sulla parte do-while. Legge finchè non ci sono più dati e l'if controlla se c'è qualcosa. (dwBytesRead > 0). Se c'è processi i dati ricevuti.

    Ma tutto questo viene richiamato dopo aver ricevuto l'evento dei dati disponibili sulla porta seriale. Leggi bene la documentazione della classe.
  • Re: Lettura dati seriale

    Ovvero: Esempio sul sito:
        // Read data, until there is nothing left
        DWORD dwBytesRead = 0;
        BYTE  abBuffer[100];
        do
        {
            // Read data from the COM-port
            serial.Read(abBuffer,sizeof(abBuffer),&dwBytesRead);
            if (dwBytesRead > 0)
            {
                // TODO: Process the data
            }
        }
        while (dwBytesRead == sizeof(abBuffer));
  • Re: Lettura dati seriale

    Ed ecco come impostare la ricezione dell'evento
    LRESULT CALLBACK MyWndProc (HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
    {
       if (nMsg == CSerialWnd::mg_nDefaultComMsg)
       {
           // A serial message occurred
           const CSerialWnd::EEvent eEvent = CSerialWnd::EEvent(LOWORD(wParam));
           const CSerialWnd::EError eError = CSerialWnd::EError(HIWORD(wParam));
    
           switch (eEvent)
           {
           case CSerialWnd::EEventRecv:
               // TODO: Read data from the port
               break;
    
               ...
           }
             
           // Return successful
           return 0;
       }
    
       // Perform other window processing
       ...
    }
  • Re: Lettura dati seriale

    Ok credo di aver capito più o meno come procedere.
    Il progetto è di tipo Console.
    L'unica cosa che non mi è chiarissima è come impostare l'evento. Ho visto il codice che mi hai postato per l'impostazione dell'evento, ma non so bene come utilizzarlo.
    In pratica il tutto dovrebbe funzionare così: io invio al controllore una serie di dati con "serial.Write()" e lui in automatico mi risponde con un'altra serie di dati (che, per la cronaca, rappresentano lo spazio libero della memoria del controllore stesso).
    Quindi in pratica la lettura deve avvenire non appena il controllore inizierà a spedire le risposte, che a sua volta coinciderà con il momento in cui io invio al controllore i dati.
  • Re: Lettura dati seriale

    Io ho scritto questo (appena prima del Main, subito dopo gli "include" per intenderci):
    
    CSerial serial;					//Dichiarazione classe 
    DWORD dwBytesRead = 0;			
    unsigned char TxBuffer[64];		//Buffer di invio dati
    unsigned char RxBuffer[64];		//Buffer di ricezione dati
    
    /******Impostazione dell'evento di lettura******/
    //
    // Registra il messaggio standard CSerial COM
    const UINT CSerial::mg_nDefaultComMsg = ::RegisterWindowMessage(_T("CSerial_DefaultComMsg"));
    
    //Evento di lettura
    LRESULT CALLBACK WndProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
    {
    	if (nMsg == CSerial::mg_nDefaultComMsg)
    	{
    		// A serial message occurred
    		const CSerial::EEvent eEvent = CSerial::EEvent(LOWORD(wParam));
    		const CSerial::EError eError = CSerial::EError(HIWORD(wParam));
    
    		switch (eEvent)
    		{
    		case CSerial::EEventRecv:
    			// TODO: Read data from the port
    			do
    			{
    				//Read data from the COM-port
    				serial.Read(RxBuffer, sizeof(RxBuffer), &dwBytesRead);
    			} while (dwBytesRead == sizeof(RxBuffer));
    
    			if (RxBuffer[13] <= 5){
    				Sleep(4 * 20);
    			}
    			Sleep(1000);
    
    			break;
    		}
    		// Return successful
    		return 0;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    E' corretto secondo te?
    A questo punto basta così oppure devo (all'interno del main) "chiamare" l'evento di lettura quando voglio che avvenga?

    Grazie
  • Re: Lettura dati seriale

    Proprio nessuno che possa darmi una mano?
  • Re: Lettura dati seriale

    Scusami ma tu non vuoi essere aiutato. Metti un listato sensa senso e aspetti che qualcuno faccia il debug e dirti dove sbagli. Per ricevere un evento devi avere una coda di messaggi e/o una finestra.
    La funzione ::RegisterWindowMessage (come dice il nome regista un messaggio per una finestra che tu non hai). Il callback WndProc è un callback di coda messaggi di una finestra che tu non hai. Come aspetti che uno ti dia una mano se sono i concetti basilari a mancare? Nel mio esempio c'è un
    // Perform other window processing
    ...
    che sta a significare processa gli ulteriori messaggi della finestra.
    A me sembra che stai cercando di correre senza imparare a camminare. O crei una finestra (nascosta se proprio non vuoi che si veda) o crea un servizio. In tutte e due i casi c'è da imparare.

    http://stackoverflow.com/questions/16448437/how-to-receive-messages-using-a-message-only-window-in-a-console-application
    http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/828f060d-9c30-40e4-9af2-b3431aee80c7/how-register-for-nongui-messages-in-console-app
  • Re: Lettura dati seriale

    Il punto è: come faccio a imparare se non so dove poter reperire le informazioni per imparare?
    Io sono riuscito a creare il mio programma per la comunicazione tramite la seriale, avendo iniziato da zero. Riesco inviare i dati che voglio sulla mia seriale, ma non riesco a leggere.
    La lettura non è fondamentale per il corretto funzionamento del programma, ma serve per migliorarlo.
    Il programma è di tipo CONSOLE, non un'applicazione windows.
    E' ovvio che io stia procedendo per tentativi, dal momento che non riesco a trovare nè sul web nè da nessun'altra parte delle informazioni dettagliate su questo argomento.
    Io penso che il mio sia un problema molto facilmente risolvibile da una persona che conosca questa materia, mentre per me si sta rivelando uno scoglio perchè i miei tentativi finora non sono andati a buon fine.
    Non pretendo niente da nessuno, ho solo chiesto un aiuto a chi penso ne sappia più di me sull'argomento. Se vorrete aiutarmi ne sarò felice, in caso contrario vi ringrazio comunque e cercherò aiuto altrove, perchè è un problema che intendo risolvere.
Devi accedere o registrarti per scrivere nel forum
12 risposte