QT Logo

Эта статья описывает один из вариантов работы с COM портом в асинхронном режиме.

Поскольку для QT я не нашёл подходящего мне инструментария, решено было написать свои классы работы с COM портом.

Предположим, что у нас есть некоторое устройство, которое может асинхронно передавать и принимать данные.

class Device
{
protected:
IOPort * m_ioport; // порт для устройства
public:
virtual void NewData(unsigned char * data, int len);
virtual bool MakeData(unsigned char * data, int * len);
};

Функция NewData будет вызываться по приходу пакета новых данных из COM порта. MakeData — будет периодически вызываться у класа прибора для опроса новых данных. Если данные для отправки есть — функция возвращает true, и заполняет массив data данными для отправки.

Наследуя своё устройство MyDevice от класса Device, и описав свои функции NewData и MakeData можно сделать нечто подобное:

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

MyDevice dev;
dev.CreatePort("/dev/ttyS0");

return a.exec();
}

Устройство dev будет жить своей жизнью, используя два треда. В одном будут формироваться данные на отправку, а во втором будут приниматься и разбираться входные данные.

Особенностью реализации класса COM-порта в Linux является, организация чтения из порта по приходу сигнала SIGIO. Для этого создан класс-нотификатор, который преобразует сигналы ядра SIGIO в сигналы QT. Каждый COM-порт подключается к данному QT-сигналу и получает оповещения о приходе нового символа из COM порта.

В исходниках выложена непроверенная реализация COM-портов и для Windows.

Скачать исходники проекта на QT (zip, 14k)