Solved

Serial Port Programming with Visual C

Posted on 2004-03-22
21
988 Views
Last Modified: 2012-05-04
I was wondering how to open, read and write to a serial port in Visual C 6? I have read the technical article in MSDN and do not really understand it. I was wondering if there is an easier way to read and write to the serial ports with minimal amounts of code?
0
Comment
Question by:changw414
  • 9
  • 7
  • 2
  • +1
21 Comments
 

Author Comment

by:changw414
Comment Utility
Oh by the way im on a Win XP machine.
0
 
LVL 17

Assisted Solution

by:mokule
mokule earned 100 total points
Comment Utility
Hi

m_hPort = ::CreateFile(m_sPort,      GENERIC_READ | GENERIC_WRITE,0, NULL,
                                     OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
if( GetCommState(m_hPort, &dcbPort) )
      {
                  dcbPort.BaudRate = atoi(m_sBody);
                  dcbPort.ByteSize = 8;
                  dcbPort.Parity = NOPARITY;
                  dcbPort.StopBits = ONESTOPBIT;
                        if(SetCommState(m_hPort, &dcbPort))
                        {
                                                                }
                 }


WriteFile(m_hPort, buf, ile, &nWyslane, NULL);
ReadFile(m_hPort, buf, ile, &nOdebrane, NULL);
0
 
LVL 6

Accepted Solution

by:
joghurt earned 25 total points
Comment Utility
Well, the above example is basically OK. However, if there's not enough characters waiting in the input queue, your program will wait until the data arrives (or wait forever, if it won't). You can use the SetCommTimeouts function to set these time-out values.

And what's missing from the above code:
HANDLE m_hPort;
char m_sPort[] = "COM1:";
DCB dcbPort;
etc.

If you want to use more than 8 serial ports, use the syntax of "\\.\COM10" instead.
0
 

Author Comment

by:changw414
Comment Utility
thx, u were a great help!!!
0
 
LVL 17

Expert Comment

by:mokule
Comment Utility
Hi changw414
If we were any help to u
You have five choices when it comes to closing your open questions....
http://www.experts-exchange.com/help.jsp#hs5
 
0
 
LVL 17

Expert Comment

by:mokule
Comment Utility
Hi changw414
r u sure that u accepted good answer
0
 
LVL 6

Expert Comment

by:joghurt
Comment Utility
mokule, neither do I think so. Sorry.
0
 
LVL 17

Expert Comment

by:mokule
Comment Utility
thank you joghurt.
0
 

Author Comment

by:changw414
Comment Utility
Yes his answer was very helpful. I figured out what I needed to do, Thanks...
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 17

Expert Comment

by:mokule
Comment Utility
changw414
Just for curiosity. Could You explain me what information from whose answer was very helpful. I'll be happy to know that You choose what You want to.
0
 

Author Comment

by:changw414
Comment Utility
both joghurt and moukle
0
 
LVL 17

Expert Comment

by:mokule
Comment Utility
so why didn't u split points?
0
 

Author Comment

by:changw414
Comment Utility
i didnt know how? Im new to this site.
0
 
LVL 17

Expert Comment

by:mokule
Comment Utility
I'm also rather new. May be for that reason I'm so unhappy ;-) that u gave all points to joghurt and nothing to me. Generally I'm  curious whether it is possible to change ur mind afteri accepting some answer?

for splitting points or other informations read this
http://www.experts-exchange.com/Programming/Programming_Languages/C/help.jsp#hi19
0
 
LVL 17

Expert Comment

by:mokule
Comment Utility
0
 

Author Comment

by:changw414
Comment Utility
can i still split the points still?
0
 
LVL 17

Expert Comment

by:mokule
Comment Utility
Not just simply split now, I think.
You should follow the link in my previous message.
0
 

Author Comment

by:changw414
Comment Utility
yes please i wanna split it half and half, cause both tips were very helpful, I read your FAQ but I still dont see where to split the points.
0
 

Expert Comment

by:Mamata_gd
Comment Utility
#include "stdio.h"
#include <windows.h>
#include <process.h>
#include <time.h>
#include <string.h>


int GetChksm(char *, int );
unsigned _stdcall WorkerThread(void);
void SetCommParameters(HANDLE);
bool openCommandFile();
bool writetoLogFile(CHAR *);
bool InitializeController();

#define MAX_MESSAGE            256
#define STX                        0x02
#define ETX                        0x03
#define MAX_IOC_MSG_LEN 240

int i;
HANDLE hComm, hMutex,hEvent;
CHAR CommandQ[35][MAX_MESSAGE];
volatile CHAR bridgebuffer[MAX_MESSAGE];
UCHAR seqNum = 'a';

main()
{
      HANDLE hThread = 0;
      CHAR buffer[MAX_MESSAGE];
      DWORD threadID,dwSomeData = 42;
      CHAR *pCommand,*pResponse;
      const char *portName = "COM3";
      UCHAR length;
      int j = 0;
                  
      if ( !openCommandFile() )
      {
            printf("Can not Create and open the file\n");
            return 0;
      }

      // Create the communication port
      hComm = CreateFile( portName,                                // Specify port device: default "COM1"
                                    GENERIC_READ | GENERIC_WRITE, // Specify mode that open device.
                                    0,                            // the devide isn't shared.
                                    NULL,                         // the object gets a default security.
                                    OPEN_EXISTING,                // Specify which action to take on file.
                                    0,                            // default.
                                    NULL);                        // default.

      if ( INVALID_HANDLE_VALUE == hComm )
      {
            printf("Communication handle could not create properly\n");
            return 0;
      }

      SetCommParameters(hComm);

    // Create the Synchronizaton object, called hMutex
      hMutex = CreateMutex(0,    // Security attrubutes
                                    FALSE, // Do not own the Mutex
                                    0);    // Nameless mutex

      if ( 0 == hMutex )
      {
            CloseHandle(hComm);
            return 0;
      }

      hEvent = CreateEvent(NULL,      // No security
                                    TRUE,      // Manual Reset
                                    FALSE,  // Initial state in not signaled
                                    NULL);  // No name to event

      if ( NULL == hEvent )
      {
            CloseHandle(hComm);
            CloseHandle(hMutex);
            return 0;
      }


      if ( !InitializeController() )
      {
            CloseHandle(hComm);
            CloseHandle(hMutex);
            CloseHandle(hEvent);
            return 0;
      }
      
      // Create and start the thread
      hThread = CreateThread( NULL, // Can not be inherited
                                          0,        // Default stack size
                                          (LPTHREAD_START_ROUTINE) WorkerThread, // Thread start function name
                                          NULL,                                                // No parameter passed
                                          0,                        
                                          &threadID);

      if ( hThread == 0 )
      {
            printf("Thread can not be created\n");
            CloseHandle(hComm);
            CloseHandle(hMutex);
            CloseHandle(hEvent);
            return 0;
      }

      // Go in loop till end of file.
      while (1)
      {
            printf("Enter the command: ");
            
            if ( fgets(&buffer[3],(MAX_MESSAGE-6),stdin) != NULL )
            {
                  if ((pCommand = strchr(&buffer[3], '\n')) != NULL)
                        *pCommand = '\0';
            }
            if ( !strcmp("quit",&buffer[3]) )
                  break;
   
            // Attach header
            pCommand = &buffer[0];
            *pCommand = STX;
            *(pCommand+1) = '0';
            *(pCommand+2) = seqNum;
            if ( seqNum == 't' )
                  seqNum = 'a';
            else
                  seqNum++;

            pResponse = strchr(pCommand,'\0');
            length = pResponse-pCommand;

            
            // Calculate checksum and attach trailer
            sprintf(&buffer[length],"%02x",GetChksm(buffer,length));
            buffer[length+2] = ETX;
            buffer[length+3] = '\0';


            // Aquire the Mutex
            WaitForSingleObject(hMutex,INFINITE);
            // Copy the command string into the Sendbuffer
            strncpy((char *)&bridgebuffer[0],buffer,strlen(buffer));
            //printf("String is %s and length %d \n",(char*)bridgebuffer,strlen((char *)bridgebuffer));
            // Relase the Mutex
            ReleaseMutex(hMutex);

            SetEvent(hEvent);

            Sleep(2000);
      }
      // Terminate thread

      // Close all the handles
      CloseHandle(hComm);

      CloseHandle(hThread);

      CloseHandle(hMutex);
      
      return 0;
}
      

int GetChksm(char *buf, int len)
{
      unsigned int total = 0, i;
      
      if (len < 4 || len >= MAX_IOC_MSG_LEN)
            return 0;
      
      for (i = total = 0; i < len; i++)
            total += *buf++;

      return ((~total) & 0xff);
}

#define EIGHT_SECONDS 2000

unsigned _stdcall WorkerThread()
{
      bool bResult;
      CHAR Sendbuffer[MAX_MESSAGE];
      CHAR Recvbuffer[MAX_MESSAGE];
      ULONG nbytes;
//      time_t   start, finish;
      UCHAR length;
      char *p;
      DWORD dwRes;

      // Start the time
      //time(&start);
      while (1)
      {
            // Loop till buffer gets some date to 8 seconds expires
            dwRes = WaitForSingleObject(hEvent,EIGHT_SECONDS);

            switch ( dwRes )
            {
                  case WAIT_OBJECT_0:
                        //Aquire the n=mutex
                        WaitForSingleObject(hMutex,INFINITE);
                        // Copy to senbuffer
                        strncpy(Sendbuffer,(char *)&bridgebuffer[0],strlen((char *)bridgebuffer));
                        // Fill the memory with NULL
                        strnset( (char *)&bridgebuffer[0], 0, MAX_MESSAGE );
                        // Release the Mutex
                        ReleaseMutex(hMutex);
                        // Get the length of command string
                        if ( ( p = strchr((char *)&Sendbuffer[0],ETX) ) != NULL )
                              length = p - ( (char *)&Sendbuffer[0] );

                        break;

                  case WAIT_TIMEOUT :
                        Sendbuffer[0] = STX;
                        Sendbuffer[1] = '0';
                        Sendbuffer[2] = 't';
                        Sendbuffer[3] = 'Z';
                        sprintf(&Sendbuffer[4],"%02x",GetChksm(Sendbuffer,4));
                        Sendbuffer[6] = ETX;

                        length = 7;
                        // And send the 'Z' command
                        break;
                  default :
                        printf("Error in WaitForSingleObject\n");
                        ExitThread(0);
            }

            ResetEvent(hEvent);
            
            // Start the counter again
            //time(&start);
            
            if ( writetoLogFile(Sendbuffer) )
            {
                  bResult  = WriteFile(hComm,                  // handle to file to write to
                                Sendbuffer,                        // pointer to data to write to file
                                length,             // number of bytes to write
                                &nbytes,NULL);   // pointer to number of bytes written
                  if ( FALSE == bResult)
                  {
                        printf("Writing of serial communication has problem.");
                        return FALSE;
                  }


                  // Wait for response in loop
                  nbytes = 0;
                  strnset(&Sendbuffer[0],0,MAX_MESSAGE);
                  strnset(&Recvbuffer[0],0,MAX_MESSAGE);
                  //Sleep(1000);
                  while (1)
                  {
                        Sleep(1000);
                        bResult = ReadFile(hComm,            // handle of file to read
                                            Recvbuffer,           // handle of file to read
                                            MAX_MESSAGE,      // number of bytes to read
                                            &nbytes,          // pointer to number of bytes read
                                            NULL);              // pointer to structure for data
                        if ( NULL == bResult )
                        {
                              printf("Reading of serial communication has problem.");
                              return FALSE;
                        }
                        if ( nbytes )
                        {
                              //printf("String = %s and length = %d\n",Recvbuffer,nbytes);
                              break;
                        }
                  }

                  bResult = writetoLogFile(Recvbuffer);
                  if ( 0 == bResult )
                  {
                        printf("Could not write the data to log file\n");
                        return 0;
                  }
            }
      }
      return 0;
}

void SetCommParameters(HANDLE hComm)
{
      DCB dcb = {0};
      DCB config;
//      DWORD dwCommEvent=0;
      COMMTIMEOUTS timeouts;

      if ( !GetCommTimeouts(hComm,&timeouts) )
            printf("Error getting Communication timeout\n");

//      timeouts.ReadIntervalTimeout = MAXDWORD;
      timeouts.ReadIntervalTimeout = 20;
      timeouts.ReadTotalTimeoutMultiplier = 3;
      timeouts.ReadTotalTimeoutConstant = 2;
      timeouts.WriteTotalTimeoutMultiplier = 3;
      timeouts.WriteTotalTimeoutConstant = 2;

      printf("ReadTimeIntervaltimeOut = %d\n",timeouts.ReadIntervalTimeout);
      printf("ReadTotalTimeoutMultiplier = %d\n",timeouts.ReadTotalTimeoutMultiplier);
      printf("ReadTotalTimeoutConstant = %d\n",timeouts.ReadTotalTimeoutConstant);
      printf("WriteTotalTimeoutMultiplier = %d\n",timeouts.WriteTotalTimeoutMultiplier);
      printf("WriteTotalTimeoutConstant = %d\n",timeouts.WriteTotalTimeoutConstant);


      if ( !SetCommTimeouts(hComm,&timeouts) )
            printf("Error Setting Communication Timeouts\n");
                                                                  
      if (!GetCommState(hComm, &dcb))
       // Error getting current DCB setting
         printf("Error getting current status\n");
    else
       // DCB is ready for use.
    {
          printf("BaudRate = %d StopBits = %d Parity %d and ByteSize = %d\n",
                                                 dcb.BaudRate,    // Specify buad rate of communicaiton.
                                                 dcb.StopBits,    // Specify stopbit of communication.
                                                dcb.Parity,      // Specify parity of communication.
                                                dcb.ByteSize);   // Specify  byte of size of communication.
          config = dcb;

          config.BaudRate = CBR_38400;
          config.StopBits = ONESTOPBIT;
          config.Parity = NOPARITY;
          config.ByteSize = 8;

          if ( SetCommState(hComm, &config))
            {
                if (GetCommState(hComm, &dcb) )
                        printf("BaudRate = %d StopBits = %d Parity %d and ByteSize = %d\n",
                                                            dcb.BaudRate,    // Specify buad rate of communicaiton.
                                                            dcb.StopBits,    // Specify stopbit of communication.
                                                            dcb.Parity,      // Specify parity of communication.
                                                            dcb.ByteSize);   // Specify  byte of size of communication.
            }
      }

}

bool openCommandFile()
{
      HANDLE hCommandFile=0;
      ULONG numberofbytes;//,nbytes;
      //bool bResult;
      CHAR buffer[MAX_MESSAGE];
      CHAR *pCommand;

      // Open the file where command strings are stored
      hCommandFile = CreateFile("c:\\ggg\\sioccmd\\command.txt",
                              GENERIC_READ|GENERIC_WRITE,
                              FILE_SHARE_READ,
                              NULL,                        // secuity
                              OPEN_EXISTING,            // existing always
                              0,0);

      // If CreateFile is unsuccessful
      if ( INVALID_HANDLE_VALUE == hCommandFile )
      {
            printf("Can not open the file and error = %d\n",GetLastError());
            return 0;
      }
      else
      {
            printf("File has been created successfully\n");
            printf("Handle = %p\n",hCommandFile);
      }

      int i = 0;
      int j = 0;
      int iFilePointer = 0;
      // read the file
      while ( (ReadFile(hCommandFile,&buffer[0],MAX_MESSAGE,&numberofbytes,NULL)) && numberofbytes )
      {
            while ( numberofbytes )
            {
                  // Find the line feed and replace with null character
                  if ( (pCommand = strchr( &buffer[i],'\n')) != NULL )
                  {
                        *(pCommand-1) = '\0';
                        strncpy( (char*)(CommandQ+j),&buffer[i],strlen(&buffer[i]));
                  }
                  else
                  {
                        iFilePointer += i;
                        if ( 0xFFFFFFFF == SetFilePointer(hCommandFile,iFilePointer,NULL,FILE_BEGIN) )
                        {
                              printf("Can not set the pointer\n");
                              return 0;
                        }
                        i = 0;
                        break;
                  }
                  pCommand++;
                  numberofbytes = numberofbytes-(pCommand - (&buffer[i]) );
                  i += (pCommand - (&buffer[i]) );
                  j++;      
            }
      }

      return 1;
}
                  
bool writetoLogFile(CHAR *buf)
{
      SYSTEMTIME st;
      char logData[280];
      FILE *fp;
//      char *p;
      
      GetLocalTime(&st);

      GetDateFormat( 0, 0, &st, "ddd',' MMM dd,yy",logData, sizeof(logData) );
      GetTimeFormat( 0, 0, &st, "  hh':'mm':'ss tt", logData+14, sizeof(logData) );

      strcat(logData," cmd/rsp: \0");

      for (;;)
      {
            if ( *buf >= 33 )
                  strncat(logData,buf,1);
            else if ( *buf >= 0 && *buf <= 32 )
            {
                  char aa[4];
                  sprintf(aa,"<%02d>",*buf);
                  strncat(logData,aa,4);
                  if ( * buf == ETX )
                        break;
            }
            buf++;
      }
            
      fp = fopen("c:\\ccc\\sioccmd\\log.txt","a+");
      fprintf(fp,"%s\n",logData);
      fclose(fp);

      return 1;
}


bool InitializeController()
{
      bool bResult;
      CHAR Sendbuffer[MAX_MESSAGE];
      CHAR Recvbuffer[MAX_MESSAGE];
      char *pCommand,*pResponse;
      ULONG nbytes;
      int stringlength,j = 0;

      while (1)
      {
            stringlength = strlen((char*)(CommandQ+j));
            strncpy(&Sendbuffer[3], (char*)(CommandQ+j),stringlength+1);
            
            
            if ( !(strcmp("quit",(char*)(CommandQ+j) ) ) )
                  break;

            j++;


            // Attach header
            pCommand = &Sendbuffer[0];
            *pCommand = STX;
            *(pCommand+1) = '0';
            *(pCommand+2) = seqNum;
            if ( seqNum == 't' )
                  seqNum = 'a';
            else
                  seqNum++;
            pResponse = strchr(pCommand,'\0');
            stringlength = pResponse-pCommand;

            
            // Calculate checksum and attach trailer
            sprintf(&Sendbuffer[stringlength],"%02x",GetChksm(Sendbuffer,stringlength));
            Sendbuffer[stringlength+2] = ETX;
            Sendbuffer[stringlength+3] = '\0';

            if ( writetoLogFile(Sendbuffer) )
            {
                  bResult  = WriteFile(hComm,                  // handle to file to write to
                                Sendbuffer,                        // pointer to data to write to file
                                stringlength+3,           // number of bytes to write
                                &nbytes,NULL);                  // pointer to number of bytes written
                  if ( FALSE == bResult)
                  {
                        printf("Writing of serial communication has problem.");
                        return FALSE;
                  }


                  // Wait for response in loop
                  nbytes = 0;
                  strnset(&Sendbuffer[0],0,MAX_MESSAGE);
                  strnset(&Recvbuffer[0],0,MAX_MESSAGE);
                  
                  while (1)
                  {
                        Sleep(1000);
                        bResult = ReadFile(hComm,            // handle of file to read
                                            Recvbuffer,           // handle of file to read
                                            MAX_MESSAGE,      // number of bytes to read
                                            &nbytes,          // pointer to number of bytes read
                                            NULL);              // pointer to structure for data
                        if ( FALSE == bResult )
                        {
                              printf("Reading of serial communication has problem.");
                              return FALSE;
                        }
                        if ( nbytes )
                        {
                              //printf("String = %s and length = %d\n",Recvbuffer,nbytes);
                              break;
                        }
                  }

                  bResult = writetoLogFile(Recvbuffer);
                  if ( 0 == bResult )
                  {
                        printf("Could not write the data to log file\n");
                        return 0;
                  }
            }
      }
      return TRUE;
}
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

744 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

13 Experts available now in Live!

Get 1:1 Help Now