Thread: Serial Communications w/API

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    2

    Serial Communications w/API

    I have a need for read and write access a COM port for an application. It appears that MS Visual C++ and Visual Basic no longer support "conveinient" library functions for the COM port. As such I decided to build my own Communications Class with Window API functions found in windows.h. The experience would be good.

    The MSDN site is helpful to some extent, with a huge portion of the site dedicated to APIs. However, the examples frequently introduce new terminology and concepts, of which I am woefully unfamiliar, i.e. threads, that produces more questions per line of code than anything else. Conceptually it sounds like threads behave as hardware interrupts. What say you?

    I can open and close COM1: and setup the DCB and TimeOuts, which is all fairly straight forward. Using WriteFile, the recommended method to write to the port, I receive a persistent error code (5) from GetLastError(). The decoded meaning is "Access Denied". What could be causing this error?

    According to MSDN literature, API functions like WriteFile and ReadFile have a pointer to a structure in their parameter list called OVERLAPPED. Windows CE requires NULL for the structure pointer because it does not support overlapping (asynchronus operation of RX and TX sides). Does Windows-XP allow for NULL pointer to OVERLAPPED if the application needs only synchronus TX/RX capability? I wonder if this might be contributing to the cause of error-5.

    In past months I've seen a coule of homebrew classes for communications using the API, but I don't fully understand what the authors intent, so prefer to avoid implementing something I can't support.

    Your constructive comments would be greatly appreciated.

    Regards,
    J=K

    Saints have a past and Sinners have a future.

  2. #2
    It's full of stars adrianxw's Avatar
    Join Date
    Aug 2001
    Posts
    4,829
    Difficult to say from the info you've given. Assuming your handle is valid, does it have write access to the port? Are all the parameters you are passing to WriteFile() correct? Are the OVERLAPPED elements correct? Silly things like passing a value rather then a pointer to the value can give error 5.

    The interpretation of a NULL value to the OVERLAPPED structure pointer depends on the flags set when building the HANDLE, which you don't describe.

    All manner of possibilities really.
    Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream.

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    2
    Here is the code. Thanks for taking the time to have a look at it.

    Regards,
    John


    Code:
    ///////////////////////////////////
    // Communications Class 
    // Communications.h
    ///////////////////////////////////
    
    #define COMMUNICATIONS_H
    
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    class Communications
    {
    
    private:
    
    	HANDLE CommPortHandle;
    
    	DCB dcb;
    
    	DCB *pdcb;
    
    public:
    
    	void OpenCommPort(void);			// opens COM1:
    
    	void CloseCommPort(void);			// closes COM1:
    
    	HANDLE GetCommPortHandle(void);		// returns the COM1: handle
    
    	void BuildDCB(void);				// sets DCB parameters
    
    	void BuildTimeOuts(void);			// sets COM1: timeouts
    
    	bool SendTestString(void);			// sends a test string to COM1:
    };
    #endif
    
    
    ///////////////////////////////////
    // Communications Class 
    // Communications.cpp
    ///////////////////////////////////
    
    #include "Communications.h"
    
    /////////////////////////////////////////////////////////////////////////
    void Communications::OpenCommPort(void)
    // Opens COM1: for reading and writing. If CreateFile is successful,
    // a pointer to the port is stored in CommPortHandle (private). Otherwise,
    // the pointer is saved as zero. The function reports verbose indications 
    // of success or failure.
    {
    	char comport[]="COM1:";
    	HANDLE x=0;
    
    	  x = CreateFile(comport,						// pointer to name of the file
    					 GENERIC_READ || GENERIC_WRITE, // access (read-write) mode
    					 0,								// share mode
    					 NULL,							// pointer to security attributes
    					 OPEN_EXISTING,					// how to create
    					 FILE_ATTRIBUTE_NORMAL,			// port attributes
    					 NULL);							// handle to file with attributes to copy
    	if(!x)
    		{
    			cout<<"Error Opening COM1:"<<endl;
    			CommPortHandle=0;
    		}
    	else
    		{
    			cout<<"COM1: Opened Successfully"<<endl;
    			CommPortHandle=x;
    		}
    }
    /////////////////////////////////////////////////////////////////////////
    HANDLE Communications::GetCommPortHandle(void)
    // returns the handle to this COM port.
    {
    	return(CommPortHandle);
    
    // report back
    	cout<<"Handle Returned"<<endl;
    }
    /////////////////////////////////////////////////////////////////////////
    void Communications::CloseCommPort(void)
    // this function closes the comport and sets CommPortHandle=0
    {
    	CloseHandle(CommPortHandle);
    	CommPortHandle=0;
    
    // report back
    	cout<<"Port Closed"<<endl;
    }
    /////////////////////////////////////////////////////////////////////////
    void Communications::BuildDCB(void)
    // this function set DCB parameters
    {
    
    // create DCB objects
    	DCB dcb, *pdcb;
    
    // set the dcb pointer
    	pdcb=&dcb;
    
    // define the variables in the dcb object
    	dcb.DCBlength=sizeof(dcb);
    	dcb.BaudRate=300;
    	dcb.fBinary=true;
    	dcb.fParity=false;
    	dcb.fOutxCtsFlow=false;
    	dcb.fOutxDsrFlow=false;
    	dcb.fDtrControl=DTR_CONTROL_ENABLE;
    	dcb.fDsrSensitivity=false;
    	dcb.fTXContinueOnXoff=true;
    	dcb.fOutX=false;
    	dcb.fInX=false;
    	dcb.fErrorChar=false;
    	dcb.fNull=true;
    	dcb.fRtsControl=RTS_CONTROL_ENABLE;
    	dcb.fAbortOnError=false;
    	// dcb.fDummy2 do not use
    	dcb.wReserved=0;
    	dcb.XonLim=1;
    	dcb.XoffLim=1;
    	dcb.ByteSize=8;
    	dcb.Parity=NOPARITY;
    	dcb.StopBits=1;
    	dcb.XonChar=0;
    	dcb.XoffChar=0;
    	dcb.ErrorChar=0;
    	dcb.EofChar=0;
    	dcb.EvtChar='&';
    	// dcb.wReserved do not use
    
    //set the COM1: according to dcb parameters 
    	SetCommState(CommPortHandle,pdcb);	
    
    // report back
    	cout<<"DCB Built"<<endl;
    }
    /////////////////////////////////////////////////////////////////////////
    void Communications::BuildTimeOuts(void)
    // this function set the COM1: timeouts
    
    {
    // create COMMTIMEOUTS object
    	COMMTIMEOUTS cto;
    
    // set comm timeout variables here
    	cto.ReadIntervalTimeout=MAXWORD;
    	cto.ReadTotalTimeoutConstant=0;
    	cto.ReadTotalTimeoutMultiplier=0;
    	cto.WriteTotalTimeoutConstant=2000;
    	cto.WriteTotalTimeoutMultiplier=0;
    
    // set the COM1: timeouts
    	SetCommTimeouts(CommPortHandle,&cto);
    
    // report back
    	cout<<"Timeouts Set"<<endl;
    }
    /////////////////////////////////////////////////////////////////////////
    
    bool Communications::SendTestString(void)
    {
    	bool result=false;
    
    	DWORD n, txresult;
    		
    	unsigned long int byteswritten=0;
    
    	char *str;        
    
    	str="This is a test of the serial communications port.";
    
    	n=strlen(str);
    
    	cout<<"The test string is "<<n<<" characters long\n";
    
    	cout<<"Started Writing...\n";
    
    	txresult=WriteFile(CommPortHandle,str,n,&byteswritten,0);
    
    	DWORD LE=GetLastError(); // always returns with 5 (ERROR_ACCESS_DENIED)
    
    	cout<<"GetLastError()="<<LE<<"\n";	
    
    	cout<<"txresult is "<<txresult<<"\n";
    
    	return result;
    }
    
    ///////////////////////////////////
    // Communications Class Testbed
    // commtest.cpp
    ///////////////////////////////////
    #include "Communications.h"
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    void main()
    {
    // create a Communications object
    	Communications c;
    
    // open the port
    	c.OpenCommPort();
    
    // build the DCB
    	c.BuildDCB();
    
    // build the timeouts
    	c.BuildTimeOuts();
    
    // send a test string to COM1:
    
    	c.SendTestString();
    
    // close the port
    	c.CloseCommPort();
    
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. serial port to poll on request
    By infineonintern in forum C++ Programming
    Replies: 2
    Last Post: 06-11-2009, 06:52 AM
  2. Serial Communications with win32 api
    By Blackthorne in forum C Programming
    Replies: 1
    Last Post: 01-26-2003, 12:45 PM
  3. DOS, Serial, and Touch Screen
    By jon_nc17 in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 01-08-2003, 04:59 PM
  4. Serial communications problem.
    By papudi in forum C Programming
    Replies: 1
    Last Post: 10-11-2002, 04:23 PM
  5. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM