Communication RS232 and parallell port

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?  
emtk9702Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

kellyjjCommented:
are we talking about dos? or windows?
0
paulsinnCommented:
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
emtk9702Author Commented:
The program will be operated from dos. Read process-data from the parallellport. Write to an powersupply with communication over RS232.
0
Newly released Acronis True Image 2019

In announcing the release of the 15th Anniversary Edition of Acronis True Image 2019, the company revealed that its artificial intelligence-based anti-ransomware technology – stopped more than 200,000 ransomware attacks on 150,000 customers last year.

issamwdCommented:
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
jstolanCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
emtk9702Author Commented:
Adjusted points to 110
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Software

From novice to tech pro — start learning today.