Reputation: 14254
I'm trying to write a C++ MFC application that uses the serial port (e.g. COM8). Every time I try to set the DCB it fails. If someone can point out what I'm doing wrong, I'd really appreciate it.
DCB dcb = {0};
dcb.DCBlength = sizeof(DCB);
port.Insert( 0, L"\\\\.\\" );
m_hComm = CreateFile(
port, // Virtual COM port
GENERIC_READ | GENERIC_WRITE, // Access: Read and write
0, // Share: No sharing
NULL, // Security: None
OPEN_EXISTING, // The COM port already exists.
FILE_FLAG_OVERLAPPED, // Asynchronous I/O.
NULL // No template file for COM port.
);
if ( m_hComm == INVALID_HANDLE_VALUE )
{
TRACE(_T("Unable to open COM port."));
ThrowException();
}
if ( !::GetCommState( m_hComm, &dcb ) )
{
TRACE(_T("CSerialPort : Failed to get the comm state - Error: %d"), GetLastError());
ThrowException();
}
dcb.BaudRate = 38400; // Setup the baud rate.
dcb.Parity = NOPARITY; // Setup the parity.
dcb.ByteSize = 8; // Setup the data bits.
dcb.StopBits = 1; // Setup the stop bits.
if ( !::SetCommState( m_hComm, &dcb ) ) // <- Fails here.
{
TRACE(_T("CSerialPort : Failed to set the comm state - Error: %d"), GetLastError());
ThrowException();
}
Thanks.
Additional Info: The generated error code is 87: "The parameter is incorrect." Probably Microsoft's most useful error-code. j/k
Upvotes: 5
Views: 11722
Reputation: 361
This is my code and its working well.
/* Try to open the port */
hCom = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hCom != INVALID_HANDLE_VALUE) {
printf("Handle success\n");
}
dcb = { 0 };
dcb.DCBlength = sizeof(dcb);
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess) {
// Handle the error.
printf("GetCommState failed with error %d.\n", GetLastError());
CloseHandle(hCom);
return APP_ERROR;
}
// Fill in DCB: 57,600 bps, 8 data bits, no parity, and 1 stop bit.
dcb = { 0 };
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = CBR_115200; // Set the baud rate
dcb.ByteSize = 8; // Data size, xmit, and rcv
dcb.Parity = NOPARITY; // No parity bit
dcb.StopBits = ONESTOPBIT; // One stop bit
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess) {
// Handle the error.
printf("SetCommState failed with error %d.\n", GetLastError());
CloseHandle(hCom);
return APP_ERROR;
}
}
printf("Serial port successfully reconfigured.\n");
Upvotes: 1
Reputation: 14254
I was able to resolve the problem using BuildCommDCB
:
DCB dcb = {0};
if ( !::BuildCommDCB( _T("baud=38400 parity=N data=8 stop=1"), &dcb ) )
{
TRACE(_T("CSerialPort : Failed to build the DCB structure - Error: %d"), GetLastError());
ThrowException();
}
Upvotes: 2
Reputation: 68064
My money is on this:
dcb.StopBits = 1;
The MSDN docs says this about StopBits:
The number of stop bits to be used. This member can be one of the following values.
ONESTOPBIT 0 1 stop bit. ONE5STOPBITS 1 1.5 stop bits. TWOSTOPBITS 2 2 stop bits.
So, you're asking for 1.5 stop bits, which is such a horribly archaic thing I can't even remember where it comes from. Teleprinters, possibly.
I'd guess the chances of your driver/hardware supporting this mode are slim, hence the error.
So, change it to dcb.StopBits = ONESTOPBIT;
Upvotes: 12
Reputation: 308452
Here are some possibilities in no particular order.
GetCommState
is filling the structure with garbage since the port hasn't been initialized yet. You might just skip this step.ONE5STOPBITS
which might be invalid when combined with the other parameters.Upvotes: 3
Reputation: 7772
Look at the parameters you give to the function. They're probably incorrect, as the error code says. A google search for "SetCommState 87" shows several instances where the parameters (e.g. baud rate) weren't compatible with the serial port.
Upvotes: 0