我的目标: 我正在编写一个应用程序,一次将文件写入串口128字节(总共137个,带有ModBUS头和CRC)并等待回复。我已成功实现了写作。在发送一个137字节的数据包之后,我想在串口com上等待回复并处理它,以防抛出modbus异常。
我的问题: ReadFile函数返回170,从windows文档中,它是170(0xAA) - 请求的资源正在使用中。我实际使用的唯一资源是串口句柄,我怀疑是这个,错误是指。
注意 - - 没有使用可用的ModBUS库,因为我以特定的方式使用地址寄存器,需要完全控制 - 我只使用重叠I / O,因为(根据WinApi doc)如果串口没有字节,ReadFile永远不会返回;如果超时需要重叠访问是必须的(如果我错了,请纠正我)。 - 我有2秒的最大超时(实际等待回复的超时)和字节之间的20毫秒;如果字节之间超过20毫秒,我认为不再有字节;
有没有人有过使用ReadFile和Erro 170的经验?感谢我能得到的所有帮助。
我的部分代码:
u8 WaitModBusReply(void)
{
u8 i = 0;
u8 ReplyStatus = 0xAA;
u8 ReplyBuff[ReplyBuffSize];
u8 * ptr = &ReplyBuff[0];
static u16 TotalRX_Bytes;
DWORD dwCommEvent;
DWORD dwBytesRead;
COMSTAT ComStatus;
DWORD comErrors = 0;
OVERLAPPED read_s = {0};
read_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
for (int z=0; z< ReplyBuffSize; z++)
ReplyBuff[z] = 0;
ClearCommError(ModBUS_Port, &comErrors, &ComStatus);
ResetEvent(read_s.hEvent);
if ( !WaitCommEvent(ModBUS_Port, &dwCommEvent, &read_s) )
{
//byte_timeout += MCU_Getms_TimeConsumption();
if ( (ReadFile(ModBUS_Port, ptr+TotalRX_Bytes, ReplyBuffSize-
TotalRX_Bytes, &dwBytesRead, NULL) )) //&dwBytesRead &modbus_reply
{
fprintf(stderr, "\n EXEC 3");
// ReadFile(PC_TestCenterPort, pBufPtr+TotalRX_Bytes, BufSize-
TotalRX_Bytes, &BytesRead, NULL);
TotalRX_Bytes += dwBytesRead;
i++;
ReplyStatus = Reply_Received;
}
}
else
printf("Error setting Com event mask:%d ", GetLastError());
if ( ReplyStatus == Reply_Received)
{
fprintf(stderr, "\nExit error3: %d\n", GetLastError() );
if ( (i == 4) ) // Exception returned. Parse it
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = ReplyBuff[i-2];
}
else if ( (i == 7) ) // Reply returned
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = Reply_OK;
}
}
/*
for ( int j=0; j<= 256; j++)
printf("\nReplyBuff[%d]: %X", j, ReplyBuff[j]); */
return ReplyStatus;
}
检查应答数组的逻辑未实现,因此忽略该部分。 该函数由:
调用u8 SerialDataSend(void)
{
u8 t_status = BufferSent;
int write_status = -1;
int read_status = -1;
DWORD bytes_written = 0;
OVERLAPPED write_s;
memset(&write_s, 0, sizeof(write_s));
write_s.Internal = 0;
write_s.InternalHigh = 0;
write_s.Offset = 0;
write_s.OffsetHigh = 0;
write_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
if ( !SerialInit() )
{
while (!t_status)
{
fprintf(stderr, "Starting transmission -\n");
while(packages_left > 0 && !t_status)
{
write_status = WriteFile(ModBUS_Port, ModBUS_Buffer(), 137,
&bytes_written, &write_s); //&write_s
fprintf(stderr,"\r ModBUS transaction - Packages left:%4d",
packages_left);
if( write_status ) // Return values for success and
overlapped access ongoing
{
fprintf(stderr, "Error :%d.\n", GetLastError());
t_status = BufferFailed;
CloseHandle(ModBUS_Port);
break;
}
//FlushFileBuffers(ModBUS_Port);
read_status = WaitModBusReply();
printf("READ STATUS: %d\n", read_status);
if ( !read_status && !write_status )
{
fprintf(stderr, "\n------------------------------------------------------------");
fprintf(stderr, "\n Exception occurred: %X\n",
read_status);
t_status = BufferFailed;
Sleep(1);
break;
}
packages_left--;
Sleep(200);
}
//printf("EXEC 1\n");
if (!t_status)
{
fprintf(stderr, "\n\nTransaction Complete. Bytes written :
%d\n", FileSize);
packages_left = 10;
}
break;
}
fclose(HMI_Program);
if ( t_status != BufferFailed )
{
fprintf(stderr, "Closing serial port - ");
if ( !CloseHandle(ModBUS_Port) )
fprintf(stderr, "Error :%d.\n", GetLastError());
else
fprintf(stderr, "OK.\n");
}
}
fflush(stdout);
fflush(stderr);
return t_status;
}
和初始化串口的功能:
u8 SerialInit(void)
{
memset(&SerialSettings,0,sizeof(SerialSettings));
SerialSettings.DCBlength = sizeof(SerialSettings);
SerialSettings.BaudRate = CBR_115200;
SerialSettings.ByteSize = 8;
SerialSettings.StopBits = TWOSTOPBITS;
SerialSettings.Parity = NOPARITY;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutConstant = 2000;
timeouts.ReadTotalTimeoutMultiplier = 1 ;
memset(&timeouts,0,sizeof(timeouts));
fprintf(stderr, "Opening serial port - ");
sprintf(COM_Port, "\\\\.\\COM%d", port_no);
ModBUS_Port = CreateFile(COM_Port, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if (ModBUS_Port == INVALID_HANDLE_VALUE)
fprintf(stderr, "Error\n\n");
else
fprintf(stderr, "OK\n");
if ( !GetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error getting device state.");
CloseHandle(ModBUS_Port);
}
else if( !SetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error setting device parameters.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommTimeouts(ModBUS_Port, &timeouts) )
{
fprintf(stderr, "Error setting timeouts.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommMask(ModBUS_Port, EV_RXCHAR | EV_ERR ) )
{
fprintf(stderr, "\nError setting com mask.");
CloseHandle(ModBUS_Port);
}
return GetLastError();
}
感谢。