pySerial замораживает после прочтения 3 раза - PullRequest
0 голосов
/ 19 ноября 2010

Мы программируем рис, и мы диагностировали, что если мы отправим данные на последовательный порт, когда он пытается отправить нам данные, программа заблокируется (и наш код python, и гипертерминал потерпят крах при тестировании).Он работал в гипертерминале и вводил его медленно (> 0,5 секунды между ударами) и зависал при ударе по клавиатуре.Поэтому мы ввели time.sleep, который длиннее 0,5 секунд, но он все еще не работает.

Вот наш тестовый код.

import serial
import time

ser = serial.Serial("COM1")
ser.baudrate=2400

while 1:
    for i in range(23):
        ser.write(0x41)       
        time.sleep(.5)
        print("ok")

    rec = ser.read()
    rec2 = ser.read()
    rec3 = ser.read()
    print(rec)
    print(rec2)
    print(rec3)

    for i in range(23):
        data = ser.read()
        print(data)
        print("ok")
    time.sleep(5)

наша функция получения данных.Раньше мы посылали «ок» каждый раз, когда получал символ (как мы знаем, что он зависает после 3 итераций).Мы вывели его за пределы цикла, чтобы увидеть, не является ли это причиной проблемы, но это не так.Этот код вообще не отправляет "ok".

unsigned char receiveData(unsigned char *rxData, int length){
  // 1. Flag bit, RCIF, will be set when reception is complete and an interrupt will be generated if enable bit, RCIE, was set.
 char send[3] = "ok";

 int index = 0;

 if(rxData==(void*)0 || rxInitialized==FALSE) return FAILURE;
 while(index<length){
  while(PIR1bits.RCIF==0);       
  rxData[index]= RCREG;
  Delay1KTCYx(5);
  index++;
 }
    configureTransmission();
    sendData(send,3);

  // 2. Read the RCSTA register to get the 9th bit (if enabled) and   determine if any error occurred during reception.
  // 3. Read the 8-bit received data by reading the RCREG register.
  // 4. If any error occurred, clear the error by clearing enable bit   CREN.
 return SUCCESS;
}

Ответы [ 2 ]

2 голосов
/ 19 ноября 2010

(Этот ответ предполагает, что вы используете PIC16, предложенный именами определенных регистров.)

Короче говоря, это похоже на переполнение буфера в сочетании с ошибкой в ​​этом цикле в receiveData. Тот факт, что он замораживается после отправки трех символов подряд, может быть объяснен p117 руководства:

Возможно, что два байта данных будут получены и переданы в RCREG FIFO, а третий байт начнет переключаться в регистр RSR

Это объясняет магическое число три.

Пошагово перебирая код PIC, рассмотрите следующий сценарий (только пример). Первый раз:

// One character already in RCREG - RCIF set
while(PIR1bits.RCIF==0);
// Reads ONE character - RCIF clear
rxData[index]= RCREG;
// While waiting here, two more characters are received - RCIF set
Delay1KTCYx(5);
index++;

Второй раз вокруг:

// RCIF set from before
while(PIR1bits.RCIF==0);
// Reads ONE character - RCIF STILL set, ONE character remains in UART FIFO!
rxData[index]= RCREG;
// While waiting here, three more characters are received
// RCIF set, RCREG fills up and the third character is discarded!
Delay1KTCYx(5);
index++;

Теперь остальная часть цикла будет продолжать читать из RCREG до index == length, но, поскольку некоторые символы были отброшены, когда UART FIFO был заполнен, вы никогда не попадете туда и, похоже, завис!

Что еще более вероятно, так это то, что вы получаете символы еще до того, как дойдете до этой функции, поэтому UART FIFO заполняется еще до того, как вы туда доберетесь.

Есть несколько способов обойти это.

  1. Сделайте это в прерывании, чтобы немного быстрее переместить входящие символы в буфер.
  2. Используйте цикл для чтения из RCREG: while(RCIF) rxData[index]= RCREG;, это гарантирует, что вы очистите буфер при чтении из буфера UART, но это не остановит переполнения вне этой функции или во время этой задержки.
  3. Проверьте флаг OERR - если он установлен, предположите, что случилось что-то плохое, и начните сначала.
  4. Имеет символ остановки или начальный символ (например, конец строки, пунктуация и т. Д.), Который сообщает вам, когда действительная команда запускается или останавливается. Если у вас есть два начальных символа без символа остановки или какой-либо другой запутанной комбинации, предположите, что вы в плохом состоянии, и начните все сначала.

Несколько дополнительных советов: вы можете просто сойти с ума, пытаясь учесть и компенсировать каждый пропущенный символ или проблему, подобную этой, в вашем коде PIC, но в конечном итоге это просто еще одна ошибка связи. Приоритеты в коде PIC должны быть следующими: быстрое восстановление после ошибок и отсутствие блокировки. Обнаружение ошибок и правильное восстановление должны обрабатываться клиентским кодом, где это намного, намного проще.

1 голос
/ 19 ноября 2010

Используется ли для связи от PIC линия RTS / CTS последовательного порта?Возможно, PIC ожидает какой-то контроль потока, и вы слишком быстро отправляете на него данные без какого-либо контроля потока.Ознакомьтесь с ограничениями PIC и, если необходимо, откройте порт с включенным flow control .

...