Часто бывает необходимо, чтобы работа с устройством поддерживалась как в windows, так и в linux. В моем случае нужно было обеспечить работу com-порта в приложении, написанном на с/с++ с использованием кроссплатформенной библиотеки QT. Штатной поддержки программирования портов в QT нет (да и ни к чему это). Поэтому в win32 для работы с портом будем использовать средства WinAPI. В linux системах же, как известно для работы с устройствами используются специальные файлы.
Итак, взяв на вооружение всем знакомый gcc и его windows-аналог mingw, напишем нехитрый код.
Код будет довольно таки искусственным, т.к. ставится цель не более, чем показать принципы работы с com-портами в двух операционках. Для управления компилятором будем использовать директивы определения компилятора и ОС (__MINGW32__ и __linux). Com-портом в нашем случае является устройство dev/ttyS0 и COM1.
Здесь в win32 используется функция CreateFile, параметры по ссылке в коде. Функция возвращает хендл на на устройство, в которым мы дальше будем работать. Аналогично работает и open в linux.
Для записи в порт используем ранее возвращенный хендл и пишем соответствующими функциями.
Процедура чтения выглядит аналогично.
Кроме того, существуют функции для настройки самих портов. Об их использовании я, возможно, напишу в следующих статьях. В нашем примере все работает по стандартным настройкам системы.
Осталось дело за малым — скомпилировать код под каждую из ОС.
Надеюсь, что эта практика пригодится кому-то, кроме меня самого.
Приятного си-программирования!
Итак, взяв на вооружение всем знакомый gcc и его windows-аналог mingw, напишем нехитрый код.
Код будет довольно таки искусственным, т.к. ставится цель не более, чем показать принципы работы с com-портами в двух операционках. Для управления компилятором будем использовать директивы определения компилятора и ОС (__MINGW32__ и __linux). Com-портом в нашем случае является устройство dev/ttyS0 и COM1.
Инициализация
#ifdef __MINGW32__
#include <windows.h>
#endif
#ifdef __linux
#include <sys/types.h>
#include <fcntl.h>
#endif
#include <stdio.h>
int main() {
#ifdef __MINGW32__
HANDLE hSerial = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if (hSerial == INVALID_HANDLE_VALUE) {
printf("Error opening port\r\n");
return -1;
}
#endif
#ifdef __linux
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY );
if (fd <0) {
printf("Error opening port\n");
return -1;
}
#endif
...
Здесь в win32 используется функция CreateFile, параметры по ссылке в коде. Функция возвращает хендл на на устройство, в которым мы дальше будем работать. Аналогично работает и open в linux.
Запись
char * data; // данные записи в порт
data[0] = 0x01;
#ifdef __MINGW32__
DWORD dwBytesWrite = 0; // кол-во записанных байтов
if(!WriteFile(hSerial, data, 1, &dwBytesWrite, NULL)){
printf("write error\r\n");
}
#endif
#ifdef __linux
int iOut = write(fd, data, 1);
if (iOut < 0){
printf("write error\n");
}
#endif
Для записи в порт используем ранее возвращенный хендл и пишем соответствующими функциями.
Процедура чтения выглядит аналогично.
Чтение
char * buffer;
#ifdef __MINGW32__
if(!ReadFile(hSerial, buffer, 1, &dwBytesWrite, NULL)){
printf("read error\r\n");
}
#endif
#ifdef __linux
int iOut = read(fd, buffer, 1);
if (iOut < 0){
printf("read error\n");
}
#endif
Закрытие порта
#ifdef __MINGW32__
CloseHandle(hSerial);
#endif
#ifdef __linux
close(fd);
#endif
Кроме того, существуют функции для настройки самих портов. Об их использовании я, возможно, напишу в следующих статьях. В нашем примере все работает по стандартным настройкам системы.
Осталось дело за малым — скомпилировать код под каждую из ОС.
Надеюсь, что эта практика пригодится кому-то, кроме меня самого.
Приятного си-программирования!