Java: чтение последовательного порта (скорость 921600 бод)

Я разрабатываю программное обеспечение Java, которое должно иметь возможность считывать некоторые данные, отправленные устройством через последовательный COM-порт, для меня очень важна скорость связи, поэтому скорость передачи данных установлена ​​​​на 921600. Вначале все работает нормально (и поэтому он читает правильные данные, которые устройство отправляет через последовательный порт), но через некоторое время программное обеспечение начинает считывать неправильные данные. Похоже, что программа слишком медленная и на самом деле теряет часть данных, когда они поступают во входной буфер (возможно, когда входной буфер полностью заполняется в первый раз). Чтобы ускорить операцию чтения, я в настоящее время использую подход к чтению, при котором программное обеспечение обрабатывает как можно больше байтов за одно чтение. Я также пытался увеличить размер входного буфера (используя метод serialPort.setInputBufferSize(byte), но это не решило мою проблему). Итак, кто-нибудь когда-либо выполнял быструю последовательную связь с java? Я что-то упускаю? Почему какое-то время все работает нормально, а потом перестает нормально работать?

Это мой код для части чтения (даже управляемой), пожалуйста, пропустите часть преобразования данных, это просто потому, что все данные на самом деле состоят из 2 байтов, и поэтому мне также нужно составить их, прежде чем записывать их в файл txt.

/**
 *
 * @param evt
 */
@Override
public void serialEvent(SerialPortEvent evt) {

     switch(evt.getEventType()) {

        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
            System.out.println("THE OUTPUT BUFFER IS EMPTY");
            break;

        case SerialPortEvent.DATA_AVAILABLE:
            try {     

                while(SerialPortEvent.DATA_AVAILABLE == 1) {


                   num_bytes = input.available();
                   array = new byte[num_bytes];

                   bytes_read = input.read(array, 0, num_bytes);

                   dato = new short[bytes_read];
                   datoc = new int[bytes_read/2];
                   datos = new String[bytes_read/2];


                   for(j=0;j<bytes_read;j++){                           
                       dato[j] = (short) (((byte) array[j]) & 0xff);
                   }

                   k = 0;
                   for(j=0;j<(bytes_read/2);j++){

                       datoc[j] = dato[k];
                       datoc[j] = (datoc[j]<<8) + dato[k+1];
                       datoc[j] = datoc[j] & 0xffffffff;  
                       k = k + 2;
                   }

                   for(j=0;j<(bytes_read/2);j++){

                       System.out.println(datoc[j]);
                       datos[j] = Integer.toString(datoc[j]);
                       output1.write(datos[j] + " ");
                   }

               }
            } catch(IOException ex) {
              logText = "Failed to read data. (" + ex.toString() + ")";
              System.out.println(logText);
            }
            break;

    }

person STiLLeN    schedule 04.10.2012    source источник
comment
Сколько времени? Если вы можете обрабатывать данные в течение часа, прежде чем произойдет сбой, я предполагаю, что у вас может быть утечка памяти или сбой, когда Java выполняет сборку мусора (просто предполагаю, что Java сделает это). Кроме того, серийное событие запускается снова до того, как вы закончите обработку последнего события?   -  person Jeff    schedule 05.10.2012


Ответы (2)


Похоже, ваша программа недостаточно быстро обслуживает входящие данные; это будет работать в течение определенного периода времени, потому что входные данные попадают в буфер, и когда вы очищаете буфер, появляется больше места для большего количества входных данных. Но если данные поступают быстрее, чем вы их обрабатываете в целом, в конечном итоге ваш буфер переполняется, а данные все равно поступают, и им некуда деваться. Для последовательной связи было характерно, что такие данные сбрасывались на (виртуальный) этаж.

Также обычно устанавливается статус, указывающий на «переполнение буфера». Первое, что я хотел бы проверить, это то, доступен ли вам этот статус в любой библиотеке, которую вы используете для чтения последовательных данных, и посмотреть, будет ли он установлен/когда он будет установлен. Это подтвердит, что вышеописанное происходит.

Еще одна вещь, которую следует проверить, если это разумно в вашей среде, — это возможность XON/XOFF. Это была/есть функция некоторых последовательных коммуникаций, позволяющая получателю указать отправителю, что его буфер почти заполнен, и прекратить отправку (XOFF), пока не будет сообщено, что все в порядке, чтобы начать снова (XON). Не все аппаратное и программное обеспечение поддерживает эту функцию.

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

person arcy    schedule 04.10.2012
comment
XON/XOFF — это программное управление потоком, поэтому оно не связано с аппаратной поддержкой. Очень редко используется XON/XOFF. Гораздо более распространенным решением для управления потоком данных является аппаратная RTS/CTS. Подавляющее большинство оборудования поддерживает RTS/CTS. - person TJD; 04.10.2012
comment
Для поддержки XON/XOFF должен быть полный дуплекс; возможно, я слишком далеко ухожу в историю — я сомневаюсь, что существует много полудуплексных систем, — но действительно нужна аппаратная поддержка программного обеспечения для отправки сигналов. Вы правы в том, что это программное обеспечение, и я забыл упомянуть RTS / CTS - OP должен взглянуть на это, и я рад, что вы упомянули об этом. - person arcy; 04.10.2012

Что-то, что замедляло последовательную связь, было использование System.out.println(). Без этого получение данных в конечном итоге наладилось

person STiLLeN    schedule 14.07.2013