Soros port kezelés

2011.07.18. 10:16 | arabiata | Szólj hozzá!

Címkék: kommunikáció serial rs232 soros port

 Na, ez nincs a Qt-ban. Van egy qextserialport nevű utólag elkészített osztály, ami elvileg multiplatformos megoldást kínál. Belenéztem a forráskódjába, találtam benne néhány to-do és to be implemented megjegyzés. Ettől függetlenül lehet, hogy működik a dolog, de nem próbáltam ki. Hacsak nem akarjuk két gépet összekötve tesztelni a soros port kezelőt, van itt egy megoldás:

- Virtual serial port emulator (VSPE)

- Docklight scripting

- Putty

 A VSPE létrehoz két virtuális soros portot, amikre putty-al rákapcsolódva mehet a kommunikáció. A Docklight szerepe a putty-hoz hasonlít, csak sokkal többet tud. Ajánlok még két leírást http://www.robbayer.com/files/serial-win.pdf, és http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c5425.

Ezenkívül az http://msdn.microsoft.com/en-us/ is sok segítséget ad.

1. Port megnyitása:

/*

          adatok.at(3).toLocal8Bit().constData()

          adatok.at(3) -> QString

          adatok.at(3).toLocal8Bit() -> QByteArray

          adatok.at(3).toLocal8Bit().constData() -> const char *

          CreateFile -> WCHAR az első paraméter tipusa

          CreateFileA -> char az első paraméter tipusa

   */

 

  win_soros_leiro = CreateFileA(adatok.at(3).toAscii().constData(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

  if (win_soros_leiro == INVALID_HANDLE_VALUE) {

 

    log_iras(trUtf8("Soros port hiba kód: ") + QString::number(GetLastError()));

    return false;

 

  }

 Az adatok.at(3) tartalmazza a port nevét (COM1: pl.). Az overlapped szerepe, hogy ne álljon meg a program futása a soros portról várt adatok bejöveteléig.

 2. Paraméterek beállítása:

  DCB dcb;

  if (GetCommState(win_soros_leiro, &dcb) == false) {

    log_iras(trUtf8("GetCommState: ") + QString::number(GetLastError()));

    CloseHandle(win_soros_leiro);

    return false;

  }

  strcpy(munka, adatok.at(4).toAscii().constData());

  dcb.BaudRate = atoi(munka);

 

  strcpy(munka, adatok.at(5).toAscii().constData());

  dcb.ByteSize = atoi(&munka[0]);

 

  strcpy(munka, adatok.at(6).toAscii().constData());

  int_munka = atoi(&munka[0]);

  int_munka--;

  dcb.Parity = int_munka;

 

  strcpy(munka, adatok.at(7).toAscii().constData());

  int_munka = atoi(&munka[0]);

  int_munka--;

  dcb.StopBits = int_munka;

  if (SetCommState(win_soros_leiro, &dcb) == false) {

    log_iras(trUtf8("SetCommState: ") + QString::number(GetLastError()));

    CloseHandle(win_soros_leiro);

    return false;

  }

 A DCB struktúra tartalmazza a kommunikációs paramétereket: baud rate, paritás bit, stb. A CreateFile által visszaadott handler a win_soros_leiro. Kiolvassuk a DCB tartalmát, a szükséges elemeket módosítjuk, majd visszaírjuk az új tartalmat. Az adatok.at(6,7)-ből konvertálás után azért kell levonni 1-et, mert az adatbázisból az enum miatt 1-el nagyobb érték érkezik.

3. Időzítés beállítása:

  COMMTIMEOUTS timeouts = {0};

  timeouts.ReadIntervalTimeout = 0;

  timeouts.ReadTotalTimeoutMultiplier = 0;

  timeouts.ReadTotalTimeoutConstant = 2000;

  timeouts.WriteTotalTimeoutConstant = 0;

  timeouts.WriteTotalTimeoutMultiplier = 0;

  if (SetCommTimeouts(win_soros_leiro, &timeouts) == false) {

    log_iras(trUtf8("SetCommTimeouts: ") + QString::number(GetLastError()));

    CloseHandle(win_soros_leiro);

    return false;

  }

 

 Tekintve, hogy a soros port olvasását végtelen ciklusban végezzük, nem ildomos azt állandóan pörgetni. Így beállítottam egy 2 másodperces timeout értéket, hogy ennyit várjon a következő karakter érkezésére. Ha jön adat megszakad a timeout, és beolvassa a portról a ReadFile, ha nem jön semmi, a gép végzi a saját dolgát.

4. Overlapped struct beállítása:

  ov.Offset = 0;

  ov.OffsetHigh = 0;

  ov.Internal = 0;

  ov.InternalHigh = 0;

  ov.hEvent = NULL;

 5. Olvasunk:

int osztaly::olvasas() {

  bool retVal;

  DWORD atvitt_byte;

  olv[0] = 0;

  retVal = ReadFile(win_soros_leiro, &olv, sizeof (olv), NULL, &ov);

  if ((retVal == false) && (GetLastError() != ERROR_IO_PENDING)) {

    log_iras("ReadFile hiba: " + QString::number(GetLastError()));

    return -1;

  }

  retVal = GetOverlappedResult(win_soros_leiro, &ov, &atvitt_byte, TRUE);

  if (retVal == false) {

    if (GetLastError() != ERROR_IO_INCOMPLETE) {

      log_iras(trUtf8("GetOverlappedResult hiba: ") + QString::number(GetLastError()));

      return -1;

    }

  } else {

    feldolgozas(atvitt_byte);

  }

  return atvitt_byte;

}

 Ezt a függvényt futtatjuk végtelen ciklusban. A következő pontban megmutatom, hogy lehet kilépni a ciklusból. Itt egyedül a GetOverlappedResult érdekes, ez mondja meg, hogy befejeződött-e az olvasás a portról. Ha az utolsó paraméter FALSE, akkor nem várja meg az eredményközléssel az olvasás végét, hanem örömében TRUE-t ad vissza, ha valami adat érkezett. A feldolgozásnak elég gyorsnak kell lennie, hogy ne fogja meg az egész ciklus futását. Talán itt érdemes egy másik szálat futtani. ReadFile-nál ERROR_IO_PENDING akkor áll be, ha még folyik az olvasás a portról, és így a GetOverlappedResult is vár.

6. Kilépés a ciklusból:

void osztaly::futtato() {

  int retVal = -1;

  leallito = false;

  while (leallito == false) {

    retVal = olvasas();

    switch (retVal) {

    case -1:

      leallito = true;

      break;

    case 0:

      server_komm();

      break;

    }

  } // while

  takarito();

  return;

}

 Ha az olvasas -1-et ad vissza, gáz van. Ha 0-t, a beállított timeout járt le, semmi adat nem érkezett a portról.

7. Programozott leállítás:

void osztaly::server_komm() {

  int olv_bytes = 0;

  char olv[5];

  leallito = false;

  kliens->disconnectFromServer();

  kliens->connectToServer("qt_labor");

  if (kliens->state() == QLocalSocket::ConnectedState) {

    kliens->waitForReadyRead(1000);

    olv_bytes = kliens->readLine(olv, 5);

  }

  qDebug() << olv << olv_bytes;

  if (strcmp(olv, "STOP") == 0) {

    leallito = true;

  }

}

 

 

A bejegyzés trackback címe:

https://qtqt.blog.hu/api/trackback/id/tr433076315

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása