Russian Qt Forum

Qt => Общие вопросы => Тема начата: titan83 от Август 25, 2014, 11:18



Название: QtSerialPort и rs485 без автоматического RTS
Отправлено: titan83 от Август 25, 2014, 11:18
Всем привет.
Знаю, что такая тема уже поднималась, но есть у меня есть специфика(
В общем, в моем устройстве на ARM9 rs485 реализован на чипах ADMxxx без автоопределения RTS, а в качестве RTS выступает просто линия GPIO, которую надо прижать к земле перед передачей и отпустить после, соответственно, setRequestToSend для меня неактуально.
Выставить RTS перед посылкой нетрудно - трудно ее вовремя снять. Я пробовал вариант с сигналом bytesWritten(qint64), но он поступает когда данные будут переданы в системную функцию write(), и при этом число переданных байт будет всегда равно отправляемому. В результате из 10 байт я успеваю послать 4.
В качестве второго варианта я хотел использовать функцию waitForBytesWritten(), но она, видимо, не переопределена в QSerialPort и всегда возвращает false.
И похоже, что мне придется активно читать форумы по переделке драйверов uart, чтобы выставлять в какой-нибудь файл sysfs "0" в момент окончания передачи.
Может все-таки возможно решить эту задачу высокоуровневыми средствами?
Спасибо.


Название: Re: QtSerialPort и rs485 без автоматического RTS
Отправлено: Bepec от Август 25, 2014, 13:23
Да, руки надо отрывать тем, кто их разрабатывает без авто RTS :)

Windows система НЕ реального времени. Поэтому точно и быстро реализовать "прижимание" линии не получится. Всегда будет погрешность ~ 50 мс, что очень плохо скажется на скорости и частоте передач.

update: ммм.. ты на встроенной системе программу пишешь? Или на какой?


Название: Re: QtSerialPort и rs485 без автоматического RTS
Отправлено: kuzulis от Август 25, 2014, 22:31
Цитировать
Я пробовал вариант с сигналом bytesWritten(qint64), но он поступает когда данные будут переданы в системную функцию write(), и при этом число переданных байт будет всегда равно отправляемому.

Не. Планировалось так, чтобы сигнал bytesWritten() излучался именно тогда, когда данные "были отправлены" в устройство. Т.е. когда сработала аналогия select() && fdwrite (QSocketNotifier с типом Write), т.е. когда передающий буфер драйвера вновь готов к заполнению новыми данными для передачи. Да, это понятно, что реально это не означает, что если передающий буфер опустел то данные переданы в линию. В реальности все сложнее.. Но тем не менее "косвенно" можно примерно на это положиться.

Еще ты можешь попробовать использовать QSerialPort::handle() для вызова сисколла ioctl() с флагом FIONWRITE чтобы посмотреть сколько там данных в буфере драйвера еще готовы к отправке но еще не отправились и как-то поллить это. Но этот FIONWRITE поддерживается не всеми драйверами и ядрами (вроде как), да и вообще не факт что заработает.

UPD: Или можешь также попробовать использовать этот самый QSerialPort::handle() и через ioctl() установить порт в блокирующий режим (т.к. по-умолчанию он открывается в неблокирующем). Тогда уж точно функция write() будет ждать пока данные не отправятся. Но в этом случае тебе придется перенести QSerialPort в отдельный поток, т.к. сам понимаешь - блокирующий ввод/вывод - это блокирующий ввод/вывод.  :)

Цитировать
В качестве второго варианта я хотел использовать функцию waitForBytesWritten(), но она, видимо, не переопределена в QSerialPort и всегда возвращает false.

Да не, вроде она должна работать. Если не работает - значит какой-то касяк в QSerialPort .


Название: Re: QtSerialPort и rs485 без автоматического RTS
Отправлено: titan83 от Август 27, 2014, 08:15
Да, руки надо отрывать тем, кто их разрабатывает без авто RTS :)
Так не получается найти микросхему, чтобы и автоRTS и оптроны на выходе(( У ADM - оптроны, у MAX - автоRTS((, а чтобы и то, и другое - не получается пока найти. А ставить еще и оптроны - так места на плате не хватит однозначно.
update: ммм.. ты на встроенной системе программу пишешь? Или на какой?
У меня на ARM9 крутиться линукс 3.2.18


Название: Re: QtSerialPort и rs485 без автоматического RTS
Отправлено: titan83 от Август 27, 2014, 08:17
Спасибо, буду пробовать, но чувствую, что это все полумеры и придется-таки падать на уровень ядра и задействовать один из свободных таймеров( а так не хочется)