• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 418
  • Last Modified:

serial interface

i write a monitoring program and i need to read permanent the rs232 port i must receive 4 byte data
on com1. I write fallowing code fragment for initialisation the com1 and send and receive function
but when i send 4 byte data sometimes its ok sometimes not and when i will receive data i receive
everytime 2 byte or 3 byte, what can be wrong with my code,
i send a command message packet to a targetsystem and must wait for answer, how can i synchronize
send and receive sequence, the target system need time to execute the command(about 400 ms).

                 thank you

void MainFrame::OnDeviceSerial()  /*initialisation the serial interface*/
{
 
   
        COMMCONFIG com;
      COMMTIMEOUTS cto;
     
      int ans;
      CString cst;
    CString dw_par;
      CString cw_par;
      CString si_par;
      HANDLE hdl;
      ans=0;
      DCB dcbp;
       MONITORINGApp*  mainapp;
       mainapp=(MONITORINGApp*)AfxGetApp();
     hdl=mainapp->hcomm;
      
       lk = CommConfigDialog( "COM1",GetSafeHwnd( ),&com);/* show the Serial interface dialog for COM2*/
       if(hdl==0){
       hdl=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);/*open com2 for read and write*/
       }
       if(GetLastError()==ERROR_INVALID_HANDLE) AfxMessageBox("INVALIDE HANDLE");
       memset(&cto,0,sizeof(cto));/* init timeout structur for com2*/

      // cto.ReadTotalTimeoutMultiplier=1; /****125*4=500 ms time for read operation*/
      
       cto.WriteTotalTimeoutMultiplier=1;
       SetCommTimeouts(hdl,&cto);/*set timeouts */
       com.dcb.DCBlength=sizeof(com.dcb);
       DCB dcb3=com.dcb;
       GetCommState(hdl,&dcb3);
       SetCommState(hdl,&com.dcb);/*set the com parameter*/
     GetCommState(hdl,&dcbp);/*get the com parameter*/
     comok=1;
      }

================================================
================================================
BOOL transfer::send_msg()
{
BOOL mark;
BOOL send_ok;      
int byte_count;
byte_count=0;
send_ok=false;      
//fwritestat=WriteFile(APPT()->hcomm,&write_buffer,bytes_to_write,&bytes_writen,&oswrite);
      for(int m=0; m<4; m++){
            ::Sleep(50);
            fwritestat=WriteFile(APPT()->hcomm,&write_buffer[m],1,&bytes_writen,&oswrite);
            if(bytes_writen) byte_count++;}
      if(bytes_to_write==(DWORD)byte_count) send_ok=true;
      if(!fwritestat)
      {
            if(GetLastError()== ERROR_IO_PENDING)
            {
                  while(!GetOverlappedResult(APPT()->hcomm,&oswrite,&bytes_writen,TRUE)){
                        dwError=GetLastError();
                        if(dwError==ERROR_IO_INCOMPLETE)
                        {
                              dw_bytes_sent+=bytes_writen;
                              continue;
                        }
                        else{
                              ClearCommError(APPT()->hcomm,&dwerrorflag,&comstat);
                              break;
                        }
                  }
          dw_bytes_sent+=bytes_writen;
              if(dw_bytes_sent!=bytes_to_write) return(FALSE);
            }else{
                  ClearCommError(APPT()->hcomm,&dwerrorflag,&comstat);
                  return(FALSE);
            }
      }
if(send_ok) mark=true;
if(!send_ok) mark=false;      
return(mark);
}



int transfer::receive_msg(LPSTR lpszBlock, int nMaxLength)
{
BOOL fReadStat;
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
//char szError[10];
OVERLAPPED osRead;
ClearCommError(APPT()->hcomm,&dwErrorFlags,&ComStat);
dwLength=min((DWORD)nMaxLength,ComStat.cbInQue);
if(dwLength>0)
{
      fReadStat=ReadFile(APPT()->hcomm,&lpszBlock,dwLength,&dwLength,&osRead);
      if(!fReadStat)
      {
            if(GetLastError()==ERROR_IO_PENDING)
            {
                  while(!GetLastError()==(APPT()->hcomm,&osRead,&dwLength,TRUE))
                  {
                        dwError=GetLastError();
                        if(dwError==ERROR_IO_INCOMPLETE)
                              continue;
                        else
                        {
                              ClearCommError(APPT()->hcomm,&dwErrorFlags,&ComStat);
                              break;
                        }
                  }
            }
            else
                  dwLength=0;
            ClearCommError(APPT()->hcomm,&dwErrorFlags,&ComStat);
      }
}

rec_data=lpszBlock;

 return(dwLength);

}
0
fari
Asked:
fari
1 Solution
 
snoeglerCommented:
You are using - according to your code - overlapped io.
But you missed to specify FILE_FLAG_OVERLAPPED in your CreateFile() call, so the
OVERLAPPED structure you pass to WriteFile and ReadFile (oswrite) is not used except
the 'Offset' member of the OVERLAPPED structure - and even this one is not valid when
communicating with devices.
If your device supports the status lines like DTR and so on, you don't need to handle the
timeout delays as the device will reject and accept incoming bytes (same behavior when
it is sending). That means ReadFile() won't return until a byte is available, and WriteFile() won't
write a byte when the target buffer is full.

I would simply define these two functions:

BOOL ReadByte(HANDLE hCommFile,BYTE& theChar,DWORD minElapseTime)
{
  DWORD msPrev=::GetTickCount(),actualDelay;
  DWORD nBytesRead;
  ::ReadFile(hCommFile,&theChar,sizeof(BYTE),&nBytesRead,NULL);
  if(nBytesRead!=sizeof(BYTE)) // timeout error
    return FALSE;
  actualDelay=::GetTickCount()-msPrev;
  if( actualDelay<minElapseTime)
    Sleep(minElapseTime-actualDelay);
  return TRUE;
}

BOOL WriteByte(HANDLE hCommFile,BYTE theChar,DWORD minElapseTime)
{
  DWORD msPrev=::GetTickCount(),actualDelay;
  DWORD nBytesWritten;
  ::WriteFile(hCommFile,&theChar,sizeof(BYTE),&nBytesWritten,NULL);
  if(nBytesWritten!=sizeof(BYTE)) // timeout error or something
    return FALSE;
  actualDelay=::GetTickCount()-msPrev;
  if( actualDelay<minElapseTime)
    Sleep(minElapseTime-actualDelay);
  return TRUE;
}

These functions take the argument 'minElapseTime', and if the data is read or written faster
than this delay the functions wait until 'minElapseTime' has elapsed. If you set your
COMMTIMEOUTS to the appropriate values, the functions return FALSE if the delay has been
exceeded.
Of course you could use overlapped io, but then you have to watch for these things:
- specify FILE_FLAG_OVERLAPPED in the CreateFile()
- use the hEvent member of the OVERLAPPED structure:
   WaitForSingleEvent(oswrite->hEvent, theDelayInMsec);
   (The OVERLAPPED member 'hEvent' must be initialized before using
    CreateEvent() - If you don't know the event mechanism then post it, i think many experts
    can give you information on this)

And this is a tip: Structurize your code a bit more ... :)
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now