|
Introduction
The purpose of this article is to demonstrate the use of Win32 functions for serial port communication in Visual C++. A C++ class CSyncSerialComm has been developed to implement the following serial port communication operations:
- Open
- Configuration
- Read
- Write
- Close
A background in Visual C++ programming is sufficient to grasp the technical details of this article. Access to MSDN is required for looking at the definition of functions, structures etc. used in this article. The article takes a look at only non-overlapped (synchronous) operations supported by Win32. My next article will show implementation of serial port communication using overlapped (asynchronous) structures.
I. Open
Before starting any communication on a serial port, we must first open a connection. This is achieved by using CreateFile function in Win32. (Those of you familiar with File I/O must be aware of this function.) The following code is used to open a serial port connection in non-overlapped mode. m_hSerialComm = CreateFile(m_pszPortName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISITING,
0,
NULL);
if (m_hSerialComm == INVALID_HANDLE_VALUE)
The CreateFile function takes in seven parameters. (Please take a brief moment to look at this function in MSDN.)
- The first parameter specifies the port name. In our case, this is usually COM, COM2, COM3 or COM4.
- The second parameter must be
GENERIC_READ | GENERIC_WRITE to support both read and write access.
- The third parameter must always be 0 for serial port communication because unlike files, serial port access cannot be shared.
- The fourth parameter is used to set security attributes. If no security attribute needs to be specified, just use
NULL.
- The fifth parameter must always be set to
OPEN_EXISTING.
- The sixth parameter is used to specify flags and attributes (either 0 or
FILE_ATTRIBUTE_NORMAL can be used).
- The last parameter must always be
NULL as we only support non-overlapped communication.
The HANDLE m_hSerialComm that is returned by the CreateFile function can now be used for performing operations like Configure, Read and Write.
II. Configuration
After opening connection to a serial port, the next step is usually to configure the serial port connect settings like Baud Rate, Parity Checking, Byte Size, Error Character, EOF Character etc. Win32 provides a DCB struct that encapsulates these settings (refer to MSDN for DCB struct definition). Configuration of the serial port connection settings is performed in the following three steps:
- First, we have to access the present settings of the serial port using the
GetCommState function. The function takes in two parameters:
- The first parameter is the
HANDLE we received from the call to the CreateFile function.
- The second parameter is an output parameter, which returns the
DCB structure containing the present settings.
- Next, using the
DCB structure that we obtained from the previous step, we can modify the necessary settings according to the application needs.
- Finally, we update the changes by using the
SetCommState method.
The following code is a sample shown explaining the use of these functions. (Note: A number of the fields in the DCB struct are not used in the example. A more sophisticated application must allow the client to configure these settings.) DCB dcbConfig;
if(GetCommState(m_hSerialComm, &dcbConfig))
{
dcbConfig.BaudRate = dwBaudRate;
dcbConfig.ByteSize = 8;
dcbConfig.Parity = NOPARITY;
dcbConfig.StopBits = ONESTOPBIT;
dcbConfig.fBinary = TRUE;
dcbConfig.fParity = TRUE;
}
else
if(!SetCommState(m_hSerialComm, &dcbConfig))
Another important part of configuration of serial port connection settings is setting timeouts. Again, Win32 provides a COMMTIMEOUTS struct for setting Read and Write Timeouts. We are also provided with two functions GetCommTimeouts and SetCommTimeouts to access, modify, and update the timeout settings. The following code can be used to set the serial port timeouts: COMMTIMEOUTS commTimeout;
if(GetCommTimeouts(m_hSerialComm, &commTimeout))
{
commTimeout.ReadIntervalTimeout = 1000 * dwReadTimeOutIntervalInSec;
commTimeout.ReadTotalTimeoutConstant = 1000 * dwReadTimeOutConstantInSec;
commTimeout.ReadTotalTimeoutMultiplier = 1000 * dwReadTimeOutMultiplier;
commTimeout.WriteTotalTimeoutConstant = 1000 * dwWriteTimeOutInSec;
commTimeout.WriteTotalTimeoutMultiplier = 1000 * dwWriteTimeOutMultiplier;
}
else
if(!SetCommTimeouts(m_hSerialComm, &commTimeout))
III. Read
There are many different implementations for reading from a Serial Port Connection. In the CSyncSerialComm class that is provided with this article, serial communication events are used in the implementation of the Read operation. There are three important sets in this implementation.
- First, we setup a
Read Event using the SetCommMask function. (Note: This function can also be used to set many other different types of serial communication events.) This event is fired when a character is read and buffered internally by Windows Operating System. The SetCommMask function takes in two parameters:
- The first parameter is the
HANDLE we received from the call to the CreateFile function.
- The second parameter is used to specify the event type. To specify a
Read Event, we use EV_RXCHAR flag.
- After calling the
SetCommMask function, we call the WaitCommEvent function to wait for the event to occur. This function takes in three parameters:
- The first parameter is the
HANDLE we received from the call to the CreateFile function.
- The second parameter is an output parameter, which reports the event type that was fired.
- The third parameter is a pointer to an
OVERLAPPED structure. Since, our implementation is for Non-Overlapped communication, it must be set to NULL.
- Once this event is fired, we then use the
ReadFile function to retrieve the bytes that were buffered internally. The ReadFile function takes in five parameters:
- The first parameter is the
HANDLE we received from the call to the CreateFile function.
- The second parameter is a buffer that would receive the bytes if the
ReadFile function returns successfully.
- The third parameter specifies the size of our buffer we passed in as the second parameter.
- The fourth parameter is an output parameter that will notify the user about the number of bytes that were read.
- The last parameter is always
NULL for our purpose since we do not deal with non-overlapped mode.
In our example, we read one byte at a time and store it in a temporary buffer. This continues until the case when ReadFile function returns successfully and the fourth parameter has a value of 0. This indicates that the internal buffer used by Windows OS is empty and so we stopping reading. The following code shows the implementation of this technique: std::stringbuf sb;
DWORD dwEventMask;
if(!SetCommMask(m_hSerialComm, EV_RXCHAR))
if(WaitCommEvent(m_hSerialComm, &dwEventMask, NULL))
{
char szBuf;
DWORD dwIncommingReadSize;
do
{
if(ReadFile(m_hSerialComm, &szBuf, 1, &dwIncommingReadSize, NULL) != 0)
{
if(dwIncommingReadSize > 0)
{
dwSize += dwIncommingReadSize;
sb.sputn(&szBuf, dwIncommingReadSize);
}
}
else
} while(dwIncommingReadSize > 0);
}
else
IV. Write
Write operation is easier to implement than Read. It involves using just one function, WriteFile. It takes in five parameters similar to ReadFile function. The second parameter in WriteFile specifies the buffer to be written to the serial port. The following example shows implementation of Write using WriteFile. It writes one byte at a time until all the bytes in our buffer are written: unsigned long dwNumberOfBytesSent = 0;
while(dwNumberOfBytesSent < dwSize )
{
unsigned long dwNumberOfBytesWritten;
if(WriteFile(m_hSerialComm, &pszBuf[dwNumberOfBytesSent], 1,
&dwNumberOfBytesWritten, NULL) != 0)
{
if(dwNumberOfBytesWritten > 0)
++dwNumberOfBytesSent;
else
}
else
}
V. Close
After we finish all our communication with the serial port, we have to close the connection. This is achieved by using the CloseHandle function and passing in the serial port HANDLE we obtained from the CreateFile function call. Failure to do this results in hard to find handle leaks. The follow code snippet explains the use of this function: if(m_hSerialComm != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hSerialComm);
m_hSerialComm = INVALID_HANDLE_VALUE;
}
Conclusion
I hope my demonstration of the use of Win32 functions in serial port communication will serve as a starting point. I am sure as you browse through MSDN looking for these function definitions, you will come across more sophisticated functions that might be better suited for your application needs.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 30 (Total in Forum: 30) (Refresh) | FirstPrevNext |
|
|
 |
|
|
hii.. i am workin on rfid technology here in CEERI-pilani. my rfid reader is connected to serial port of my computer i want to take inputs from that reader, rfid tag code and distance measured respectively. i am writing a code in c.i want to know how to read output of rfid reader through my serial port using C.
akhshay gandhi
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
how can we identify or detect the serial port using visual c++? how send the data and receive data ie read/write data communication with port?
rahul bhalshankar
|
| Sign In·View Thread·PermaLink | 1.00/5 (4 votes) |
|
|
|
 |
|
|
this is silly question.
CSyncSerialComm s0("COM5"); unsigned long buflen = 0;
int main() { CSyncSerialComm s0("COM5"); unsigned long buflen = 0;
s0.Open(); s0.ConfigPort(CBR_19200,5); s0.Write("AT\r\n",4); char buff[255]; memset(buff,sizeof(buff),0); s0.Read(&buff,&buflen);  s0.Close();
return 0; }
for some reasons, i don't know how to pass **  . This is very simple for some, can you guys help me. A working sample would be very helpful since the downloaded sample only contain the source code.
thanks in advance
|
| Sign In·View Thread·PermaLink | 1.75/5 (4 votes) |
|
|
|
 |
|
|
int main(void) { //----------------------------------------------------- //=================First Block of Code================= //===================Open Port=========================
HANDLE SerialPort; // Handle for the serial port once it's opened DCB dcbConfig; char* m_pszPortName = "COM1"; DWORD dwBaudRate = 9600; // The baud rate that you want to set the serial port to DWORD dwReadTimeOutIntervalInSec = 1; // I don't really use this DWORD dwReadTimeOutConstantInSec = 1; // I don't really use this DWORD dwReadTimeOutMultiplier = 1; // I don't really use this DWORD dwWriteTimeOutInSec = 1; // I don't really use this DWORD dwWriteTimeOutMultiplier = 1; // I don't really use this COMMTIMEOUTS commTimeout; std::stringbuf sb; DWORD dwEventMask; DWORD dwSize; char szBuf; DWORD dwIncommingReadSize; unsigned long dwNumberOfBytesSent = 0; unsigned long dwNumberOfBytesWritten; char* pszBuf;
SerialPort = CreateFile(m_pszPortName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); // | GENERIC_WRITE,
if (SerialPort == INVALID_HANDLE_VALUE) //Handle Error Condition //----------------------------------------------------- //=================Second Block of Code================ //==================Configuration 1====================
if(GetCommState(SerialPort, &dcbConfig)) { dcbConfig.BaudRate = dwBaudRate; //set values of serial port as you want them dcbConfig.ByteSize = 8; dcbConfig.Parity = NOPARITY; dcbConfig.StopBits = ONESTOPBIT; dcbConfig.fBinary = TRUE; dcbConfig.fParity = TRUE; }
else //Handle Error Condition
if(!SetCommState(SerialPort, &dcbConfig)) //save changes to serial port values //Handle Error Condition
//------------------------------------------------------ //=================Third Block of Code================== //=================Configuration 2======================
if(GetCommTimeouts(SerialPort, &commTimeout)) { commTimeout.ReadIntervalTimeout = 1000 * dwReadTimeOutIntervalInSec; commTimeout.ReadTotalTimeoutConstant = 1000 * dwReadTimeOutConstantInSec; commTimeout.ReadTotalTimeoutMultiplier = 1000 * dwReadTimeOutMultiplier; commTimeout.WriteTotalTimeoutConstant = 1000 * dwWriteTimeOutInSec; commTimeout.WriteTotalTimeoutMultiplier = 1000 * dwWriteTimeOutMultiplier; }
else //Handle Error Condition
if(!SetCommTimeouts(SerialPort, &commTimeout)) //Handle Error Condition
//------------------------------------------------------ //================Fourth Block of Code================== //====================Read==============================
if(!SetCommMask(SerialPort, EV_RXCHAR)) //Handle Error Condition
if(WaitCommEvent(SerialPort, &dwEventMask, NULL)) {
do { if(ReadFile(SerialPort, &szBuf, 1, &dwIncommingReadSize, NULL) != 0) { if(dwIncommingReadSize > 0) { dwSize += dwIncommingReadSize; sb.sputn(&szBuf, dwIncommingReadSize); } }
else { //Handle Error Condition }
} while(dwIncommingReadSize > 0); }
else //Handle Error Condition
//------------------------------------------------------ //=================Fifth Block of Code================== //====================Write=============================
while(dwNumberOfBytesSent < dwSize /*size of the buffer pszBuf*/) { if(WriteFile(SerialPort, &pszBuf[dwNumberOfBytesSent], 1, &dwNumberOfBytesWritten, NULL) != 0) { if(dwNumberOfBytesWritten > 0) ++dwNumberOfBytesSent; else { //Handle Error Condition } }
else { //Handle Error Condition } }
//------------------------------------------------------ //=================Sixth Block of Code================== //====================Close=============================
if(SerialPort != INVALID_HANDLE_VALUE) { CloseHandle(SerialPort); SerialPort = INVALID_HANDLE_VALUE; }
return 0; }
|
| Sign In·View Thread·PermaLink | 2.33/5 (3 votes) |
|
|
|
 |
|
|
normally it should be possible to write a filename instead of the port. and it works fine with writing, but reading does not work
char **buffer = NULL; DWORD dwSize = 5; result = con->Read(buffer, dwSize); if(result != S_OK){ cout << "Error" << endl; }else{ cout << "Sucsess: " << buffer << endl; }
is there a problem in my code?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Well its not correct. Please try,
char * buffer = NULL; DWORD dwSize = 5; result = con->Read(&buffer, dwSize);
...
Hope it helps
-- modified at 19:55 Monday 14th November, 2005
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, I try to compile and run the sample program above. I create from empty pfoject of MS VC++ 6.0, and copied both of SyncSerialComm.cpp and SyncSerialComm.h. I can compile SyncSerialComm.cpp but when try to "build all" the error message has come out. "LNK2001 unresolved external symbol_main" "LNK1120 1 unresolved external"
Does anybody help to how can I solve this problem?? Please repy.
|
| Sign In·View Thread·PermaLink | 3.00/5 (2 votes) |
|
|
|
 |
|
|
Well in your project you need a main method. I presume you are using an exe project in which case it is the entry point.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thank you for replying. So that means I have to start, like this??
int main( int argc[ , char *argv[ ] [, char *envp[ ] ] ] );{
return 0; }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It seems that you read and write only one character at a time.
Wouldn't you better check the number of chars before usuing the read ?
Franck.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Franck, this was just to demonstrate the use of the function. Sure in real world apps you never read byte by byte. Its totally inefficient. Something like the code below is more typical. Thanks.
std::stringbuf strBuffer; DWORD dwEventMask;
if(!SetCommMask(m_hSerialComm, EV_RXCHAR)) //Handle Error Condition
if(WaitCommEvent(m_hSerialComm, &dwEventMask, NULL)) { static const unsigned int kdwReadSize = 1024; char szBuffer[kdwReadSize];
DWORD dwIncommingReadSize = 0;
do { if(ReadFile(m_hSerialComm, &szBuf, kdwReadSize, &dwIncommingReadSize, NULL) != 0) { if(dwIncommingReadSize > 0) { dwTotalSize += dwIncommingReadSize; sb.sputn(&szBuffer, dwIncommingReadSize); } } else //Handle Error Condition } while(dwIncommingReadSize > 0); }
else //Handle Error Condition
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
Hi there, I need a way to tell if the buffer of the PC side, (Windows) is empty. I use WriteFile and I tried to use FlushFileBuffers(); but Still I need to know that the transmitting buffer is empty. How can I accomplish that ? Thanx
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
hi,
i'm trying to write a simple string of characters to a device which connected via USB to my pc. it is listed as a serial port (COM9) on my win xp hardware device manager.
although i can open the port (COM9) and write data to it using your code, it doesn't "respond" as i expect it to.
but when i tried using a commercial toolkit like activexpert's activecomport, the hardware did respond.
i had all the configuration like baud rate and port number listed correctly.
is there a difference between normal serial port and usb serial port?
thanks for any advice.
gab
Live simply, simply live.
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
Using the class you created, I recieved the following error message: Debug Error! DAMAGE: after Normal block (#43) at 0x00440070
I believe it is because of creating a buffer of the wrong size, after changing the constructor as follows, solved the problem:
CSyncSerialComm::CSyncSerialComm(const char *pszPortName) : m_hSerialComm(INVALID_HANDLE_VALUE) { assert(pszPortName);
m_pszPortName = new char[strlen(pszPortName) + 1];//------>>>>>Added + 1 here strcpy(m_pszPortName, pszPortName); }
HTH
Kevin Shaffer kshaff03@msn.com www.lawrencepcguy.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I want to dail the modem using the serial Port. In WriteFile I Send the AT commands.Serail Port is configured but modem dailed tone is not detected by using the Writefile().Is there any timing problem?
Jawad Arif
|
| Sign In·View Thread·PermaLink | 2.25/5 (4 votes) |
|
|
|
 |
|
|
Well....i tried the sample piece of code....but the problem is that the create file function....works perfectly fine the first time when the program is run...but the next time it is run....this function....does not work and according to the error checking code...goes...into the INVALID_HANDLE stuff..i have to restart the computer again to make the code work ....but after the first run its the same case...
Another question...will this code work for LPT ports also... changing the "COMn" argument of CreateFile function to "LPTn"...??
Thankx in advance to all...
mukesh gupta
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi, I found your article very useful, but I want to know if there is a way to read the Pin Status. I want to use the serial port to set and get control signals so I need to obtain the state of the pins RI, CTS or DSR. Can you recommend me a way to do this? Thanks in advance!
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
Hi,
Thanks for sharing this nice and simple piece of code.
I was trying to use it in a sample application with two threads. One for writing information to port and other thread for reading information. The threads are synchronized using an global event object( whihc is initially created in non-signaled state).
Now event is set to signaled state after writing to port and read thread whihc is waiting on this event ( WaitForSingleObject ), tries to read information written. BUT 'WaitCommEvent' call of your Read function waits forever. Any idea what i am doing wrong here?
Thanks for your suggestions. Mukesh E-mail: mgupta@quark.co.in
|
| Sign In·View Thread·PermaLink | 1.33/5 (3 votes) |
|
|
|
 |
|
|
Mukesh,
I will check it out today.
Ok from what you say I gather the following. You have one thread for reading and one for writing. The reading thread waits for the event to be signalled before calling my Read method. The writing thread on the other hand sets the event to a signalled state after writing data to the Comm port. (I will create this case while testing today).
In the meantime, could you please let me know the following,
When I tested I used a single thread. Let me know if reading using a single thread works for you.
The reason being that I was told earlier that windows implementation of non-overlapped comm io is not very reliable.
Thanks.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi Eshwar,
Thanks for your prompt response.
First I tries using a single thread only, but that also doesn't seem to work.
Pl find the code that I am using for different threads:-
// TestSerialComm.cpp : Defines the entry point for the console application. //
#include "stdafx.h" #include "SyncSerialComm.h"
HANDLE hGlobalWriteEvent;
DWORD WINAPI ReadThread( LPVOID lpParam ) { DWORD dwWaitResult;
// Request ownership of mutex. printf ( "\nReadThread:: Waiting for event to get signaled..." ); dwWaitResult = WaitForSingleObject( hGlobalWriteEvent, // handle to mutex INFINITE); // time-out interval
printf ( "\nReadThread:: event signaled..." );
switch (dwWaitResult) { // The thread got mutex ownership. case WAIT_OBJECT_0:
{ printf ( "\nReadThread:: reading data..." ); // read CSyncSerialComm* pSyncComm = (CSyncSerialComm*)lpParam;
char **ppReadBuf = NULL; DWORD dwSize = 20; ppReadBuf = new char*[2]; ppReadBuf[0] = new char[10]; ppReadBuf[1] = new char[10]; memset ( ppReadBuf, 0, 20 );
HRESULT hr = pSyncComm->Read ( ppReadBuf, dwSize );
if ( hr == S_OK ) printf ( "\nReadThread:: reading data done..." ); else printf ( "\nReadThread:: reading data failed..." );
}
break;
// Cannot get mutex ownership due to time-out. case WAIT_TIMEOUT: return FALSE;
// Got ownership of the abandoned mutex object. case WAIT_ABANDONED: return FALSE; }
return 0; }
DWORD WINAPI WriteThread( LPVOID lpParam ) { printf ( "\nWriteThread::Write thread started..." ); // Reset hGlobalWriteEvent to nonsignaled, to block readers. if (! ResetEvent(hGlobalWriteEvent) ) { // Error exit. }
printf ( "\nWriting to port..." ); CSyncSerialComm* pSyncComm = (CSyncSerialComm*)lpParam; char szBuf[] = "Hello"; HRESULT hr = pSyncComm->Write ( szBuf, 5 ); printf ( "\nDone..." );
if ( SetEvent ( hGlobalWriteEvent ) != 0 ) printf ( "\nWriteThread::Event signaled." ); else printf ( "\nWriteThread::Event signaled failed." );
return 0; }
int _tmain(int argc, _TCHAR* argv[]) { hGlobalWriteEvent = CreateEvent( NULL, // no security attributes TRUE, // manual-reset event FALSE, // initial state is signaled "WriteEvent" // object name );
if (hGlobalWriteEvent == NULL) { // error exit }
CSyncSerialComm* pSyncComm = new CSyncSerialComm ( "COM1" );
HRESULT hr = pSyncComm->Open ( );
hr = pSyncComm->ConfigPort( CBR_19200, 5 );
DWORD dwThreadId, dwThrdParam = 1; HANDLE hThread; char szMsg[80];
hThread = CreateThread( NULL, // no security attributes 0, // use default stack size ReadThread, // thread function pSyncComm, // argument to thread function 0, // use default creation flags &dwThreadId ); // returns the thread identifier // Check the return value for success. if (hThread == NULL) { wsprintf( szMsg, "CreateThread failed." ); MessageBox( NULL, szMsg, "main", MB_OK ); } else { CloseHandle( hThread ); }
HANDLE hThread2;
hThread2 = CreateThread( NULL, // no security attributes 0, // use default stack size WriteThread, // thread function pSyncComm, // argument to thread function 0, // use default creation flags &dwThreadId ); // returns the thread identifier // Check the return value for success. if (hThread2 == NULL) { wsprintf( szMsg, "CreateThread failed." ); MessageBox( NULL, szMsg, "main", MB_OK ); } else { CloseHandle( hThread2 ); }
printf ( "\nMain thread exit waiting.Press any key..." ); getch();
hr = pSyncComm->Close ();
return 0; }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Mukesh,
I did take a look at it yesterday and did notice the problem you were talking about. I still haven't found a fix yet. It might be a problem with my write function since I have used this code successfully to perform read operations before. And by the way you need to make a small modification to your code,
Instead of,
char **ppReadBuf = NULL; DWORD dwSize = 20; ppReadBuf = new char*[2]; ppReadBuf[0] = new char[10]; ppReadBuf[1] = new char[10]; memset ( ppReadBuf, 0, 20 );
HRESULT hr = pSyncComm->Read ( ppReadBuf, dwSize );
You need to change it to something like this,
char * pReadBuf = 0; unsigned long dwBufSize;
HRESULT hr = pSyncComm->Read(&pReadBuf, dwBufSize);
...
The reason being, the function allocates space for you. If read is successful, then pReadBuf will have a size of dwBufSize will the contents read from the stream in it. But its you responsibility to call delete [] pReadBuf in the end to prevent memory leaks. As soon I come up with a fix I will let you know.
|
| Sign In·View Thread·PermaLink | 4.00/5 (2 votes) |
|
|
|
 |
|
|
I also had d same problem.But i came to know dat a port is locked exclusively for single action either read or write.So i have used two ports.Connected Com1 port on one pc to com1 of another.Now my application is working.Writing application is on one port n reading on other.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
| | |