Реализация протокола Omron FINS на стороне ПК с использованием Qt (C ++) [Driver] - PullRequest
0 голосов
/ 24 октября 2011

Я работаю для кроссплатформенного настольного приложения.Я разрабатываю его на 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 сформирована нормально?Если да, то как преодолеть / исправить?

1 Ответ

1 голос
/ 30 мая 2013

Я создал и использовал эту библиотеку в нескольких промышленных проектах, поэтому она стабильна. Но отсутствие документации. https://bitbucket.org/vladimirek/omronlib

...