Я работаю для кроссплатформенного настольного приложения.Я разрабатываю его на C ++ с использованием Qt и уже реализовал драйвер протокола Omron FINS TCP на стороне ПК через сокеты (QTcpSocket).Когда я читаю из регистра через протокол FINS - я получаю правильный ответ в течение 30 мс, но когда я пишу в регистры plc - нет ответа от ошибки тайм-аута сокета plc (код ошибки QAbstractSocket = 5).
Код для чтения из регистра (функция получает reg_addr - адрес регистра и обновляет значение): bool fins_read_reg (int reg_addr, int * value);->
static unsigned char fins_cmnd[MAX_MSG], fins_resp[MAX_MSG],fins_tcp_header[MAX_HEADER];
static unsigned char fins_send_frame[34], fins_receive_frame[32];
static int sendlen, recvlen;
//char sid = 0;
if(sid > 0xFF)
sid = 0;
if(f!=0)
{
fprintf(f,"BEGIN TO READ \n");
fprintf(f," reg_addr = %d \n",reg_addr);
fprintf(f," value = %d \n",*value);
}
/* SEND FINS/TCP COMMAND*/
/*
* GENERATE FINS COMMAND FRAME
*/
fins_send_frame[0] = 'F'; /* Header */
fins_send_frame[1] = 'I';
fins_send_frame[2] = 'N';
fins_send_frame[3] = 'S';
fins_send_frame[4] = 0x00; /* Length */
fins_send_frame[5] = 0x00;
fins_send_frame[6] = 0x00;
fins_send_frame[7] = 18+8; /*Length of data from Command up to end of FINS frame */
fins_send_frame[8] = 0x00; /* Command */
fins_send_frame[9] = 0x00;
fins_send_frame[10] = 0x00;
fins_send_frame[11] = 0x02;
fins_send_frame[12] = 0x00; /* Error Code */
fins_send_frame[13] = 0x00;
fins_send_frame[14] = 0x00;
fins_send_frame[15] = 0x00;
//command:
fins_send_frame[16] = 0x80; /* ICF */ //put 0x00 - response required //was 0x80
fins_send_frame[17] = 0x00; /* RSV */
fins_send_frame[18] = 0x03; /* GCT */
fins_send_frame[19] = 0x00; /* DNA */
fins_send_frame[20] = srv_node_no; /* DA1 *//* Ethernet Unit FINS NODE NUMBER*/
fins_send_frame[21] = 0x00; /* DA2 */
fins_send_frame[22] = 0x00; /* SNA */
fins_send_frame[23] = cli_node_no; /* SA1 *//* WS FINS NODE NUMBER OBTAINED
AUTOMATICALLY*/
fins_send_frame[24] = 0x00; /* SA2 */
fins_send_frame[25] = sid; //++sid; /* SID */
fins_send_frame[26] = 0x01; /* MRC */ //1
fins_send_frame[27] = 0x01; /* SRC */ //read
// change to read:
fins_send_frame[28] = memory_area_designation_code(reg_addr); /* VARIABLE TYPE: DM*/
if(f!=0)
{
fprintf(f,"FINS/TCP memory area designation code = %d \n",fins_cmnd[28]);
}
if(memory_area_designation_code(reg_addr) == 0xB0) //-0x0c000
{
fins_send_frame[29] = (unsigned char)((reg_addr-0x0C000)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr-0x0C000)&0xFF); //low register
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
if(memory_area_designation_code(reg_addr) == 0xB1) //-0x0DE00
{
fins_send_frame[29] = (unsigned char)((reg_addr-0x0DE00)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr-0x0DE00)&0xFF);
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
if(memory_area_designation_code(reg_addr) == 0x82) //-0x10000
{
fins_send_frame[29] = (unsigned char)((reg_addr-0x10000)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr-0x10000)&0xFF);
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
if(memory_area_designation_code(reg_addr) == 0xB3) //-0x0BA00
{
fins_send_frame[29] = (unsigned char)((reg_addr-0x0BA00)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr-0x0BA00)&0xFF);
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
fins_send_frame[31] = 0x00;//bit number
//number of words to read:
fins_send_frame[32] = 0x00; /* WORDS READ: 1*/
fins_send_frame[33] = 0x01;
/* SEND FINS/TCP COMMAND*/
sendlen = 34;
sc.write((const char*)fins_send_frame,sendlen);
if(sc.waitForBytesWritten(RESP_TIMEOUT))
{
}
else
{
if(f!=0)
{
fprintf(f,"2.error in sending FINS send frame of command %d \n",sc.error());
}
return false;
}
//lets try to get response here
if(sc.waitForReadyRead(RESP_TIMEOUT))
{
if(f!=0)
{
fprintf(f,"2.received %d \n",recvlen = sc.bytesAvailable());
}
sc.read((char*)fins_receive_frame,recvlen);
//print received header:
if(f!=0)
{
for(int i =0;i<recvlen;i++)
{
}
}
//check for errors:
if(((int)fins_receive_frame[28] == 0) && ((int)fins_receive_frame[29] == 0) )
{
//command sent ok
sid++;
//lets get value:
*value = (int)((0x0000|fins_receive_frame[30])<<8) + (int)
(0x00FF&fins_receive_frame[31]);
if(f!=0)
{
//lets get value:
fprintf(f,"2.* value = %d \n",value);
}
return true;
}
else
{
//there were errors when sending
*value = 0;
if(f!=0)
{
//lets get value:
fprintf(f,"fields 28 and 29 are not null \n");
}
return false;
}
}
else
{
//can't get response - error:
//no response:
if(f!=0)
{
fprintf(f,"2.no response %d \n",sc.error());
}
return true;
}
***
Code snippet of writing to register ( function receives reg_addr - address of a register and value to put to that register ):
bool fins_write_reg (int reg_addr, const int value);->
static unsigned char fins_cmnd[MAX_MSG], fins_resp[MAX_MSG],fins_tcp_header[MAX_HEADER];
static unsigned char fins_send_frame[36], fins_receive_frame[30];
static unsigned char srv_node_no, cli_node_no;
static int sendlen, recvlen;
// char sid = 0;
if(sid > 0xFF)
sid = 0;
if(f!=0)
{
fprintf(f,"BEGIN TO WRITE \n");
fprintf(f," reg_addr = %d \n",reg_addr);
fprintf(f," value = %d \n",value);
}
/* SEND FINS/TCP COMMAND*/
/*
* GENERATE FINS COMMAND FRAME
*/
//fins header body
fins_send_frame[0] = 'F'; /* Header */
fins_send_frame[1] = 'I';
fins_send_frame[2] = 'N';
fins_send_frame[3] = 'S';
fins_send_frame[4] = 0x00; /* Length */
fins_send_frame[5] = 0x00;
fins_send_frame[6] = 0x00;
fins_send_frame[7] = 0x1C; //20+8;
fins_send_frame[8] = 0x00; /* Command */
fins_send_frame[9] = 0x00;
fins_send_frame[10] = 0x00;
fins_send_frame[11] = 0x02;
fins_send_frame[12] = 0x00; /* Error Code */
fins_send_frame[13] = 0x00;
fins_send_frame[14] = 0x00;
fins_send_frame[15] = 0x00;
//fins command body
fins_send_frame[16] = 0x80; /* ICF */
fins_send_frame[17] = 0x00; /* RSV */
fins_send_frame[18] = 0x02; /* GCT */
fins_send_frame[19] = 0x00; /* DNA */
fins_send_frame[20] = srv_node_no; /* DA1 *//* Ethernet Unit FINS NODE NUMBER*/
fins_send_frame[21] = 0x00; /* DA2 */
fins_send_frame[22] = 0x00; /* SNA */
fins_send_frame[23] = cli_node_no; /* SA1 *//* WS FINS NODE NUMBER
AUTOMATICALLY*/
fins_send_frame[24] = 0x00; /* SA2 */
fins_send_frame[25] = sid; /* SID */
fins_send_frame[26] = 0x01; /* MRC */ //1
fins_send_frame[27] = 0x02; /* SRC */ //1 - write
// change to write:
fins_send_frame[28] = memory_area_designation_code(reg_addr); /* VARIABLE TYPE: DM*/
if(f!=0)
{
}
if(memory_area_designation_code(reg_addr) == 0xB0) //-0x0c000
{
fins_send_frame[29] = (unsigned char)((reg_addr - 0x0c000)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr - 0x0c000)&0xFF);
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
if(memory_area_designation_code(reg_addr) == 0xB1) //-0x0DE00
{
fins_send_frame[29] = (unsigned char)((reg_addr - 0x0DE00)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr - 0x0DE00)&0xFF);
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
if(memory_area_designation_code(reg_addr) == 0x82) //-0x10000
{
fins_send_frame[29] = (unsigned char)((reg_addr - 0x10000)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr - 0x10000)&0xFF);
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
if(memory_area_designation_code(reg_addr) == 0xB3) //-0x0BA00
{
fins_send_frame[29] = (unsigned char)((reg_addr - 0x0BA00)>>8);
fins_send_frame[30] = (unsigned char)((reg_addr - 0x0BA00)&0xFF);
if(f!=0)
{
fprintf(f,"fins_send_frame[29] = %d \n",fins_send_frame[29]);
fprintf(f,"fins_send_frame[30] = %d \n",fins_send_frame[30]);
}
}
fins_send_frame[31] = 0x00;//bit number
//number of words to read:
fins_send_frame[32] = 0x00; /* number of data words */
fins_send_frame[33] = 0x01;
//putting actual write value:
fins_send_frame[34] = (unsigned char)(value >> 8); //high byte
fins_send_frame[35] = (unsigned char)(value&0xFF); //low byte
//displaying what is written:
if(f!=0)
{
fprintf(f,"fins_send_frame[34] = %d \n",fins_send_frame[34]);
fprintf(f,"fins_send_frame[35] = %d \n",fins_send_frame[35]);
}
sendlen = 36;
/* SEND FINS/TCP COMMAND*/
sc.write((const char*)fins_send_frame,sendlen);
if(sc.waitForBytesWritten(RESP_TIMEOUT))
{
if(f!=0)
{
}
}
else
{
if(f!=0)
{
fprintf(f,"2.error in sending FINS tcp send frame of command %d \n",sc.error());
}
return false;
}
//sc.flush();
//lets try to get response here :
if(sc.waitForReadyRead(RESP_TIMEOUT)) // here it is RESPONSE TIMEOUT ERROR
{
if(f!=0)
{
fprintf(f,"2.received %d \n",recvlen = sc.bytesAvailable());
}
sc.read((char*)fins_receive_frame,recvlen);
if(f!=0)
{
for(int i =0;i<recvlen;i++)
{
fprintf(f,"2.received fins_receive_frame[%d] = %d \n",i,fins_receive_frame[i]);
}
}
//basic check - no error
if(((int)fins_receive_frame[28] == 0) && ((int)fins_receive_frame[29] == 0))
{
//command sent ok
sid++;
if(f!=0)
{
fprintf(f,"receive response does not contain errors");
}
return true;
}
else
{
//there were errors when sending
if(f!=0)
{
fprintf(f,"receive response contains errors");
}
return false;
}
}
else //cannot receive response
{
if(f!=0)
{
fprintf(f,"3.no response %d \n",sc.error());
}
return true;
}
где f - некоторый временный указатель файла журнала sc - экземпляр QTcpSocket, который отправляет / принимает команды FINS PLC: CP1L-L14DT1-D Опциональная плата Ethernet: CP1W-CIF41
Функция кода обозначения области памяти:
int FinsOverEthCP::memory_area_designation_code(const int addr)
{
// area codes
if(addr>0x0BFFF&&addr<0x0D800) //B0 , CIO area
return 0xB0;
if(addr>0x0DDFF&&addr<0xE000) //work area
return 0xB1; //TODO: clarified code , from memory area designation codes table
if(addr>0xFFFF&&addr<0x18000) //DM area
return 0x82;
if(addr>0xB9FF&&addr<0xBC00) //A448 - A959
return 0xB3;
else
return 0x80; //CIO,LR,HR,AR area
}
Когда я тестировал команду с помощью программного обеспечения Multiway - ответ получен и значение занесено в регистр, но то же самое с QTcpSocket и ошибкой, почему?Мой вопрос к вам: возникала ли у вас такая проблема, когда вы запускаете драйвер FINS?Почему не может быть ситуации ответа, пока команда FINS write to register сформирована нормально?Если да, то как преодолеть / исправить?