正确读取或写入串行端口Windows API
correctly reading or writing serial port Windows API
我读过很多关于串行端口读写的问题。到目前为止,没有一个能帮我弄清楚我的代码缺少什么。c++的msdn示例有未定义的变量和缺少的括号,所以尽管我可以添加括号,但它仍然不起作用。以下是我在这一点上得到的。看起来我可以打开端口并进行配置,但我无法读取一个字节/字符的数据。我真的只想要一个简单的异步串行读/写程序来从Arduino读取。
class MY_SERIAL
{
HANDLE serialinstance;
DWORD dwStoredFlags;
DWORD dwRes;
DWORD dwCommEvent;
OVERLAPPED osStatus = {0};
BOOL fWaitingOnStat;
//dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ;
DCB dcb;
COMMTIMEOUTS timeouts;
COMMCONFIG serialconfig;
public:
char inBuffer[1000];
char outBuffer[100];
PDWORD noBytes;
void close_serial()
{
CloseHandle(serialinstance);
}
//----------------------------------------------------
bool open_serial(LPCSTR portNumber) // serial port name use this format "\\.\COM10"
{
serialinstance = CreateFile(portNumber, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if(serialinstance == INVALID_HANDLE_VALUE)
{
int error = GetLastError();
printf("ERROR opening serial port %srn", portNumber);
if(error == 0x2){printf("ERROR_FILE_NOT_FOUNDrn");}
if(error == 0x5){printf("ERROR_ACCESS_DENIEDrn");}
if(error == 0xC){printf("ERROR_INVALID_ACCESSrn");}
if(error == 0x6){printf("ERROR_INVALID_HANDLErn");}
printf("error code %drn", error);
return false;
}
if(GetCommState(serialinstance, &dcb)!= true)
{
printf("ERROR getting current state of COM %d rn", GetLastError());
return false;
}
else{printf("debug read current comstatern");}
FillMemory(&dcb, sizeof(dcb), 0); //zero initialize the structure
dcb.DCBlength = sizeof(dcb); //fill in length
dcb.BaudRate = CBR_115200; // baud rate
dcb.ByteSize = 8; // data size, xmit and rcv
dcb.Parity = NOPARITY; // parity bit
dcb.StopBits = ONESTOPBIT;
if(SetCommState(serialinstance, &dcb) != true)
{
printf("ERROR setting new state of COM %d rn", GetLastError());
return false;
}
else{printf("debug set new comstatern");}
/*
if (!BuildCommDCB("115200,n,8,1", &dcb)) //fills in basic async details
{
printf("ERROR getting port comstatern");
return FALSE;
}
*/
if (!SetCommMask(serialinstance, EV_RXCHAR))
{
printf("ERROR setting new COM MASK %d rn", GetLastError());
return false;
}
else{printf("debug commmask setrn");}
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 20;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(serialinstance, &timeouts))
{
printf("ERROR setting timeout parametersrn");
return false;
}
else{printf("debug timeouts setrn");}
osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osStatus.hEvent == NULL)
{// error creating event; abort
printf("ERROR creating Serial EVENTrn");
return false;
}
else{printf("debug event created setrn");}
osStatus.Internal = 0;
osStatus.InternalHigh = 0;
osStatus.Offset = 0;
osStatus.OffsetHigh = 0;
assert(osStatus.hEvent);
printf("debug com port setting completern");
return true;
}
//---------------------------------------------------------
bool read_serial_simple()
{
char m[1000];
LPDWORD bytesRead;
if (WaitCommEvent(serialinstance, &dwCommEvent, &osStatus))
{
if(dwCommEvent & EV_RXCHAR)
{
ReadFile(serialinstance, &m, 1, bytesRead, &osStatus);
printf("data read = %d, number bytes read = %d rn", m, bytesRead);
return true;
}
else
{
int error = GetLastError();
if(error == ERROR_IO_PENDING){printf(" waiting on incomplete IOrn");}
else{printf("ERROR %drn", error);}
return false;
}
}
return false;
}
};
所以我去掉了读取功能。我现在得到一个char,它报告读取了1个字节,但char的值不正确。我得到一个48、13、10的序列,偶尔还有一个50的字节值。然而,Arduino正在发送一个系列的0,然后是一个128,这已经通过TerraTerm进行了验证。我还需要什么?
bool read_serial_simple()
{
unsigned char m = 0;
DWORD bytesRead;
if(ReadFile(serialinstance, &m, 1, &bytesRead, &osStatus) == true)
{
printf("data read = %d, number bytes read = %d rn", m, bytesRead);
return true;
}
else{
int error = GetLastError();
if(error == ERROR_IO_PENDING){printf(" waiting on incomplete IOrn");}
else{printf("ERROR %drn", error);}
return false;
}
}
所以现在我可以读取一个字节的数据,但不能向端口写入一个字节或更多。我只得到ERROR_IO_PENDING。有人也能帮上忙吗。在下面写下我班的函数。
bool write(DWORD noBytesToWrite)
{
if(WriteFile(serialinstance, outBuffer, noBytesToWrite, NULL, &osStatus) == true)
{
printf("message sentrn");
return true;
}
else
{
int error = GetLastError();
if(error != ERROR_IO_PENDING){LastError();}
return false;
}
}
我从main调用这两个函数,如下
myserial.open_serial(COM12);
myserial.outBuffer[0] = 'H';
myserial.outBuffer[1] = 'e';
myserial.outBuffer[2] = 'L';
myserial.outBuffer[3] = 'l';
myserial.outBuffer[4] = 'O';
for(int n=0; n<5; n++){printf("%c", myserial.outBuffer[n]);}
printf("rn");
while(1)
{
myserial.read();
myserial.write(5);
//system("PAUSE");
}
目前,arduino被设置为读取字节并将其重复回电脑。它在arduino IDE串行监视器上做得很好,所以现在我只需要让这个电脑程序写出来。
您的bytesRead
变量是一个未初始化的指针。您正在将一个无效地址传递给ReadFile()
进行写入。
将LPDWORD bytesRead
替换为DWORD bytesRead
,然后使用&bytesRead
将其传递给ReadFile()
。
编辑:同时消除FILE_FLAG_OVERLAPPED
。你没有正确处理它,如果你在阅读前WaitForSingleObject()
,那么使用它是没有意义的。
对不起,我的回答有点晚,但当我检查另一个串行端口的详细信息时,我发现了这个。
原始代码中有一个小缺陷。您正在使用FILE_FLAG_OVERLAPPED标志调用CreateFile。这意味着您希望使用非阻塞调用。您需要删除此标志,或者更改ReadFile和WriteFile调用,使它们包含指向OVERLAPPED结构WriteFile的指针。
您的代码使用ReadFile,因为它将同步完成,因为有一个字符已经在等待。WriteFile将返回IO_PENDING结果,以指示写入已排队。
- Qt Q串行端口未编程设备未关闭
- 在 linux c++ 中没有通过串行端口发送的数据
- 检查串行端口Linux中是否有传入数据(cbInQue for linux)
- 在不传输的情况下更改 Win32 中的串行端口波特率
- 增强 ASIO 和串行端口异步读取
- 串行端口写入究竟如何从缓冲区实际写入数据?
- 如何将参数这些串行端口传递到函数中
- 从 C/C++ 访问 Android 中的串行端口
- Qt两个串行端口发送和接收
- 通过串行端口从GPS传感器读取
- 提升 asio 串行端口"end of file"
- 通过串行端口发送多个值
- 与QSerialPort配合使用的串行端口仿真
- 如何通过boost::asio和shared_ptr创建串行端口
- 串行端口编码
- 如何在Visual Studio中进行串行端口编程C++Windows和Linux之间的可移植性?
- Windows 7 的 QT 5.2 串行端口写入问题
- Windows:C++:从文件重定向到串行端口(输入)
- 检测移除开放串行端口设备(Qt / Windows)
- 正确读取或写入串行端口Windows API