Современные технологии автоматизации» («СТА») —  журнал для квалифицированных специалистов по промышленной автоматизации Форум СТА — современные технологии автоматизации Домашняя страница
Домашняя страница форума CTA Домашняя страница форума CTA > II. АСУТП и SCADA > Архив
  Активные темы Активные темы
  FAQ FAQ  Искать в форуме   Зарегистрироваться Зарегистрироваться  Вход в систему Вход в систему

Программирование HART модема

 Ответить Ответить
Автор
Сообщение
HART-USER Смотреть выпадающим
Новичок
Новичок


Присоединился: 29 Апрель 2005
Online Status: Offline
Публикации: 1
Свойства публикации Свойства публикации   Ответить, цитируя автора - HART-USER Ответить, цитируя автора -  ОтветитьОтвет Прямая ссылка на эту публикацию Тема сообщения: Программирование HART модема
    Опубликовано: 29 Апрель 2005 17:47

Доброго всем времени суток! Очень прошу откликнуться lamerokа!!! И всех соображающих в этой области тоже прошу помочь!
Пожалуйста помогите кто работал с HART модемом.
Мне необходимо прочитать с датчика давления ABB Kent-Teylor серийный номер. Воспользовался кодом lamerokа. Ответ от датчика есть, только если посылаем фрейм с командой 0. Приходят данные в виде цифр:254,255,255...8,5,2.... (на посланные мной 11 байт приходит 27байт), как преобразовать в нормальный вид (допустим в цифры серийного номера или значение переменной)???.Если посылаю другие команды(1 или 0х01,2 или 0х02 и т.д.),то ответа нет.В чем дело??? Может я не правильно пишу код команды? Программу пишу на С++ Builder6.
Привожу код:

HANDLE hCom;
DCB dcb={0};
COMSTAT comStat;
COMMTIMEOUTS  ct;
DWORD dwWrite, dwFactWrite, dwWait, dwRead=0, dwErr, dwNumB, dwRMask=EV_TXEMPTY;
OVERLAPPED Sync={0};
String strPC="PC: ", strABB="ABB: ";

//**************код lamerokа********************************************************      
BYTE sbuf[100] = {0};
int max_send = 0;
BYTE devN = 0;    
BYTE rbuf[100] = {0};

BYTE CalculateCRC(BYTE* buff, int buff_len)
{
 BYTE crc = 0;
 for (int i=0; i<buff_len; i++)
  crc ^= buff;
 return crc;
}

void FillShortFrame(int preamble_size, BYTE dest, BYTE cmd, BYTE* data, BYTE data_len, BYTE* sbuf, int& nSend)
{
 // преамбула
 for (int i=0; i<preamble_size; i++) sbuf = 0xFF;
 sbuf[preamble_size]  = 0x02;        // короткий кадр, master-to-slave
 BYTE addr = 0x80;
 addr |= (dest & 0x80);
 sbuf[preamble_size+1] = addr;
 sbuf[preamble_size+2] = cmd;
 sbuf[preamble_size+3] = data_len;
 memcpy(sbuf+preamble_size+4, data, data_len);
 BYTE crc = CalculateCRC(sbuf+preamble_size, data_len+4);
 sbuf[preamble_size+4+data_len] = crc;
 nSend = data_len + 5 + preamble_size;
}
//**************************************************************************************   


//***********Кнопка открытия порта***********************************************

void __fastcall TForm1::bOpenPortClick(TObject *Sender)
{
hCom=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);

if (hCom==INVALID_HANDLE_VALUE)
   {MessageDlg("Ошибка открытия порта",mtError,TMsgDlgButtons()<<mbOK,0);
   return;}

   dcb.DCBlength        = sizeof(DCB);
   dcb.BaudRate         = CBR_1200;
   dcb.Parity           = ODDPARITY;
   dcb.fBinary          = 1;
   dcb.ByteSize         = 8;
   dcb.StopBits         = ONESTOPBIT;
   dcb.fDtrControl = DTR_CONTROL_ENABLE;
   dcb.fRtsControl = RTS_CONTROL_TOGGLE;

 ct.ReadIntervalTimeout = 0;
 ct.ReadTotalTimeoutMultiplier = 0;
 ct.ReadTotalTimeoutConstant = 1000;
 ct.WriteTotalTimeoutMultiplier = 0;
 ct.WriteTotalTimeoutConstant = 1000;

SetCommState(hCom,&dcb))
SetCommMask(hCom, EV_TXEMPTY))
EscapeCommFunction(hCom,SETDTR))
SetCommTimeouts(hCom,&ct))

}

//***********Кнопка записи и чтения сообщения*******************************

void __fastcall TForm1::bSendToPortClick(TObject *Sender)
{
//*****************************WRITING THE DATA*****************************

// Очищаем буферы приема/передачи
PurgeComm(hCom, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR)

Sync.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);

/////////////////////////////////////////////////////////////////////////////

BYTE cmd = 0;//!!! вот здесь меняю команду и в ответ ничего не приходит !!!

FillShortFrame(6, devN, cmd, NULL,0 , sbuf, max_send);

/////////////////////////////////////////////////////////////////////////////

WriteFile(hCom,sbuf,max_send,&dwFactWrite,&Sync)
  
CloseHandle(Sync.hEvent);

//*****************************READING THE DATA*****************************

Sync.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);

if (!WaitCommEvent(hCom,&dwRMask,&Sync))
   {
   if (GetLastError()==ERROR_IO_PENDING)
      {
      dwWait=WaitForSingleObject(Sync.hEvent, TIMEOUT);
      switch(dwWait)
         {
         case WAIT_OBJECT_0:

                     dwNumB=comStat.cbInQue;// количество байтов в приемном буфере
                    
                     if(ReadFile(hCom,rbuf,dwNumB,&dwRead,&Sync))
                       {
                       
                //*****В процессе выполнения программа попадает сюда*******//
          
                        Memo1->Lines->Add(strABB + rbuf[0]); // сюда вывожу
                        Memo1->Lines->Add(strABB + rbuf[18]);// часть полученной
                        Memo1->Lines->Add(strABB + rbuf[19]);// информации                       
                        CloseHandle(Sync.hEvent);
                        return;
                       }
        

         case WAIT_TIMEOUT:
                  Memo1->Lines->Add("TimeOut...");
                  CloseHandle(Sync.hEvent);
                  return;

         default:
                  MessageDlg("Ошибка выполнения операции WaitForSingleObject (RF)",mtError,TMsgDlgButtons()<<mbOK,0);
                  CloseHandle(Sync.hEvent);
                  return;
         }
      }
   else
      {MessageDlg("Ошибка в WaitCommEvent",mtError,TMsgDlgButtons()<<mbOK,0);
      CloseHandle(Sync.hEvent);
      return;}
   }
else
   {
   dwNumB=comStat.cbInQue;

   if(ReadFile(hCom,rbuf,dwNumB,&dwRead,&Sync))     
      {
      Memo1->Lines->Add(strABB + rbuf[0]);
      CloseHandle(Sync.hEvent);
      return;
      }
   }
}

Многие проверки на ошибки я убрал, чтобы код был поменьше.
С нетерпеньем жду откликов.

Наверх
casey Смотреть выпадающим
Новичок
Новичок
Аватар

Присоединился: 19 Июль 2005
Категория: Ukraine
Online Status: Offline
Публикации: 39
Свойства публикации Свойства публикации   Ответить, цитируя автора - casey Ответить, цитируя автора -  ОтветитьОтвет Прямая ссылка на эту публикацию Опубликовано: 19 Июль 2005 14:46

Для чтения заводской инфы я использу такой код:

могут быть небольшие ошибки, я его почистил от лишнего, а для команд 0х01, 0х02, и т.д. нужно использовать длинный фрейм, в котором адрес уже не 1 байт, а 5 - эти байты ты собственно и получаешь командой 0х00;

 

struct data_00
{
BYTE preamb1,preamb2,preamb3,preamb4,preamb5,preamb6;
BYTE frame;
BYTE addr1;
BYTE command;
BYTE ByteCount;
BYTE CheckSum;
};

struct data_03
{
BYTE preamb1,preamb2,preamb3,preamb4,preamb5,preamb6;
BYTE frame;
BYTE addr1,addr2,addr3,addr4,addr5;
BYTE command;
BYTE ByteCount;
BYTE CheckSum;
};

struct otvet_00
{
BYTE addr1;
BYTE command;
BYTE ByteCount;
BYTE status1,status2;
BYTE x254;
BYTE manuf_ID;
BYTE device_type;
BYTE num_preambles;
BYTE com_revision;
BYTE cmd_revision;
BYTE soft_revision;
BYTE hard_revision;
BYTE func_flags;
BYTE IDnumber1,IDnumber2,IDnumber3;
BYTE CheckSum;
};

struct otvet_03
{
BYTE addr1,addr2,addr3,addr4,addr5;
BYTE command;
BYTE ByteCount;
BYTE status1,status2;
BYTE milliamper[4];
BYTE PVunits;
BYTE PV[4];
BYTE SVunits;
BYTE SV[4];
BYTE TVunits;
BYTE TV[4];
BYTE FVunits;
BYTE FV[4];
BYTE CheckSum;
};

BYTE aa;
float ff,aa1;

TForm1 *Form1;
HANDLE Comport=NULL;
DCB dcb1;
COMMTIMEOUTS comtimeouts;
COMSTAT statistic;

data_00 data0;
data_03 data1,data_d;
otvet_03 otvet1,otvet_d;
otvet_00 otvet0;
BYTE recv;

    DWORD nNumberOfBytesToWrite; 
    DWORD lpNumberOfBytesWritten; 

 


void __fastcall TForm1::Button3Click(TObject *Sender)
{
int i,k;

 

Comport = CreateFile(ComboBox1->Text.c_str(),
    GENERIC_READ | GENERIC_WRITE,
    0,    /* comm devices must be opened w/exclusive-access */
    NULL, /* no security attrs */
    OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
    0,    /* not overlapped I/O */
    NULL  /* hTemplate must be NULL for comm devices */
    );

if (Comport!=INVALID_HANDLE_VALUE)
{


GetCommState(Comport, &dcb1);
dcb1.BaudRate=1200;
dcb1.fBinary=1;
dcb1.fParity=1;
dcb1.fDtrControl=1;
dcb1.Parity=1;
dcb1.ByteSize=8;
dcb1.StopBits = ONESTOPBIT;
SetCommState(Comport, &dcb1);

comtimeouts.ReadIntervalTimeout=0;
comtimeouts.ReadTotalTimeoutMultiplier=0;
comtimeouts.WriteTotalTimeoutMultiplier=0;
comtimeouts.ReadTotalTimeoutConstant=750;
comtimeouts.WriteTotalTimeoutConstant=750;
SetCommTimeouts(&Comport,&comtimeouts);


PurgeComm(Comport,PURGE_TXCLEAR);
PurgeComm(Comport,PURGE_RXCLEAR);

i=1; - адрес устройства

data0.preamb1=0xff;
data0.preamb2=0xff;
data0.preamb3=0xff;
data0.preamb4=0xff;
data0.preamb5=0xff;
data0.preamb6=0xff;
data0.frame=0x02;
data0.addr1=128+i;
data0.command=0x00;
data0.ByteCount=0x00;
data0.CheckSum=data0.frame^data0.addr1^data0.command^data0.ByteCount;


if (WriteFile(
    Comport, // handle to file to write to
    &data0, // pointer to data to write to file
    sizeof(data0), // number of bytes to write
    &lpNumberOfBytesWritten, // pointer to number of bytes written
    NULL  // pointer to structure needed for overlapped I/O
   ))
{
Sleep(700);
   ClearCommError(Comport,NULL,&statistic);
   if (statistic.cbInQue>0)
for (recv=0x01,k=0;(recv!=0x06) && (statistic.cbInQue>0) ;k++)
{
   ClearCommError(Comport,NULL,&statistic);
   if (k>22) break;
   if (statistic.cbInQue>0)
   ReadFile(
    Comport, // handle of file to read
    &recv, // address of buffer that receives data
    1, // number of bytes to read
    &lpNumberOfBytesWritten, // address of number of bytes read
    NULL // address of structure for data
   );
}

   ClearCommError(Comport,NULL,&statistic);
   if (statistic.cbInQue>=sizeof(otvet0))
   {
   ReadFile(
    Comport, // handle of file to read
    &otvet0, // address of buffer that receives data
    sizeof(otvet0), // number of bytes to read
    &lpNumberOfBytesWritten, // address of number of bytes read
    NULL // address of structure for data
   );
}
}
}
}
else Label1->Caption=ComboBox1->Text+" can't open!!!";
}

 

Наверх
 Ответить Ответить

Переход на форум Права доступа на форуме Смотреть выпадающим

Bulletin Board Software by Web Wiz Forums® version 9.64
Powered by Web Wiz Forums Free Express Edition
Copyright ©2001-2009 Web Wiz