串行 COM 端口通信不工作
Serial COM port communications not working
我正在为我的团队正在进行的一些串行通信编写一个测试应用程序。它是在 VS2010 上用 Visual C++(非托管)编写的。我们正在 Windows 7x64 上对其进行测试。如果我们先 运行 Putty(并连接),我们的代码就可以工作。如果我们不先 运行 Putty(然后连接),则没有任何效果。
来自Read/Write文件的return代码如下:
w/o腻子
写入文件 = 1
读取文件 = 1
带腻子
写入文件 = 1
读取文件 = 1
SetCommState例程returns 1(通过):https://msdn.microsoft.com/en-us/library/windows/desktop/aa363436%28v=vs.85%29.aspx
只需仔细检查:在 SetCommState returns 0;
之后立即调用 GetLastError
我们运行正在使用 COM7,但在 GUI 中选择了 COM4(肮脏的 hack)。发生的事情是 readfile 例程没有 return 返回一个字符串(通过指针)。这表明 writefile 没有正常工作,但我对此不是 100% 确定。
有没有人知道为什么会发生这种情况?
代码如下:
注意:我试图显示所有内容,但代码格式化程序搞砸了。重要的都在这里。
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 4;
com4 = true;
OutputDebugStringW(L"SETCOM - COM4\n");
hComm = CreateFile(L"COM7", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
NULL);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
DCB comSettings;
SecureZeroMemory(&comSettings, sizeof(DCB));
comSettings.BaudRate = 9600;
comSettings.ByteSize = 8;
comSettings.Parity = NOPARITY;
comSettings.StopBits = ONESTOPBIT;
comSettings.fAbortOnError = TRUE;
b = SetCommState(hComm, &comSettings);
commSetupResult = GetLastError();
/*OutputDebugStringW(L"SetCommState = " + (int)SetCommState(hComm, &comSettings));*/
//s.Format("%d",4);//SetCommState(hComm, &comSettings));
// instance an object of COMMTIMEOUTS.
COMMTIMEOUTS comTimeOut;
// Specify time-out between charactor for receiving.
comTimeOut.ReadIntervalTimeout = 3;
// Specify value that is multiplied
// by the requested number of bytes to be read.
comTimeOut.ReadTotalTimeoutMultiplier = 3;
// Specify value is added to the product of the
// ReadTotalTimeoutMultiplier member
comTimeOut.ReadTotalTimeoutConstant = 2;
// Specify value that is multiplied
// by the requested number of bytes to be sent.
comTimeOut.WriteTotalTimeoutMultiplier = 3;
// Specify value is added to the product of the
// WriteTotalTimeoutMultiplier member
comTimeOut.WriteTotalTimeoutConstant = 2;
// set the time-out parameter into device control.
SetCommTimeouts(hComm, &comTimeOut);
break;
case ID_SETCOM_COM5:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 5;
OutputDebugStringW(L"SETCOM - COM5\n");
hComm = CreateFile(L"COM5", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM6:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 6;
OutputDebugStringW(L"SETCOM - COM6\n");
hComm = CreateFile(L"COM6", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM7:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 7;
OutputDebugStringW(L"SETCOM - COM7\n");
hComm = CreateFile(L"COM7", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM8:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 8;
OutputDebugStringW(L"SETCOM - COM8\n");
hComm = CreateFile(L"COM8", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM9:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 9;
OutputDebugStringW(L"SETCOM - COM9\n");
hComm = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM10:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 10;
OutputDebugStringW(L"SETCOM - COM10\n");
hComm = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
DWORD dwRead;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = { 0 };
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL) {}
// Error creating overlapped event; abort.
char lpBuf[32];
if (com4) {
if (!fWaitingOnRead)
{
// Issue read operation.
OVERLAPPED osWrite = { 0 };
DWORD dwWritten;
BOOL result = GetLastError();
result = WriteFile(hComm, "EO1\nJAX0\nDI\n", 12, &dwWritten, NULL);
CStringA WFError;
WFError.Format("\nSent %d result %d lasterror %d \n", dwWritten, result, GetLastError());
OutputDebugStringA(WFError);
Sleep(100);//min was 61, 100 to be safe
bool Wait = true;
DWORD start = GetTickCount() + 15000;
while (Wait && start > GetTickCount())
{
Sleep(200);
// GetLastError();
result = ReadFile(hComm, lpBuf, 32, &dwRead, NULL);
WFError.Format("Read %d, result %d, lasterror %d \n", dwRead, result, GetLastError());
OutputDebugStringA(WFError);
// WFError = "Read file error = " + WFError;
if (result != 0)
{
CString temp = lpBuf;
temp = temp.Left(dwRead);
if (temp.GetLength() > 0)
{
OutputDebugString(temp + "\n");
MessageBox(NULL, temp, L"Title", MB_OK);
// memset(&lpBuf[0], 0, sizeof(lpBuf));
}
//strcpy(lpBuf,"");
// goto start;
}
}
}
}
我有根据的猜测是,您的 SetCommState
调用失败了。您正在向它传递一个充满随机垃圾的 DCB
结构。它在 Putty 之后工作的原因是 Putty 为您配置端口,并且您的程序开始使用该配置(因为它无法建立自己的配置)。
将 DCB comSettings;
行更改为
DCB comSettings = {sizeof(DCB)};
这会正确初始化 DCBlength
成员,并将所有其他成员设置为 0。然后根据需要为您的设备设置其他成员。
并检查 SetCommState
的 return 值是否有错误(以及所有其他 API 调用的值)。
我正在为我的团队正在进行的一些串行通信编写一个测试应用程序。它是在 VS2010 上用 Visual C++(非托管)编写的。我们正在 Windows 7x64 上对其进行测试。如果我们先 运行 Putty(并连接),我们的代码就可以工作。如果我们不先 运行 Putty(然后连接),则没有任何效果。
来自Read/Write文件的return代码如下:
w/o腻子
写入文件 = 1 读取文件 = 1
带腻子
写入文件 = 1 读取文件 = 1
SetCommState例程returns 1(通过):https://msdn.microsoft.com/en-us/library/windows/desktop/aa363436%28v=vs.85%29.aspx 只需仔细检查:在 SetCommState returns 0;
之后立即调用 GetLastError我们运行正在使用 COM7,但在 GUI 中选择了 COM4(肮脏的 hack)。发生的事情是 readfile 例程没有 return 返回一个字符串(通过指针)。这表明 writefile 没有正常工作,但我对此不是 100% 确定。
有没有人知道为什么会发生这种情况?
代码如下:
注意:我试图显示所有内容,但代码格式化程序搞砸了。重要的都在这里。
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 4;
com4 = true;
OutputDebugStringW(L"SETCOM - COM4\n");
hComm = CreateFile(L"COM7", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
NULL);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
DCB comSettings;
SecureZeroMemory(&comSettings, sizeof(DCB));
comSettings.BaudRate = 9600;
comSettings.ByteSize = 8;
comSettings.Parity = NOPARITY;
comSettings.StopBits = ONESTOPBIT;
comSettings.fAbortOnError = TRUE;
b = SetCommState(hComm, &comSettings);
commSetupResult = GetLastError();
/*OutputDebugStringW(L"SetCommState = " + (int)SetCommState(hComm, &comSettings));*/
//s.Format("%d",4);//SetCommState(hComm, &comSettings));
// instance an object of COMMTIMEOUTS.
COMMTIMEOUTS comTimeOut;
// Specify time-out between charactor for receiving.
comTimeOut.ReadIntervalTimeout = 3;
// Specify value that is multiplied
// by the requested number of bytes to be read.
comTimeOut.ReadTotalTimeoutMultiplier = 3;
// Specify value is added to the product of the
// ReadTotalTimeoutMultiplier member
comTimeOut.ReadTotalTimeoutConstant = 2;
// Specify value that is multiplied
// by the requested number of bytes to be sent.
comTimeOut.WriteTotalTimeoutMultiplier = 3;
// Specify value is added to the product of the
// WriteTotalTimeoutMultiplier member
comTimeOut.WriteTotalTimeoutConstant = 2;
// set the time-out parameter into device control.
SetCommTimeouts(hComm, &comTimeOut);
break;
case ID_SETCOM_COM5:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 5;
OutputDebugStringW(L"SETCOM - COM5\n");
hComm = CreateFile(L"COM5", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM6:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 6;
OutputDebugStringW(L"SETCOM - COM6\n");
hComm = CreateFile(L"COM6", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM7:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 7;
OutputDebugStringW(L"SETCOM - COM7\n");
hComm = CreateFile(L"COM7", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM8:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 8;
OutputDebugStringW(L"SETCOM - COM8\n");
hComm = CreateFile(L"COM8", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM9:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 9;
OutputDebugStringW(L"SETCOM - COM9\n");
hComm = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case ID_SETCOM_COM10:
OutputDebugStringW(L"Previous COM port = " + portString + "\n");
comPort = 10;
OutputDebugStringW(L"SETCOM - COM10\n");
hComm = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
OutputDebugStringW(L"Error!");
else
OutputDebugStringW(L"Success!");
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
DWORD dwRead;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = { 0 };
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL) {}
// Error creating overlapped event; abort.
char lpBuf[32];
if (com4) {
if (!fWaitingOnRead)
{
// Issue read operation.
OVERLAPPED osWrite = { 0 };
DWORD dwWritten;
BOOL result = GetLastError();
result = WriteFile(hComm, "EO1\nJAX0\nDI\n", 12, &dwWritten, NULL);
CStringA WFError;
WFError.Format("\nSent %d result %d lasterror %d \n", dwWritten, result, GetLastError());
OutputDebugStringA(WFError);
Sleep(100);//min was 61, 100 to be safe
bool Wait = true;
DWORD start = GetTickCount() + 15000;
while (Wait && start > GetTickCount())
{
Sleep(200);
// GetLastError();
result = ReadFile(hComm, lpBuf, 32, &dwRead, NULL);
WFError.Format("Read %d, result %d, lasterror %d \n", dwRead, result, GetLastError());
OutputDebugStringA(WFError);
// WFError = "Read file error = " + WFError;
if (result != 0)
{
CString temp = lpBuf;
temp = temp.Left(dwRead);
if (temp.GetLength() > 0)
{
OutputDebugString(temp + "\n");
MessageBox(NULL, temp, L"Title", MB_OK);
// memset(&lpBuf[0], 0, sizeof(lpBuf));
}
//strcpy(lpBuf,"");
// goto start;
}
}
}
}
我有根据的猜测是,您的 SetCommState
调用失败了。您正在向它传递一个充满随机垃圾的 DCB
结构。它在 Putty 之后工作的原因是 Putty 为您配置端口,并且您的程序开始使用该配置(因为它无法建立自己的配置)。
将 DCB comSettings;
行更改为
DCB comSettings = {sizeof(DCB)};
这会正确初始化 DCBlength
成员,并将所有其他成员设置为 0。然后根据需要为您的设备设置其他成员。
并检查 SetCommState
的 return 值是否有错误(以及所有其他 API 调用的值)。