Newsgroup: it.comp.lang.c++
Titolo: Seriali e Windows 95 - parte II

Ho utilizzato le api di Windows per gestire le seriali, ed in
particolare riporto di seguito il codice semplificato di cio' che ho
scritto:
BOOL Seriale::Apri()
{
// apro la porta seriale COMx
    m_hCom = CreateFile( "COM1", 
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         NULL,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL);
 
// dimensiono le code
    SetupComm (m_hCom, 2048, 128);
// elimino eventuali caratteri in coda
    PurgeComm (m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR |
PURGE_RXCLEAR);
// timeout di lettura : 100ms
    COMMTIMEOUTS CommTimeOuts = { 0, };
    CommTimeOuts.ReadIntervalTimeout = 1;
    CommTimeOuts.ReadTotalTimeoutMultiplier = 100;
    CommTimeOuts.ReadTotalTimeoutConstant = 1;
    SetCommTimeouts (m_hCom, &CommTimeOuts) ;
// nessun evento
    SetCommMask (m_hCom, 0);
 
// configuro i parametri di linea
    SetCommState (m_hCom, &dcb);
// alzo i segnali DTR e RTS
    EscapeCommFunction (m_hCom, SETDTR);
    EscapeCommFunction (m_hCom, SETRTS);
}
// leggo dalla seriale un solo carattere
SERIALE_STATO Seriale::LeggiCarattere (char *chr)
{
    DWORD nLetti = 0;
    if (! ReadFile (m_hCom, chr, 1, &nLetti, NULL) || nLetti == 0)
    {
        DWORD errore = GetLastError();
        Pulisci();
        return ERRORE_LETTURA;
    }
    return SUCCESSO;
}
Quando devo leggere un messaggio chiamo la LeggiCarattere() fino a
quando non ho trovato il carattere di fine (solitamente ETX); leggo
poi 2 caratteri di CRC e controllo il CRC calcolato con il CRC
ricevuto; se diverso, invio NAK e attendo di nuovo il messaggio,
altrimenti invio ACK e continuo con il prossimo pacchetto.
Sotto Windows NT questo programma funziona benissimo.
Sotto Windows 95 capita invece che il carattere di fine messaggio non
arriva, e dopo 100ms il PC va in timeout, invia NAK e attende di nuovo
il pacchetto che a questo punto arriva 'bene'.
Non credo che sia un problema di qualche altro driver; il programma
l'ho provato su 3 PC con Windows 95, un Pentum 100, un Pentium 166 e
un Pentium 200MMX; nessun programma stava girando insieme al mio e il
mio programma non scrive su disco; prende i dati dalla seriale e li
deposita in un buffer in memoria (max coumnque 200 Kb circa).
Io non so proprio dove sbattere la testa!!!
Ho provato a dare maggior priorità al mio programma, ma non ho
ottenuto alcun risultato.
Esiste un driver per Windows 95 che corregge questo problema ?
Potrebbe essere il modo con cui inizializzo la seriale che è sbagliato
?
Grazie per l'attenzione e buon lavoro!
  Stefano  - 
m...@softeam.it


No So a cosa possa essere dovuto il tuo problema pero io aprendo la porta con
la seguente  sequenza non perdo alcun  carattere
DCB comDcb;
COMMTIMEOUTS sTimeout={ 1, 0,0 };
/* On Input StrCom = "COM1" or "COM2" ecc.
   return HANDLE.
*/
bool initCom( HANDLE *c, const char *strCom)
{
 comDcb.DCBlength = sizeof(DCB);     // sizeof(DCB)
 comDcb.BaudRate=CBR_9600;          // current baud rate
 comDcb.fBinary=TRUE;          		// binary mode, no EOF check
 comDcb.fParity=FALSE;             // enable parity checking
 comDcb.fOutxCtsFlow=FALSE;      // CTS output flow control
 comDcb.fOutxDsrFlow=FALSE;      // DSR output flow control
 comDcb.fDtrControl=DTR_CONTROL_DISABLE	;       // DTR flow control type
 comDcb.fDsrSensitivity=FALSE;   // DSR sensitivity
 comDcb.fTXContinueOnXoff=FALSE; // XOFF continues Tx
 comDcb.fOutX=FALSE;            // XON/XOFF out flow control
 comDcb.fInX=FALSE;             // XON/XOFF in flow control
 comDcb.fErrorChar=FALSE;       // enable error replacement
 comDcb.fNull=FALSE;            // enable null stripping
 comDcb.fRtsControl=RTS_CONTROL_DISABLE	;       // RTS flow control
 comDcb.fAbortOnError=FALSE;     // abort reads/writes on error
 comDcb.ByteSize=8;             // number of bits/byte, 4-8
 comDcb.Parity=NOPARITY	;               // 0-4=no,odd,even,mark,space
 comDcb.StopBits=ONESTOPBIT	;             // 0,1,2 = 1, 1.5, 2
 comDcb.XonChar=XON;              // Tx and Rx XON character
 comDcb.XoffChar=XOFF;             // Tx and Rx XOFF character
 comDcb.ErrorChar=0;            // error replacement character
 comDcb.EofChar=0;              // end of input character
 comDcb.EvtChar=STX;              // received event character
 comDcb.wReserved1;           // reserved; do not use
 *c=CreateFile(strCom,
	        GENERIC_READ,
                0,
                NULL,
                OPEN_EXISTING,
                0,
                NULL);
if (*c==NULL) return(FALSE);
if (!SetCommTimeouts(*c,&sTimeout)) return(FALSE);
if (!SetupComm(*c,12000,12000)) return(FALSE);
if (!SetCommState(*c,&comDcb))  return(FALSE);
return(TRUE);
}
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/
       Search, Read, Discuss, or Start Your Own    

Qualche punto da provare potrebbe essere:
0: il protocollo va in NAK sempre allo stesso punto ? NON credo e allora:
1: prova a piazzare un protocol analyzer per misurare quanto tempo
intercorre tra il penultimo carattere e l' ultimo;
Io cercherei di verificare che effettivamente il sistema riceva tutti i
caratteri  entro i 100ms l' uno dall' altro;
2: proverei a programmare il driver in modo che attenda indefinitamente;
3: nel caso che il punto 2 sia verificato proverei a dare dei tempi multipli
di 55ms (es: 165ms );
infatti il tic di sistema di Windows95 mi pare sia lo stesso del DOS ( per
compatibilità ),
mentre WinNT4.0 ha un tic diverso ( più breve ); cioé non verrei che il
timeout da te programmato a 100ms si riduca talvolta a 55-56ms.
Fammi sapere se ho ragione o se sono in errore.
Ciao, Matteo