Solved

Communication RS232 and parallell port

Posted on 1998-04-05
6
645 Views
Last Modified: 2013-11-15
Temperaturcontrolling of an oven with PC, to look at floating liquid crystals! You shall be able to control the temperatur of an oven with an temperatur sensor (features a duty-cycle modulated square-wave output voltage with linear response to temperatures in the -45 degreas C to +130 degreas C) wich gives out pulses with voltage 0-5 and an powersupply with serial-communication (RS232). The temperatursensor is connected to the parallellport.  A regulator program shall be implemented in C++ code. How can the regulatorprogram communicate with the parallellport and RS232?  
0
Comment
Question by:emtk9702
6 Comments
 
LVL 2

Expert Comment

by:kellyjj
ID: 1184066
are we talking about dos? or windows?
0
 

Expert Comment

by:paulsinn
ID: 1184067
The following is a peace of (stripped) code from a program I wrote to read characters from the RS232 port for input from a barcode reader. I think You can modify it easily.

Initially you need the following:

DCB      dcb;
int      idCommDev = -1;

...

      idCommDev = OpenComm( CommPoort, 1024, 128 );

      if ( idCommDev < 0 )
      {   alert_word ( "Can't open COMn", idCommDev );
            return ( FALSE );
      }

      status = BuildCommDCB( CommString, &dcb );

      if ( status < 0 )
      {      alert_word ( "Error BuildCommDCB", status );
            return ( FALSE );
      }

      status = SetCommState( &dcb );

      if ( status < 0 )
      {      alert_word ( "Error SetCommState", status );
            return ( FALSE );
      }

      if ( EnableCommNotification ( idCommDev, hWnd, 1, 1 ) == 0 )
      {      alert_string ( "Error EnableCommNotification" );
            return ( FALSE );
      }

      return ( TRUE );
}

In the window that receives the notification messages initiated with the EnableCommNotification() function you insert the following code (and expand it for your own needs).

case WM_COMMNOTIFY:
{      /* Deactivate screen saver */

      SendMessage ( GetTopWindow( 0 ), WM_KEYDOWN, 0, 0L );
      SendMessage ( GetTopWindow( 0 ), WM_KEYUP, 0, 0L );

      while ( ReadComm ( idCommDev, CommBuff, 1 ) == 1 )
      {      if ( CommBuff[0] <= 90 )
                  SendMessage ( GetFocus(), WM_CHAR, CommBuff[0], 0L );
      }

      return ( 0 );


On exit of the application do the following:

      if ( idCommDev >= 0 )
            CloseComm ( idCommDev );

PS: the 'alert_word()' function is a function I wrote to display a messagebox with a string and an integer.
0
 

Author Comment

by:emtk9702
ID: 1184068
The program will be operated from dos. Read process-data from the parallellport. Write to an powersupply with communication over RS232.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 1

Expert Comment

by:issamwd
ID: 1184069
I can help you controlling the parallel ports

the functions used :
outport();
inport();

these functions accepts a value and the address of the parallel port in decimal.
I can help you more in this field so if you are interested in knowing the specific addresses
& the pins numbers & their meaning you have just to e-mail me & I'll send you the answer
through this sight as an answer.
e-mail : issamwd@cyberia.net.lb
0
 
LVL 2

Accepted Solution

by:
jstolan earned 110 total points
ID: 1184070
I'm presuming that you are attempting this using 32-bit windows.  If not, some of the techniques discussed earlier will work fine.  If you are using 32 bit windows (95 or NT) you need to use the CreateFile function, then use standard File I/O functions such as WriteFile and ReadFile to communicate.  I quote below from the CreateFile help topic under Visual C++.

------------------------------------------------------------

Communications Resources
The CreateFile function can create a handle to a communications resource, such as the serial port COM1. For communications resources, the dwCreationDistribution parameter must be OPEN_EXISTING, and the hTemplate parameter must be NULL. Read, write, or read-write access can be specified, and the handle can be opened for overlapped I/O. For more information about communications, see Communications

---------------------------------------------------------------

The code snippet below shows how I used this for the serial port.  The parallel port is very similar, although without the baud rate and parity issues.  Note that this API gives extremely powerful capability for I/O multitasking and callback functionality.

----------------------------------------------------------------

BOOL OpenSerialPort(BOOL bMessages)
{
     // First check if we need a serial port, if we aren't
     // connected to anything we don't need it
     if( m_bConnectedToLabelPrinter || m_bConnectedToPC )
          {
          // Use cszTemp to define the comm port
          CString cszTemp ;
          cszTemp.FormatMessage( "COM%1!u!:", m_iComPort + 1 ) ;
          // Get a handle to the file using the selected comm port
          m_hndlComm = CreateFile(  cszTemp,
                                    GENERIC_READ | GENERIC_WRITE,
                                    0,
                                    NULL,
                                    OPEN_EXISTING,
                                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED ,
                                    NULL ) ;

          // If invalid, display the message "PrntInfc.cpp\nUnable to create serial port file"
          if( INVALID_HANDLE_VALUE == m_hndlComm )
               {
               if( bMessages ) AfxMessageBox( IDS_PERR1 ) ;
               return FALSE;
               }
          // Set parity string based on member variable
          CString cszParity;
          switch ( m_iParity )
               {
               case 0: { cszParity="N" ; break ; }
               case 1: { cszParity="O" ; break ; }
               case 2: { cszParity="E" ; break ; }
               case 3: { cszParity="S" ; break ; }
               case 4: { cszParity="M" ; break ; }
               }
 
          // Set Baud Rate based on member variable
          int m_iBaud ;
          switch ( m_iBaudRate )
               {
               case 0: { m_iBaud = 110 ; break ; }
               case 1: { m_iBaud = 300 ; break ; }
               case 2: { m_iBaud = 600 ; break ; }
               case 3: { m_iBaud = 1200 ; break ; }
               case 4: { m_iBaud = 2400 ; break ; }
               case 5: { m_iBaud = 4800 ; break ; }
               case 6: { m_iBaud = 9600 ; break ; }
               case 7: { m_iBaud = 14400 ; break ; }
               case 8: { m_iBaud = 19200 ; break ; }
               case 9: { m_iBaud = 38400 ; break ; }
               case 10: { m_iBaud = 56000 ; break ; }
               case 11: { m_iBaud = 128000 ; break ; }
               case 12: { m_iBaud = 256000 ; break ; }
               }
          // now use cszTemp to hold the BuildCommDCB control string
          cszTemp.FormatMessage("baud=%1!u! parity=%2!s! data=%3!u! stop=%4!u!",
                                 m_iBaud,
                                 cszParity,
                                 m_iDataBits+7,
                                 m_iStopBits+1) ;
          DCB myDCB;

          if( !BuildCommDCB( cszTemp,&myDCB ) )
               {
               DWORD dwError = GetLastError() ;
               cszTemp.FormatMessage( IDS_BUILDDCB_ERROR, dwError ) ;
               if( bMessages ) AfxMessageBox( cszTemp ) ;
               return FALSE;
               }
          myDCB.fOutxCtsFlow = TRUE;
          myDCB.fRtsControl = RTS_CONTROL_ENABLE;
          if( !SetCommState(m_hndlComm, &myDCB ) )
               {
               DWORD dwError = GetLastError() ;
               cszTemp.FormatMessage( IDS_SETSTATE_ERROR, dwError ) ;
               if( bMessages ) AfxMessageBox( cszTemp ) ;
               return FALSE;
               }
          if( !PurgeComm(m_hndlComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) )
               {
               DWORD dwError = GetLastError() ;
               cszTemp.FormatMessage( IDS_PURGECOMM_ERROR, dwError ) ;
               if( bMessages ) AfxMessageBox( cszTemp ) ;
               return FALSE;
               }
          COMMTIMEOUTS myCommTimeOuts;
          myCommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
          myCommTimeOuts.ReadTotalTimeoutMultiplier = 5 ;
          myCommTimeOuts.ReadTotalTimeoutConstant = 200 ;
          myCommTimeOuts.WriteTotalTimeoutMultiplier = 5 ;
          myCommTimeOuts.WriteTotalTimeoutConstant = 200 ;
          if( !SetCommTimeouts(m_hndlComm, &myCommTimeOuts) )
               {
               DWORD dwError = GetLastError() ;
               cszTemp.FormatMessage( IDS_SETCOMMTIMEOUTS_ERROR, dwError ) ;
               if( bMessages ) AfxMessageBox( cszTemp ) ;
               return FALSE;
               }
          return TRUE;
          }
     // Warn the user that we are in the hardware emulation mode
     if( m_bHardwareEmulation ) AfxMessageBox( IDS_NO_HARDWARE_WARNING );
     return FALSE;
}

DWORD Communicate(  LPSTR lpszSendBuffer,     // Pointer to character buffer to send
                    DWORD dwBytesToSend,      // Number of bytes to send
                    LPVOID lpReceiveBuffer,   // Pointer to object to receive (may be various types)
                    DWORD dwBytesToReceive,   // Number of bytes to receive
                    DWORD dwSeconds,          // Time in seconds to wait for a response
                    BOOL    bMessages )
{
     // Temporary string for messages and the like
     CString cszTemp;

     // Purge any comm stuff which may be remaining
     if( !PurgeComm( m_hndlComm,
                     PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) )
          {
          // Report any errors in the PurgeComm function and exit
          DWORD dwError = GetLastError() ;
          cszTemp.FormatMessage( IDS_PURGECOMM_ERROR3, dwError ) ;
          if( bMessages) AfxMessageBox( cszTemp ) ;
          return PR_COMMERROR;
          }

     // Initialize an OVERLAPPED structure to control timeouts more precisely
     OVERLAPPED ovrComm ;
     memset( &ovrComm, 0, sizeof( OVERLAPPED ) ) ;
     ovrComm.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ;
     if (ovrComm.hEvent == NULL)
          {
          // Report any errors in the CreateEvent function and exit
          if( bMessages) AfxMessageBox( IDS_CREATEEVENT_ERROR ) ;
          return PR_COMMERROR;
          }
     ResetEvent( ovrComm.hEvent ) ;

     // Write the bytes to the serial port
     DWORD dwBytesWritten ;
     DWORD dwActualBytesToSend ;
     DWORD dwBytesRemaining = dwBytesToSend ;
     // Keep track of total bytes sent
     DWORD dwTotalBytesSent = 0 ;
     do   {
          // Limit the bytes to send in ine shot to 100
          if( dwBytesRemaining <= 100 )
               {
               dwActualBytesToSend = dwBytesRemaining ;
               dwBytesRemaining = 0 ;
               }
          else {
               dwActualBytesToSend = 100 ;
               dwBytesRemaining -= 100 ;
               }
          // WriteFile will probably return TRUE after sending the bytes
          // since the message is short for most operations
          if( !WriteFile( m_hndlComm, lpszSendBuffer+dwTotalBytesSent, dwActualBytesToSend ,&dwBytesWritten, &ovrComm ) )
               {
               // But it may go here if there is an error
               DWORD dwError = GetLastError() ;
               // ERROR_IO_PENDING indicates the bytes are in the output que
               if( dwError != ERROR_IO_PENDING )
                    {
                    // If a different error occurs, report it and exit
                    cszTemp.FormatMessage( IDS_WRITEFILE_ERROR, dwError ) ;
                    if( bMessages) AfxMessageBox( cszTemp ) ;
                    return PR_COMMERROR;
                    }
               // Only wait the specified maximum time
               for( DWORD i = 1; i < (200*dwSeconds); i++ )
                    {
                    // Sleep for 5 milliseconds
                    Sleep( 5 ) ;
                    // Check if overlapped result is complete
                    COMSTAT myComStat ;
                    // ClearCommError allows us to check the output que
                    ClearCommError( m_hndlComm, &dwError, &myComStat ) ;
                    // If the output que is zero, the bytes have been sent
                    if( myComStat.cbOutQue == 0 )
                         {
                         dwBytesWritten = dwActualBytesToSend ;
                         i = 200 * dwSeconds;
                         }
                    }
               }
          dwTotalBytesSent += dwBytesWritten ;
          }
     while ( dwBytesRemaining > 0 ) ;
     dwBytesWritten = dwTotalBytesSent ;


     // Check to see if we left the loop because the bytes were sent
     // or because we timed out
     if( dwBytesWritten != dwBytesToSend )
          {
          // If we timed out, report the error and exit
          if( bMessages) AfxMessageBox( IDS_WRITETIMEOUT_ERROR ) ;
          return PR_COMMERROR;
          }
     // if dwBytesToReceive == 0,
     if( dwBytesToReceive == 0 ) return PR_OK ;

     // if dwBytesToReceive == 10000,
     // this means the size of the return buffer is not known
     BOOL bUndeterminedReceiveSize = FALSE ;
     if( dwBytesToReceive == 10000 )
          {
          // Set the flag, and set the bytes to receive to 1
          bUndeterminedReceiveSize = TRUE ;
          dwBytesToReceive = 1 ;
          }
     // Now wait for the printer to put bytes in the in que
     COMSTAT myComStat ;
     for( DWORD i = 1; i < (10*dwSeconds); i++ )
          {
          Sleep( 100 ) ;
          DWORD dwTemp;
          // Check if bytes in que matches bytes to receive
          ClearCommError( m_hndlComm, &dwTemp, &myComStat ) ;
          if( myComStat.cbInQue >= dwBytesToReceive) break;
          }
     // If the number of bytes is undetermined
     if( bUndeterminedReceiveSize )
          {
          // Wait 1 second after receiving first byte
          Sleep( 1000 ) ;
          DWORD dwTemp;
          // Get the total size of the received buffer
          ClearCommError( m_hndlComm, &dwTemp, &myComStat ) ;
          // Set the bytes to receive to the size of the buffer
          dwBytesToReceive = myComStat.cbInQue ;
          }
     // Check to see if we left the loop because we received
     // the bytes, or because we timed out
     if( myComStat.cbInQue < dwBytesToReceive )
          {
          // If we timed out, report the error and exit
          cszTemp.FormatMessage( IDS_READTIMEOUT_ERROR, 0 ) ;
          if( bMessages) AfxMessageBox( cszTemp ) ;
          return PR_COMMERROR;
          }

     // Now attempt to read the bytes
     memset( &ovrComm, 0, sizeof( OVERLAPPED ) ) ;
     ovrComm.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ;
     if (ovrComm.hEvent == NULL)
          {
          // Report any errors in the CreateEvent function and exit
          if( bMessages) AfxMessageBox( IDS_CREATEEVENT_ERROR ) ;
          return PR_COMMERROR;
          }
     ResetEvent( ovrComm.hEvent ) ;
     DWORD dwBytesRead ;
     // ReadFile should return immediately since there are bytes in the que
     if( !ReadFile( m_hndlComm, lpReceiveBuffer, dwBytesToReceive, &dwBytesRead, &ovrComm ) )
          {
          // If not, report the error and exit
          DWORD dwError = GetLastError() ;
          cszTemp.FormatMessage( IDS_READFILE_ERROR, dwError ) ;
          if( bMessages) AfxMessageBox( cszTemp ) ;
          return PR_COMMERROR;
          }
     // Check to see if all of the bytes were read
     if( dwBytesRead != dwBytesToReceive )
          {
          // Report the error with error code zero and exit
          cszTemp.FormatMessage( IDS_READFILE_ERROR, 0 ) ;
          if( bMessages) AfxMessageBox( cszTemp ) ;
          return PR_COMMERROR;
          }
     // Purge any remaining comm stuff
     if( !PurgeComm(m_hndlComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) )
          {
          // Report any errors in the PurgeComm function and exit
          DWORD dwError = GetLastError() ;
          cszTemp.FormatMessage( IDS_PURGECOMM_ERROR3, dwError ) ;
          if( bMessages) AfxMessageBox( cszTemp ) ;
          return PR_COMMERROR;
          }
     // Otherwise return
     return PR_OK ;
}


void CloseSerialPort(BOOL bMessages)
{
     // First check if have a serial port, if we aren't
     // connected to anything we don't need to do anything
     if( m_bConnectedToLabelPrinter || m_bConnectedToPC )
          {
          CString cszTemp ;
          // Clear Data Terminal Ready
          if( !EscapeCommFunction( m_hndlComm, CLRDTR ) )
               {
               DWORD dwError = GetLastError() ;
               cszTemp.FormatMessage( IDS_ESCAPECOMM_ERROR, dwError ) ;
               if( bMessages ) AfxMessageBox( cszTemp ) ;
               return ;
               }
          // Purge the communication port
          if( !PurgeComm(m_hndlComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) )
               {
               DWORD dwError = GetLastError() ;
               cszTemp.FormatMessage( IDS_PURGECOMM_ERROR2, dwError ) ;
               if( bMessages ) AfxMessageBox( cszTemp ) ;
               return ;
               }
          // Close the handle
          if( !CloseHandle(m_hndlComm ) )
               {
               DWORD dwError = GetLastError() ;
               cszTemp.FormatMessage( IDS_CLOSEHANDLE_ERROR, dwError ) ;
               if( bMessages ) AfxMessageBox( cszTemp ) ;
               return ;
               }
          }
     return ;
}
 



0
 

Author Comment

by:emtk9702
ID: 1184071
Adjusted points to 110
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Storage devices are generally used to save the data or sometime transfer the data from one computer system to another system. However, sometimes user accidentally erased their important data from the Storage devices. Users have to know how data reco…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
The viewer will learn how to successfully download and install the SARDU utility on Windows 7, without downloading adware.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now