Link to home
Start Free TrialLog in
Avatar of nsuresh
nsuresh

asked on

serial port gurus URGENT

hi

i'm developing an application to read data
from  a serial port of the PC , on Windows95
The strange behaviour , i'm observing is that
sometimes , i'm missing out some characters

i'm posting the extracts of the code here .
This is a direct read case ..ie ,No error
checking protocol exists.

Could someone tell me the possible reasons of me missing
out characters ??

this functions are meant to be called from a pb application
the caller first calls opencomm() and then calls chat()
with the obtained handle
the problem is in the chat() function's readfile
ie sometimes some characters are missing

i hope i have made myself clear.
This is urgent ,Please get back at u'r earliest .

Regards
Suresh

int __declspec(dllexport) __stdcall OpenComm(char *commport,int baudrate,int bits,char parity,int stop,
                              HANDLE *retHandle)
{
      HANDLE comHandle;
      BOOL success;
      DCB dcb;
      COMMTIMEOUTS timeouts;
      char buf[1000];

      
      comHandle = CreateFile(commport,
            GENERIC_READ|GENERIC_WRITE,
            0, 0, OPEN_EXISTING,
            //FILE_FLAG_OVERLAPPED, 0);
            FILE_ATTRIBUTE_NORMAL, 0);

      if (comHandle == INVALID_HANDLE_VALUE) {
                        return (int)-1;
      }      

      // Get the current COMM settings
      success = GetCommState(comHandle, &dcb);
      if (!success)
            return (int)-2;
      
            
      dcb.BaudRate = baudrate;
      dcb.ByteSize = bits;

      switch (parity) {
      case 'O' : dcb.Parity = ODDPARITY;break;
      case 'N' : dcb.Parity = NOPARITY;break;
      case 'E' : dcb.Parity = EVENPARITY;break;
      }

      switch (stop) {
      case 1   : dcb.StopBits = ONESTOPBIT;break;
      /* case 1.5 : dcb.StopBits = ONE5STOPBITS;break; */
      case 2   : dcb.StopBits = TWOSTOPBITS;break;
      }

      // Set flow control
      dcb.fInX = dcb.fOutX = TRUE;
      dcb.XonLim = 50;
      dcb.XoffLim = 200;
      dcb.XonChar = XON;
      dcb.XoffChar = XOF;


      // Save the COMM settings
      success = SetCommState(comHandle, &dcb);
      if (!success)
            return (int) -3;
            

      // Set the timeouts
      timeouts.ReadIntervalTimeout                  = MAXDWORD;
      timeouts.ReadTotalTimeoutMultiplier            = MAXDWORD ;
      timeouts.ReadTotalTimeoutConstant            = 100;
      timeouts.WriteTotalTimeoutMultiplier      = 10 ;
      timeouts.WriteTotalTimeoutConstant            = 100 ;
      success = SetCommTimeouts( comHandle, &timeouts ) ;

      if (!success)
            
            return (int) -4;
      

      // Set the DTR line
      EscapeCommFunction(comHandle, SETDTR);

      *retHandle = comHandle;


      return (int) 1;
}


/* read from scanner ,write to outfile */

int __declspec(dllexport) __stdcall Chat (HANDLE comHandle,char *outfile )

/*      returns number of records
      outfile is file to store data output from scanner
      infile  is file to be read in and transmitted to scanner
 */


      char in_buf[1024]
      char c;
      DWORD in_cnt = 0;
      DWORD      numRead,numWrite;
      BOOL      success = TRUE;
      // BOOL      cont = TRUE;
      int      stx_flag = 0;

      
      DWORD      error = 0;
      int      rec_cnt = 0;
      int t = 0, nothing_to_read = 0, more_to_read = 1;
      HANDLE      inHandle,outHandle;




      memset(in_buf,'\0',sizeof(in_buf));

      outHandle = CreateFile(outfile,
            GENERIC_WRITE,
            0, 0, CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL, 0);

      if (outHandle == INVALID_HANDLE_VALUE) {

            error = OUTFILE_ERROR;
      }

      
      while (success && error == 0 && more_to_read)
      {
            
            success = ReadFile(comHandle, &c, 1,&numRead, 0);

            if(!success) // i'm having problems here
                  break;


            if (numRead != 1)
            {

      
                  // no outstanding, or nothing after some time
                  if (more_to_read == 1 || nothing_to_read >= 50)
                  
                  {
                        if(rec_cnt)
                              error=1;

                        break;
                  }


                  
                  nothing_to_read++;
                  continue;
            }

            nothing_to_read = 0;
            more_to_read++;

            switch (c)
            {
            case STX : /* transmission starts with stx*/
                  
                  stx_flag = 1;
                  break;

            case ETX : /* and ends with etx/etb */
            case ETB :
                  more_to_read=0;
                  break;
            default :
                  in_buf[in_cnt] = c;
                  in_cnt++;
            
                  if(stx_flag && c == LF)
                  {
                                /* write output to file */
                        success = WriteFile (outHandle,      in_buf,in_cnt,&numWrite,NULL);
                        FlushFileBuffers(outHandle);
                        if (! success) {
                              continue;
                        }
                        if (numWrite != in_cnt) {
                              success=FALSE;
                              continue;
                        }
                        //in_buf[0] = 0;
                        memset(in_buf,'\0',sizeof(in_buf));
                        in_cnt = 0;
                  }
            
                  
                  }/* switch */
            
      }// while
      CloseHandle (inHandle);
      CloseHandle (outHandle);
      
}



Avatar of zebada
zebada

I haven't looked at your code in detail, but it looks OK.
Try this code, it works for me...

synchcom.h
----------
// *************************************************************************
// *                                                                       *
// *                       (C) - 1999 Paul Blackmore                       *
// *                                                                       *
// *************************************************************************
//
// Modifications
// -------------------------------------------------------------------------
// Version | When        | Who | Why
// --------+-------------+-----+--------------------------------------------
// 1.0     | 1999-Sep-21 | PSB | Created program
//         |             |     |
// --------+-------------+-----+--------------------------------------------
//         |             |     |
//         |             |     |
// -------------------------------------------------------------------------


#if !defined(SC_H_INCLUDED)
#define SC_H_INCLUDED

#include  <windows.h>

#ifdef _WIN32
  #ifdef _SCDLL
    #define SC_DLL __declspec(dllexport)
  #else
    #define SC_DLL __declspec(dllimport)
  #endif
#else
  #define SC_DLL
#endif

// SyncCom Errors:
#define SCE_BASE        20000       // Base of SyncCom error numbers.
#define SCE_INIT        SCE_BASE+0  // Com port not initialised, call comInit() first.
#define SCE_READ        SCE_BASE+1  // No data read.
#define SCE_WRITE       SCE_BASE+2  // No data written.
#define SCE_CREATE      SCE_BASE+3  // Can't create connection to com port.
#define SCE_SETUP       SCE_BASE+4  // Can't setup buffers for com port.
#define SCE_GETCOM      SCE_BASE+5  // Can't read com port settings.
#define SCE_SETCOM      SCE_BASE+6  // Can't write com port settings.
#define SCE_BUILD       SCE_BASE+7  // Can't build Device Control Block.
#define SCE_GETCOMTIME  SCE_BASE+8  // Can't read com port timeout settings.
#define SCE_SETCOMTIME  SCE_BASE+9  // Can't write com port timeout settings.

#define SCE_PEAK        SCE_BASE+9  // Upper bound of SyncCom error numbers.

// Constants
#define MAX_ERRMSGLEN   1024                // Maximum error message length
#define MAX_BUFLEN      80          // Maximum length of data buffer
#define MAX_COMSPECLEN  64          // Maximum length of com specification

// Global variables
extern SC_DLL int       errCode;    // Error code
extern SC_DLL char      errText[];  // error message

// API Functions
SC_DLL int scInit(int comid,char *comspec);
//     Initialises com port with compsec.
//         comid is the COM port number 1=COM1, 2=COM2 etc
//         comspec is the COM port specification: "baud=8192 parity=N stop=1 data=8"
//     Return value:
//         0: OK
//        -1: FAIL check global variables: errCode and errText

SC_DLL int scTimeOut(int t1,int t2,int t3);
//     Sets up com port timeouts, default: t1=5,t2=1,t3=10.
//         Each byte must be received within t1 milliseconds of previous byte.
//         All bytes must be received within (t2*bytes reqested)+t3 milliseconds.
//     Return value:
//         0: OK
//        -1: FAIL check global variables: errCode and errText

SC_DLL int scDone(void);
//     Closes com port and releases it for other applications
//     Return value:
//         0: OK
//        -1: FAIL check global variables: errCode and errText

SC_DLL int scRead(char *buf,int bufSize);
//     Attempts to reads bufSize bytes of data from comport into buf.
//     Return value:
//       >=0: OK, number of bytes read.
//        -1: FAIL check global variables: errCode and errText

SC_DLL int scWrite(char *buf,int bufSize);
//     Attempts to write bufSize bytes of data from buf to comport.
//     Return value:
//       >=0: OK, number of bytes written.
//        -1: FAIL check global variables: errCode and errText

#endif

synchcom.c
----------
// *************************************************************************
// *                                                                       *
// *                       (C) - 1999 Paul Blackmore                       *
// *                                                                       *
// *************************************************************************
//
// Modifications
// -------------------------------------------------------------------------
// Version | When        | Who | Why
// --------+-------------+-----+--------------------------------------------
// 1.0     | 1999-Sep-21 | PSB | Created program
//         |             |     |
// --------+-------------+-----+--------------------------------------------
//         |             |     |
//         |             |     |
// -------------------------------------------------------------------------

#define _SCDLL

#include <stdio.h>
#include "synchcom.h"

SC_DLL int    errCode;
SC_DLL char   errText[MAX_ERRMSGLEN+1];

static HANDLE       *comfd=NULL;
static COMMTIMEOUTS ct;
static DCB          dcb;
static char         comName[32];

static char         *scErrList[SCE_PEAK] = {
                      "Com port is not initialised, call scInit() first.\n",
                      "No data received.\n",
                      "No data sent.\n",
                      "Can't create connection to com port.",
                      "Can't setup buffers for com port.",
                      "Can't read com port settings.",
                      "Can't write com port settings.",
                      "Can't build Device Control Block.",
                      "Can't read com port timeout settings.",
                      "Can't write com port timeout settings."
                    };
static char         aldl[1024];
static BYTE         eprom[0x10000];

static void scError(int e);

// -------------------------------------------------------------------------
SC_DLL int
scInit(int comid,char *comspec)
{

  sprintf(comName,"COM%d:",comid);

  if ( (comfd=CreateFile(comName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL))==INVALID_HANDLE_VALUE ) {
    scError(SCE_CREATE);
    return -1;
  }
   
  if ( !SetupComm(comfd,1024,1024)!=0 ) {
    scError(SCE_SETUP);
    return -1;
  }

  if ( !GetCommState(comfd,&dcb) ) {
    scError(SCE_GETCOM);
    return -1;
  }

  if ( !BuildCommDCB(comspec,&dcb) ) {
    scError(SCE_BUILD);
    return -1;
  }

  // Set minimal flow control
  dcb.fOutxCtsFlow = 0;
  dcb.fOutxDsrFlow = 0;
  dcb.fDtrControl = DTR_CONTROL_DISABLE;
  dcb.fDsrSensitivity = 0;
  dcb.fOutX = 0;
  dcb.fInX = 0;
  dcb.fRtsControl = RTS_CONTROL_DISABLE;

  if ( !SetCommState(comfd,&dcb) ) {
    scError(SCE_SETCOM);
    return -1;
  }

  // Set default timeouts
  if ( scTimeOut(5,1,10)<0 ) {
    printf("Error %d: %s\n",errCode,errText);
    return -1;
  }

  return 0;
}

// -------------------------------------------------------------------------
SC_DLL int
scDone()
{
  if ( comfd==NULL ) {
    scError(SCE_INIT);
    return -1;
  }

  CloseHandle(comfd);
  comfd = NULL;

  return 0;
}

// -------------------------------------------------------------------------
SC_DLL int
scTimeOut(int t1,int t2,int t3)
{
  if ( comfd==NULL ) {
    scError(SCE_INIT);
    return -1;
  }

  if ( !GetCommTimeouts(comfd,&ct) ) {
    scError(SCE_GETCOMTIME);
    return -1;
  }

  // t1: Maximum number of millisecond to wait between each received byte.
  // t2: Wait for t2*nBytesToRead milliseconds for all bytes to be received.
  // t3: Wait an additional t3 milliseconds.

  ct.ReadIntervalTimeout = t1;
  ct.ReadTotalTimeoutMultiplier = t2;
  ct.ReadTotalTimeoutConstant = t3;

  ct.WriteTotalTimeoutMultiplier = 10;
  ct.WriteTotalTimeoutConstant = 100;
 
  if ( !SetCommTimeouts(comfd,&ct) ) {
    scError(SCE_SETCOMTIME);
    return -1;
  }
  return 0;
}

// -------------------------------------------------------------------------
SC_DLL int
scRead(char *buf,int bufSize)
{
  int  bytesRead;

  if ( comfd==NULL ) {
    scError(SCE_INIT);
    return -1;
  }

  if ( !ReadFile(comfd,buf,bufSize,&bytesRead,NULL) ) {
    scError(SCE_READ);
    return -1;
  }
  return bytesRead;
}

// -------------------------------------------------------------------------
SC_DLL int
scWrite(char *buf,int bufSize)
{
  int bytesWritten;

  if ( comfd==NULL ) {
    scError(SCE_INIT);
    return -1;
  }

  if ( !WriteFile(comfd,buf,bufSize,&bytesWritten,NULL) ) {
    scError(SCE_WRITE);
    return -1;
  }
  return bytesWritten;
}

// -------------------------------------------------------------------------
static void
scError(int e)
{
  errCode = e;
  if ( SCE_BASE<=errCode && errCode<=SCE_PEAK )
    strcpy(errText,scErrList[errCode-SCE_BASE]);
  else
    strcpy(errText,"Unknown error");
}
ASKER CERTIFIED SOLUTION
Avatar of baeg
baeg

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nsuresh

ASKER

i could not try this out ,
will do that soon
incidentally i found the same problem with the accessories/hyperterm also

thanx a lot
suresh


This question was awarded, but never cleared due to the JSP-500 errors of that time.  It was "stuck" against userID -1 versus the intended expert whom you awarded.  This corrects that and the expert will now receive these points, all verified.
Moondancer
Moderator @ Experts Exchange