voral, я тут накопал примеров работы с modbus(master-sleve) на сях, подскажите, пожалуйста, можно их будет применить(интерпретировать) к dibus. Возможно это не корректный вопрос, но мой уровень не позволяет большего :( ...
voral, я тут накопал примеров работы с modbus(master-sleve) на сях, подскажите, пожалуйста, можно их будет применить(интерпретировать) к dibus. Возможно это не корректный вопрос, но мой уровень не позволяет большего :( ...
все зависит от примеров.... В любом случае в примерах стоит изучить и понять как все сделано. А там уж видно будет. Вообще в таких вещах брать чужой код опасно не разобравшись - баг вылезет замучаешься искать. Мало ли в алгоритме автор заложил копированием памяти что то кудато прописывать характерное для модбаса в неожиданном месте......
К тому же я в dibus не вчитывался особо - взглянул по диагонали :)
Привет всем
Обращаюсь снова к Вам за помощью :rolleyes:
Тут меня "до глубины душевной" проблема тронула. Поняв, что порт на отрез отказывается со мнос сотрудничать, я максимально упростил пример от сюда http://libserial.sourceforge.net: открываю порт, устанавливаю значение структуры termios newtio и сохраняю настройки -
Затем в отладчике проганяю прогу и командой setserial просматриваю параметры порта - НИ КАКОЙ РАЗНИЦЫ - параметры не поменялись :( :O
Подскажите, пожалуйста, с чем это связано?
Я не пользуюсь отладчиком и у меня не бывало таких чудес, чтобы tcsetattr
не выполнилась. setserial для проверки програмы тоже никогда не использовал.
Надо понять, что надо от порта и эти параметры установить.
"man termios" достаточно подробный. Правда, когда я только начинал работать
с COM-портом, я пользовался книгой на русском, где termios очень подробно
описана. Это было лет 10 назад.
Я как-то не имел с этим проблем ни в DOS, ни в Windows, ни в Linux.
Обмен всегда делается по определёному протоколу, вот и реализуйте его.
Если сомневаетесь, что tcsetattr выполняется, проверьте с помощью
tcgetattr. М.б., она выполняется, но не так, как вам хочется.
Если вы устанавливаете параметры порта с помощью termios, то вы его
полный хозяин, как напишете, так и будет работать.
Привет всем
С Новым Годом и Рождеством Христовым! smile
Объясните, пожалуйста, что я не так делаю :rolleyes:
Я просто сделал две проги одна пишет, другая читает (фиг уж с этими настройками!). Так вот чтение зависает...
strace показало: read(3 ... - зависание...
Тоже и с утилой cat - виснет зараза: в консоле(при записи) отобразилась сторока(из используемого файла), курсор остановился после последнего символа и завис (вроде должно перейти к готовности принятия команд?). На чтение - сразу виснет :(
Вот чё это за ...
Поскольку мы не знаем, что вы делаете, поэтому не можем сказать, что вы делаете не так.
Я тоже однажды сделал две коротких программы, одна консольная в Linux, другая
с небольшим окном в Windows, обменивались данными через COM-порт. Одна посылала
строку, другая принимала, выводила на экран и посылала обратно, 1-я её принимала,
выводила и посылал новую.
То, что чтение зависает, видно и без strace. Либо неправильно настроена termios,
не в соответствии с протоколом, либо неправильно вызывается системная read.
У меня всегда была подпрограмма чтения, уже из которой вызывалась read,
т.к. были разные протоколы обмена.
Поскольку мы не знаем, что вы делаете, поэтому не можем сказать, что вы делаете не так. Пётр.
- хотел протестировать скачанные проги http://sourceforge.net/projects/libserial/- Не получилось :(
Заием решил протестировать на уровне утилит - результат тот-же :(
(создаю файл с текстом; в одной раб. панеле записываю этот файл в порт: cat; в другой - считываю из порта....)
Я наскоро посмотрел, что это такое.
Однажды в Qt я сам сделал класс для COM-порта для Linux и базовый для него тоже,
т.к. меня не устраивал имеющийся в Qt базовый класс, что-то похожее на IODEVICE.
Там есть пример, работает ли он у вас? Он почему-то для работы с /dev/ttyUSB0.
На чистом C++ я реальных программ не писал, если бы потребовалось, сделал бы
что-нибудь попроще, ориентируясь на класс для Qt.
Точнее, у меня было 2-3 программы для Windows, но они не работали с COM-портом.
Мне это кажется излишне сложным. Если у вас программа на C++, то ничто не
мешает работать с COM-портом так же, как в программе на C, т.е. самому открыть
порт, установить свойства, написать программы для чтения и записи для конкретного
протокола связи и ими пользоваться. Это будет и быстрее, чем в примере, где чтение
из порта посимвольное.
Привет всем
Спасибо большое, Peter, за участие smile
Peter написал:
На чистом C++ я реальных программ не писал, если бы потребовалось, сделал бы что-нибудь попроще...
Так я и сделал как можно проще...
Объясните мне непонятливому, пожалуйста :rolleyes: , с чем связано такое поведение:
Делаю две проги на запись и чтение
text
int open_port(void)
{
int fd;
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY |O_NONBLOCK);
if (fd == -1)
perror("open_port: Unable to open /dev/ttyS0 - ");
else
{
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &options);
}
fcntl(fd, F_SETFL, 0);
return (fd);
}
...
int n = write(fd,"STROKA\n",6);
...
int n ;
while(n != -1)
{
n = read(fd,&ch,1);
....
}
И тут начинается самое интересно oO
- Кольцо - запускаю ридера в одном сеансе, а запись в другом - чтение подвисает(как я и писал...), даже не выполняется printf перед read
- Кольцо - запускаю прослушку cat /dev/ttyS0 и она срабатывает: отображается строка и ждет...
- Ставлю заглушку на один порт - ридер работает нормально, в случаи побайтового считывания. В противном случаи зацикливается и выводит то по 2 символа, то по 3 и кракозябру....
Я сам не очень понятливый, т.к. из приведённого мне не ясно, что вы там запускаете.
Покажите всю программу.
1) Не вижу тут двух портов;
2) Было бы логичнее, если бы open_port принимала как аргумент ссылку на fd
в основной программе, хотя можно и так;
3) При вызовах системных функций лучше использовать символические имена для флагов,
а не константы. Что вы подразумевали в вызове fcntl? В open указано ведь O_RDWR.
4) Что вы называете сеансом? Вообще проверить кольцо из двух портов можно и в одной
программе и с помощью двух независимых, одна из которых пишет, а другая читает.
Вот пример работающей программы, в case 1, 2, 4, 5 она пишет в порт и ждёт ответа,
в case 3 она, кроме этого, начиная со 2-го раза для записи ждёт, когда другая сторона
выставит сигнал DSR.
Как здесь делать вложение, я не помню. Текст можно привести в читаемый вид с помощью
команды indent.
int readto(int fd,char* buf){
//reads from fd to buf+1 bytes until '\r' with timeout VTIME/10.
int nb=1;
ssize_t nr;
while(*(buf+nb-1)!='\r'){nr=read(fd,(void*)(buf+nb),1);
if(nr<=0){if(nb==1){if(buf[0]==' ')fprintf(stdout,"timeout at 1st\n");
nb=0;}break;}
else{if(buf[0]!=' ')fprintf(stdout,"readto: %d %d\n",nb,buf[nb]);nb++;}}
if(nb>1){if(buf[nb-1]=='\r')buf[nb-1]=0;else buf[nb]=0;}
return nb-1;}
// chpa2_d.in
14 ibr, 15 - 38400
1 icom, 1 - ttyS0
2 nd in sec
4 nw in sec
60 ivt in 0.1s
1 idv, 1/2 - COM/USB
void main()
{
int fd = open_port();
if (fd < 0)
exit(-1)
int n ;
while(n != -1)
{
if (n == -1)
break;
// Получается считывать только по-байтно
n = read(fd,&ch,1);
....
}
}
int open_port(void)
{
int fd;
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY |O_NONBLOCK);
if (fd == -1)
perror("open_port: Unable to open /dev/ttyS0 - ");
else
{
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &options);
}
/*
Если не вставить эту стороку в ридере - вылет из цикла
while по break - С чем это связано???????
*/
fcntl(fd, F_SETFL, 0);
return (fd);
}
Ну а запись в порт - тоже самое, только меняю порт и передаю тестовую стороку:
...
int n = write(fd,"STROKA\n",6);
...
Теперь запускаю ридера во одном командере, а райтера - в другом...
Ну результат, как и писал - чтение зависло в ожидании, если кольцо.
Так же и с готовым примером из источника выше...
А если заглушка на один порт - нормально считывается только по-байтно...
Я никогда не пытался писать и читать один и тот же порт и не задумывался
о том, как это возможно. Данные, которые пишутся в порт, из него только
уходят, они не поступают в него, в его буфер приёма.
Если же записанные в него данные не считываются приёминком на другом
конце кабеля, то я не помню, что будет, в лучшем случае они просто будут
постепенно перезаписываться
Если ваша заглушка - это перемыкание TxD-RxD, то, м.б., и будет работать
запись/чтение на одном порту.
Если на вашем компьютере два COM-порта, то их надо соединить модемным
кабелем, в одной программе писать в 1-й порт, а в другой из 2-го читать.
В одной программе открыть 1-й порт только для записи, в другой открыть 2-й
только для чтения, но можно и оба для чтения/записи.
Структуру termios хорошо бы объявлять в главной программе, чтобы она
существовала всё время её работы, хотя это не обязательно. Если уж
параметры порта устанавливаются через неё, то её тоже хорошо бы обнулять
перед установкой параметров.
Мне непонятно, почему порт открывается с флаом O_NONBLOCK, вроде бы надо
без него.
Откуда вы взяли
text
fcntl(fd,S_SETFL,0);
и что такое в ней 0? 0 - это значение флага O_RDONLY.
У меня же программа работает без вызова fcntl.
Моя программа тоже читает посимвольно. В вашей write передаётся 6 символов,
а в строке их 7.
Что касается зависаний и ожидания прихода символа, то посмотрите описание
параметрво termios c_cc[VTIME] и c_cc[VMIN].