Кросплатформенная работа с COM портом

 
0
 
C++
ava
Mal Hack | 01.02.2008, 13:40
Доброе время суток!

Задача: открыть СОМ порт, послать пакет, получить ответ, прочитать. Все. Частота съема 100 Гц.

Посмотрел темы по сабжу. В большинстве из них работа с ком портом идет через CreateFile, что, как я понимаю, под никсами не работает. А нужен именно кросплатформенный вариант. В одной из тем было упоминание fopen... В никсах да, логично: /dev/ttyS0, а как в винде с этим  работать?

Есть другой вариант? Нужно сделать именно средставами стандартного С++.

Вопрос не совсем в тему, но для данного случая тоже важен. Есть переходник COM->USB, вот если работаю через такую вещь, чтение запись писать относительно USB или он будет полностью моделировать COM?

Спасибо.
Ответы (18)
ava
EnergoHokum | 01.02.2008, 16:01 #
Блин!!! Ты будешь смеяться, но:

    FILE* ff;
    if((ff=fopen("COM1","r+")) == NULL)
    { printf("Can`not open \"COM1\"\n"); return -1; }
    fclose(ff); return 0;


А я-то уже полез в глобальное пространство имён, искать "каталог", где могут эти "файлы" лежать... Видно, ссылка жёсткая есть на них.
ava
Mal Hack | 01.02.2008, 16:06 #
EnergoHokum, смеяться я не буду, потому что задачу надо решать... Такой вариант у меня есть, само собой, но неужели он будет работать, зная всю любовь майкрософта к офигенно удобному доступу к железу....
ava
EnergoHokum | 01.02.2008, 16:09 #
А чем это будет отличаться от использования ::CreateFile() кроме невозможности установки атрибутов защиты? Должно работать...
ava
Mal Hack | 01.02.2008, 16:15 #
Так "должно" или "проверенно"... Вот в чем вопрос... Ну нет у меня возможности на винде протестировать... Сейчас по крайней мере smile
ava
EnergoHokum | 01.02.2008, 16:18 #
А что тебя именно интересует? Будут ли отправляться в порт что_мне_захочется_туда_послать?

Ну вот счас под M$Win запустил монитор порта, и сделал так:

#include <stdio.h>

int main(int argc,char** argv)
{
    FILE* ff;
    if((ff=fopen("COM1","r+")) == NULL)
    { printf("Can`not open \"COM1\"\n"); return -1; }
    fprintf(ff,"Text send in COM1-port\n");
    fclose(ff); return 0;
    return 0;
}


-- монитор видит, что в порт сыпется.

А вот ссылка с ЛОР-а, там про /dev/ttyX в GNU/Linux пишут. Может, пригодится...
ava
Lazin | 01.02.2008, 16:21 #
Условная компиляция вам поможет.
Можно класс для работы с портом написать и реализовать его по разному на разных платформах, а интерфейс сделать один и тот-же, там и писать то толком нечего, если конечно не надо с ним асинхронно работать.
EnergoHokum, а параметры порта как устанавливать будешь  smile 
ava
Mal Hack | 01.02.2008, 16:27 #
Цитата (Lazin @  1.2.2008,  16:21 findReferencedText)
Можно класс для работы с портом написать и реализовать его по разному на разных платформах, а интерфейс сделать один и тот-же, там и писать то толком нечего, если конечно не надо с ним асинхронно работать.

Это не шибко удобно. В самой программе есть намного больше, над чем стоит так работать...

Цитата (Lazin @  1.2.2008,  16:21 findReferencedText)
Условная компиляция вам поможет.

Если мне не изменяет память, это #ifdef и т.п., но стандартным макросов, определящию ОС я там не нашел..

Цитата (EnergoHokum @  1.2.2008,  16:18 findReferencedText)
А что тебя именно интересует? Будут ли отправляться в порт что_мне_захочется_туда_послать? 

Работоспособность, т.е. не будет ли система воспринимать COM1, как имя файла в текущем каталоге ;)

Цитата (Lazin @  1.2.2008,  16:21 findReferencedText)
EnergoHokum, а параметры порта как устанавливать будешь  smile  

Как я понимаю, чтение/запись устанавливается в fopen, а остальное.... В принципе ничего такого сверхестественного не надо, порт работает в стандартном режиме.
ava
EnergoHokum | 01.02.2008, 16:29 #
Хм, #ifdef-ом, вестимо, tcgetattr(), tcsetattr() под M$Win нету, если только Cygwin использовать, но это может быть неприемлемо.

Добавлено позднее:
Цитата


не будет ли система воспринимать COM1, как имя файла в текущем каталоге



Если я правильно понял, то при всём желании ты не сможешь создать файл COM1 в текущем каталоге, ибо:
Цитата


The following reserved device names cannot be used as the name of a file: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9. Also avoid these names followed by an extension, for example, NUL.tx7.

ava
Mal Hack | 01.02.2008, 22:16 #
Цитата (EnergoHokum @  1.2.2008,  16:29 findReferencedText)
Хм, #ifdef-ом, вестимо, tcgetattr(), tcsetattr() под M$Win нету, если только Cygwin использовать, но это может быть неприемлемо.

Не совсем понял тебя, по части слова "вестимо" smile сигвин отменяется.

Цитата (EnergoHokum @  1.2.2008,  16:29 findReferencedText)
Если я правильно понял, то при всём желании ты не сможешь создать файл COM1 в текущем каталоге, ибо:

Окей. Сделаю так, посмотрим, что из этого получится.
ava
EnergoHokum | 02.02.2008, 10:43 #
Ну, я в смысле, что в M$Win и в GNU/Linux разные функции управляют настройками порта (скорость, количество бит, проверка чётности и проч. проч. проч...).
ava
Mal Hack | 26.02.2008, 22:22 #
Вот, сварганил, как появится возможность буду тестировать smile

#include "COM.h"

using namespace std;

FILE * nsComPort::comOpen(string port)
{
    string filename("COM"+port);

    return fopen(filename.c_str(),"rwb");
}

void nsComPort::comReadPort(FILE * COM, signed short int *out, signed short int *in)
{
    fwrite(out, 22, 1, COM);
    fread(&in, 22, 1, COM);
}

void nsComPort::comClose(FILE * COM)
{
    fclose(COM);
}
ava
Denjs | 03.03.2008, 03:08 #
по поводу кроссплатформенной работы с компортом и настройки компорта под линукс и виндоус:
я под QT писал, но куски кода которые работают с портом - не используют ничего кроме "наитивных возможностей".
потому посмотри. У меня через Open/CreateFile и без инициации асинхронной работы (я запускаю
отдельный поток в котором читаю порт с таймаутом. не слишком изящЪно может но работает)

Все это входит в "OTPD Device Links
https://developer.berlios.de/projects/otpdlinks/
скачать примеры - и смотри (пример кстати под штрих500 сделан - если кто знает что это за устройство).
за ответом по поводу работы с ком-портом - там класс t_seriallink_otpd есть - исходники его глянь ( t_seriallink_otpd.cpp ) - там есть фактическое сопоставление процесса настройки под виндоус и под линукс (разные секции условной компиляции) - думаю разобраться можно.


Есть ещё проект (не моё )) ):
"QextSerialPorthttp://qextserialport.sourceforge.net/
- тоже работа с ком-портом - более тонкие чем у меня настройки. имхо немного более хитро реализован.
Аналогично для QT. Под Виндоус и линукс.

________________
ava
takedo | 07.03.2008, 07:00 #
Mal Hack,


Цитата


EnergoHokum, а параметры порта как устанавливать будешь  smile  



Как я понимаю, чтение/запись устанавливается в fopen, а остальное.... В принципе ничего такого сверхестественного не надо, порт работает в стандартном режиме.

 smile3  smile3
Ты абсолютно не верно понимаешь. На самом деле передача по порту имеет кучу параметров! Такие например как стоповые биты(от 1 до 2х), количество бит информации(от 7 до 10), бит чётности, и наконец скорость передачи. Все это выглядит физически как "пила" напряжения на входе-выходе порта. Чем больше частота работы с портом, тем меньше времени занимают зубцы. Если один компьютер работает на частоте 115000, другой 4800, то представь, как один из них может поднаи...ться при чтении данных? Работа в винде с портом идет через драйвер, там есть очередь входящей инфы и исходящей. Микрософт для этого придумала функцию КреатеФиле и сопутствующие, что придумал юникс - я не андерстенд. Но знаю точно одно - работа с портом это нестандартное дело для С/С++! Так что, если есть желание сделать один файл с кодом и для юниксов и для виндовсов - условная компиляция. В винде точно есть переменная, говорящая, что это винда, можешь на неё ориентироваться. Удачи.
ava
andrew_121 | 07.03.2008, 07:47 #
Цитата (EnergoHokum @ 1.2.2008,  16:09)
А чем это будет отличаться от использования ::CreateFile() кроме невозможности установки атрибутов защиты? Должно работать...

::CreateFile() - это ВинАпи, с помощью этой ф-ции под виндой можно открыть все что только может открываться,
поэтому не нужно путать оную с POSIX-open() или fopen();
А так-как говориться о кроссплатформенности, то этот подход не совсем тот.

Почитайте: http://www.xml.com/ldd/chapter/book/

Я делал такое, и...
Удачи...
ava
redman1986 | 20.03.2008, 10:44 #
Если интересует под Qt (класс  Qextserialport) могу помочь.... писал проект для работы с COM - портом на QT (3.3.4)
ava
Mal Hack | 20.03.2008, 23:42 #
fopen в винде не катит совершенно...
Вишка вот какая.. Надо открывать через CreateFile, затем устанавливать DCB (Device Control Bloc) и после этого работать.

http://www.realcoding.net/article/view/2416 - ссылка...
ava
EnergoHokum | 24.03.2008, 09:47 #
А какая в данном случае разница, что использовать -- fopen или CreateFile? Функция установки параметров порта BuildCommDCB не привязана к handle открываемого устройства, она первым параметром принимает символическое имя (COM3, LPT0 etc.) устройства, параметры которого настраиваем.
ava
Mal Hack | 25.03.2008, 00:06 #
Мне все параметры настраивать не нужно. Поэтому юзаю GetCommState/SetCommState...
Зарегистрируйтесь или войдите, чтобы написать.
Фирма дня
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Участники
advanced
Отправить