我在Windows平台下修改了C(codeblocks / mingw)中其他人编写的串行通信环回代码。我能够正确发送数据。我通过打开终端软件验证了这一点。但我无法收到数据。我在下面的代码中从ReadFile()的输入缓冲区998读取错误消息错误。不知道错误是什么。 我正在使用两个CP210x USB到串行模块,并将TxD连接到一个到另一个的RxD。
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <commdlg.h>
//#include <windef.h>
#include <time.h>
int nread,nwrite;
void myDelay(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
int main(int argc, char* argv[])
{
HANDLE hSerial;
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char *words, *buffRead, *buffWrite;
DWORD dwBytesWritten, dwBytesRead;
if(argc<3)
{
printf("Enter the com port as command line parameter and t for transmitter and r for receiver\n");
printf("Example: Serial.exe com4 t\n");
return(1);
}
hSerial = CreateFile(argv[1],GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if ( hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf(" serial port does not exist \n");
}
else
{
printf(" some other error occured\n");
}
return(1);
}
if (!GetCommState(hSerial, &dcbSerialParams.dcb))
{
printf("error getting state \n");
return(1);
}
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
// Set various serial port parameters.
dcbSerialParams.dcb.BaudRate = CBR_9600;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
dcbSerialParams.dcb.fBinary = TRUE;
dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.dcb.fOutxCtsFlow = FALSE;
dcbSerialParams.dcb.fOutxDsrFlow = FALSE;
dcbSerialParams.dcb.fDsrSensitivity= FALSE;
dcbSerialParams.dcb.fAbortOnError = TRUE;
if (!SetCommState(hSerial, &dcbSerialParams.dcb))
{
printf(" error setting serial port state \n");
return(1);
}
GetCommTimeouts(hSerial,&timeouts);
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier= 10;
if(!SetCommTimeouts(hSerial, &timeouts))
{
printf("error setting port state \n");
return(1);
}
while(1)
{
// Use a delay of 500 msec
myDelay(500);
if(!strcmp(argv[2],"t"))
{
printf("Write Mode\n");
//****************Write Operation*********************//
words = "This is a string to be written to serial port COM1";
nwrite = strlen(words);
buffWrite = words;
dwBytesWritten = 0;
if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL))
{
printf("error writing to output buffer \n");
return(1);
}
}
//***************Read Operation******************//
else
{
dwBytesRead = 0;
nread = strlen(words);
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer %d\n", GetLastError());
continue;
}
printf("Data read from read buffer is \n %s \n",buffRead);
}
}
CloseHandle(hSerial);
return(0);
}
答案 0 :(得分:0)
读取和写入COM端口相互阻塞,使FIFO在用尽时几乎完全超时。 FIFO中也可能存在一些数据......如果发送和接收过大的数据块,则数据丢失的可能性更大。
这里是非线程COM端口访问的古老小例子
//---------------------------------------------------------------------------
//--- port class ver: 1.0 ------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _port_h
#define _port_h
//---------------------------------------------------------------------------
class port
{
public: HANDLE hnd;
AnsiString error;
DWORD rlen,wlen,err;
DCB rs232_state;
COMMPROP properties;
COMMTIMEOUTS timeouts;
COMSTAT stat;
port();
~port();
int open(AnsiString name);
void close();
int get_stat(); // err,stat
int get_timeouts(); // timeouts
int set_timeouts();
int get_properties(); // properties
int get_rs232_state(); // rs232_state
int set_rs232_state();
void rst_rs232_state();
void out(BYTE data) { WriteFile(hnd,&data,1,&wlen,NULL); }
void in (BYTE *data) { ReadFile (hnd, data,1,&rlen,NULL); }
void in (char *data) { ReadFile (hnd, data,1,&rlen,NULL); }
void out(BYTE *data,DWORD len) { WriteFile(hnd,data,len,&wlen,NULL); }
void in (BYTE *data,DWORD len) { ReadFile (hnd,data,len,&rlen,NULL); }
};
//---------------------------------------------------------------------------
port::port()
{
rlen=0;
wlen=0;
err =0;
error="";
hnd=NULL;
rst_rs232_state();
}
//---------------------------------------------------------------------------
port::~port()
{
close();
}
//---------------------------------------------------------------------------
int port::open(AnsiString name)
{
close();
rlen=0;
wlen=0;
hnd=CreateFile( name.c_str(),GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,NULL);
if (hnd==NULL) return 0;
get_timeouts();
get_properties();
get_rs232_state();
timeouts.ReadIntervalTimeout;
timeouts.ReadTotalTimeoutMultiplier;
timeouts.ReadTotalTimeoutConstant;
timeouts.WriteTotalTimeoutMultiplier;
timeouts.WriteTotalTimeoutConstant;
properties.wPacketLength;
properties.wPacketVersion;
properties.dwServiceMask;
properties.dwReserved1;
properties.dwMaxTxQueue;
properties.dwMaxRxQueue;
properties.dwMaxBaud;
properties.dwProvSubType;
properties.dwProvCapabilities;
properties.dwSettableParams;
properties.dwSettableBaud;
properties.wSettableData;
properties.wSettableStopParity;
properties.dwCurrentTxQueue;
properties.dwCurrentRxQueue;
properties.dwProvSpec1;
properties.dwProvSpec2;
properties.wcProvChar[1];
return 1;
}
//---------------------------------------------------------------------------
void port::close()
{
if (hnd==NULL) return;
CloseHandle(hnd);
hnd=NULL;
}
//---------------------------------------------------------------------------
int port::get_stat()
{
if (ClearCommError(hnd,&err,&stat)) return 1;
error=GetLastError();
return 0;
}
//---------------------------------------------------------------------------
int port::get_timeouts()
{
if (GetCommTimeouts(hnd,&timeouts)) return 1;
error=GetLastError();
get_stat();
return 0;
}
//---------------------------------------------------------------------------
int port::set_timeouts()
{
if (SetCommTimeouts(hnd,&timeouts)) return 1;
error=GetLastError();
get_stat();
return 0;
}
//---------------------------------------------------------------------------
int port::get_properties()
{
if (GetCommProperties(hnd,&properties)) return 1;
error=GetLastError();
get_stat();
return 0;
}
//---------------------------------------------------------------------------
int port::get_rs232_state()
{
if (GetCommState(hnd,&rs232_state)) return 1;
error=GetLastError();
get_stat();
return 0;
}
//---------------------------------------------------------------------------
int port::set_rs232_state()
{
if (SetCommState(hnd,&rs232_state)) return 1;
error=GetLastError();
get_stat();
return 0;
}
//---------------------------------------------------------------------------
void port::rst_rs232_state()
{
rs232_state.BaudRate = CBR_9600;
rs232_state.ByteSize = 8;
rs232_state.Parity = NOPARITY;
rs232_state.StopBits = ONESTOPBIT;
rs232_state.fOutxCtsFlow= FALSE;
rs232_state.fOutxDsrFlow= FALSE;
rs232_state.fOutX = FALSE;
rs232_state.fInX = FALSE;
rs232_state.fBinary = FALSE;
rs232_state.fRtsControl = RTS_CONTROL_DISABLE;
}
//---------------------------------------------------------------------------//---------------------------------------------------------------------------
//---------------------------------------------------------------------------//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
它位于 C ++ / VCL 中,因此只需将AnsiString
重写为char*
或您获得的任何字符串类型,并将File例程更改为您的。如果您无权访问重写为 C 的类。用法很简单:
// globals and init
port com;
com.open("COM2");
com.timeouts.ReadIntervalTimeout =10;
com.timeouts.ReadTotalTimeoutMultiplier =10;
com.timeouts.ReadTotalTimeoutConstant =10;
com.timeouts.WriteTotalTimeoutMultiplier=10;
com.timeouts.WriteTotalTimeoutConstant =10;
com.set_timeouts();
// send/recv
char q;
com.out(`x`); // send x
com.in (&q); // recv ...
你应该使用线程来解决这个问题,因为没有线程,通信就会阻塞。无论如何没有用于环回的线程你应该:
BYTES
并非所有COM端口都有大的FIFO ...... 为了更安全,请阅读内部线程......如:
volatile bool _stop=false; // set this to true when you want to exit
unsigned long __stdcall thread_com(LPVOID p)
{
char q;
for (;!_stop;)
{
com.in (&q); // recv ...
if (q<32) q=`.`; // data loss due to timeout if not sending `0..31` of coarse
Sleep(1); // just not to burn CPU ...
}
}
HANDLE thread_com_hnd=CreateThread(0,0,thread_com,NULL,0,0); // do this only after COM port is initialized