Comunicazione tramite seriale

di Anonimizzato13652 il
30 risposte
Buongiorno a tutti, sono un novizio del C++ e avrei bisogno di aiuto. Io dovrei scrivere un piccolo eseguibile in C++ che permettesse di prendere dei dati numerici da un file .txt e inviarli tramite porta seriale (COM2 nel mio caso) a un microcontrollore. Il problema è che non ho mai lavorato con le seriali e in più sono all'inizio della programmazione in C++. Non vi chiedo certo di risolvermi completamente il problema, ma vi chiedo se potreste per favore scrivermi alcune righe di codice per darmi un'idea di come si inizia un lavoro di questo tipo. Sono in alto mare proprio perchè non so come cominciare. Grazie in anticipo a tutti.

30 Risposte

  • Ciao, dipende da che sistema operativo utilizzi.
    Se sei in Windows puoi utilizzare la API CreateFile()
    
    CreateFile(
          "\\\\.\\COM2",     // address of name of the communications device
          GENERIC_READ|GENERIC_WRITE,          // access (read-write) mode
          0,                  // share mode
          NULL,               // address of security descriptor
          OPEN_EXISTING,      // how to create
          0,                  // file attributes
          NULL                // handle of file with attributes to copy
       );
    
    E poi per spedire caratteri usi WriteFile() e per leggere usi ReadFile().
    Ad ogni modo qui è spiegato bene http://www.codeproject.com/Articles/3061/Creating-a-Serial-communication-on-Win32
    Spero di esserti stato d'aiuto
  • Innanzitutto grazie delle preziose info che mi hai dato. Si io utilizzo Windows 7 come sistema operativo. L'unica cosa che non ho capito è l'utilizzo della funzione CreateFile. Come la devo usare se, ad esempio, voglio inviare tramite COM2 i dati provenienti da un file chiamato "prova.txt"?grazie dell'aiuto.
  • Allora ho scaricato i file .h e .cpp relativi alla classe CSerial, ma mi da alcuni errori in fase di compilazione all'interno del file .cpp

    Vi posto solo il codice relativo alle righe che danno errore e poco altro, così da non inserire cose inutili:
    
    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <stdio.h>
    #include <windows.h>
    #include "CSerial.h"
    
    CSerial::CSerial()
    {
    
    	....
            ....
    
    
    if (m_bOpened) return(TRUE);
    
    	char szPort[15];
    	char szComParams[50];
    	DCB dcb;
    	wsprintf(szPort, "COM%d", nPort); // ERRORE!!!!!!!
    
    
    	m_hIDComDev = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
    	if (m_hIDComDev == NULL) return(FALSE); // ERRORE!!!!!!
    
    	memset(&m_OverlappedRead, 0, sizeof(OVERLAPPED));
    	memset(&m_OverlappedWrite, 0, sizeof(OVERLAPPED));
    
    	COMMTIMEOUTS CommTimeOuts;
    	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
    	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
    	CommTimeOuts.ReadTotalTimeoutConstant = 0;
    	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
    	CommTimeOuts.WriteTotalTimeoutConstant = 5000;
    	SetCommTimeouts(m_hIDComDev, &CommTimeOuts);
    
    	wsprintf(szComParams, "COM%d:%d,n,8,1", nPort, nBaud); // ERRORE!!!!!!!!
    
    ...
    ...
    ...
    
    Gli errori sono tutti e 3 di questo tipo':
    - impossibile convertire l'argomento 1 da 'char [15]' a 'LPCWSTR'

    Sembra che le parole incriminate siano: "szPort", "COM%d", "szComParams", "COM%d:%d,n,8,1".

    Sapreste dirmi dove ho sbagliato?Io ho semplicemente scaricato questi due file e inseriti nel mio progetto (che al momento è ancora vuoto).

    Grazie
  • Secondo me dovresti fare un passo indietro e provare a ricompilare il progetto di esempio.
    Il problema che hai è probabilmente dovuto ad header sbagliati (vedi stdafx.h) ma, come ti dicevo, è meglio se parti dal programma di esempio.
  • Il problema è che non c'è nessun programma di esempio! Esistono solo questi due file Serial.h e Serial.cpp che io non posso fare altro che includere nel progetto e tentare di far funzionare!...Però mi segnala questo errore e non capisco perchè...

    Cosa intendi con "errore dovuto a header sbagliati"?Quali sarebbero secondo te?
  • Magari puoi sostituire l'header stdafx.h con
    
    #define STRICT
    #include <crtdbg.h>
    #include <tchar.h>
    #include <windows.h>
    
    come è spiegato nell'articolo stesso.
  • Allora ho utilizzato la classe CSerial come suggerito da skynet. Ho provato a scrivere un po' di codice ma non riesco a trovare un modo per inviare i dati contenuti nel mio file di testo tramite seriale.
    Il file di testo contiene dati disposti su 3 colonne e n righe
    (es. 1 2 3)
    4 7 9
    8 4 10
    2 4 1

    Vorrei inviarli riga per riga (cioè prima 1 2 3, poi 4 7 9, etc...) tramite la mia porta seriale, ma mi manca la parte del codice relativa all'invio di dati. Per giunta non trovo neanche esempi sul web. Help please. Grazie a tutti in anticipo.
    Vi posto il codice che ho scritto:
    
    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <crtdbg.h>
    #include <string>
    #include <tchar.h>
    #include <windows.h>
    #include "Serial.h"
    
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        #define MAXR 100
    	float mat[MAXR][3];
    
    	// legge dati dal file txt
    	ifstream dati("C:\\Users\\ALESSANDRO\\Desktop\\Parte1.txt");
    	int r = 0;
    	while (!dati.eof())
    	{
    		dati >> mat[r][0] >> mat[r][1] >> mat[r][2];
    		r++;
    	}
    	dati.close();
    
    	CSerial serial; // utilizzo della classe CSerial
    	if (serial.Open(2, 9600)) // apre la porta seriale COM2
    	{
    		CODICE CHE MI MANCA DA SCRIVERE
    	}
    	else
    		MessageBox(HWND_DESKTOP, "Failed to open port!", "Error", MB_OK);
    	return 0;
    }
    
  • serial.Write("Hello world");
    
    Cosa non comprendi?
    Sei sicuro di aver aperto la porta seriale correttamente?
    Che impostazioni si aspetta il microcontrollore come parita, bit di stop, handshaking ecc?
    Hai impostato un evento/messaggio custom da cui puoi ricevere le risposte della porta seriale?

    Cmq in nessun contesto della classe non vedo l'apertura porta col numero, ma sempre come stringa quindi fai attenzione anche ai valori di ritorno della funzione Open.
    virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED);
    
  • Altra cosa da segnalare.
    Tu non hai un MessageLoop in quanto sei in console. Il MessageBox che usi ha come parent il desktop. Quindi senza MessageLoop non puoi avere messaggi custom da cui non puoi ricevere risposta dal microcontrollore.
    Se questa è una cosa sporadica (mando dati e stop) può anche andar bene ma controlla l'apertura porta e impostazioni di connessione.
  • bool CSerialPortManager::Initialize( CWnd *pParent )
    {
    	std::wstring comPort = std::move(_T("COM") + to_string(m_comPortNumber,0));
    	LONG lastError = Open(comPort.c_str(),pParent,UWM_SERIAL,m_comPortNumber);
    	if(lastError == ERROR_SUCCESS)
    	{
    		Setup(CSerialMFC::EBaud2400,CSerialMFC::EData8,CSerialMFC::EParNone,CSerialMFC::EStop1);
    		SetupHandshaking(CSerialMFC::EHandshakeOff);
    		SetupReadTimeouts(CSerialMFC::EReadTimeoutNonblocking);
    		return true;
    	}
    	return false;
    }
    
    Piccolo esempio (anche se in MFC) di apertura porta e controllo errore.
  • Per inviare una stringa scritta sul momento (tipo "Hello World") ho capito come si fa, ma non so bene quale sia il codice corretto per inviare dei dati presi da un certo file. Magari è molto simile il codice, ma non essendo molto esperto non sono riuscito a scriverlo.
    No a dirti la verità non sono affatto sicuro di averla aperta correttamente, dato che è la prima volta che lo faccio!!:)...Ci ho provato, ma probabilmente nel mio codice ci sono ancora delle lacune. Per questo lo ho postato, così almeno potrò imparare qualcosa dalle vostre correzioni.

    Grazie ancora
  • Le impostazioni della comunicazione col microcontrollore li sai solo tu quindi informati di questo e possiamo modificare il tuo codice di conseguenza.
  • Ok ti ringrazio. Il microcontrollore non lo ho progettato io, ma un'altra persona e quindi devo chiedere a lui le specifiche e così potrò comunicartele.
    Nel frattempo ti chiedo una cosa riguardo il codice da te postato: il tuo codice scritto in MFC è molto diverso da quello che dovrei scrivere io oppure cambia solo un po' la dicitura?...
Devi accedere o registrarti per scrivere nel forum
30 risposte