Как получить больше 64 байт на Arduino?

Я получаю около 90 байтов через последовательный порт. Но у Arduino последовательный буфер всего на 64 байта. Из-за этого ограничения я не могу принимать больше байтов.

char c;

void read_response() {
  while(Serial.available > 0) {
    c=Serial.read();
    Serial.print(c,HEX);
    Serial.print(",");
  }
}

Я попытался использовать указанную выше функцию для чтения последовательных данных, но она способна читать только 64 байта.

Я попробовал еще один подход:

char rxdata[]={};

void read_response() {
  while(Serial.available > 0) {
    int len= Serial.readBytes(rxdata, 90)
  }
}

При таком подходе я тоже получал только 64 байта.

Serial.flush() также не работает, так как ожидает завершения текущей передачи. И у меня нет управления передачей. Передатчик непрерывно отправляет 90 байт.

Пожалуйста, дайте мне несколько предложений.

, 👍2


3 ответа


1

Вам потребуется скорректировать концепцию последовательной связи, чтобы не полагаться на передачу всех 90 байт данных в последовательный входной буфер перед их считыванием в ОЗУ.

Вместо этого вам нужно постоянно очищать аппаратный буфер в ОЗУ так часто, как вы проходите через loop(), и избегать использования delay(), которое не позволит вашей программе очистить буфер.

Чтобы узнать, когда вы достигли конца передачи, вам следует либо убедиться, что входящий последовательный поток имеет маркер в конце (например, символ '\n'), либо всегда имеет фиксированную длину (например, всегда ровно 90 байт).

В качестве примера, вот программа, которая ищет '\n' как маркер конца данных:

#DEFINE MAX_INPUT 90

char inputBuffer[MAX_INPUT+1]; // Обрабатывает до 90 байт в строке в стиле C с завершением нулевым символом.

void setup() 
{
  Serial.begin(115200); // инициализация
  inputBuffer[0] = '\0'; //Инициализируем строку как пустую.
  Serial.println("Begin:");
}

void loop() {

  if (Serial.available()>0)
  {
    char input = Serial.read();
    static int s_len; // статические переменные по умолчанию равны 0
    if (s_len>=MAX_INPUT) {
      // Уже получено максимальное количество символов
      // Игнорировать все новые входные данные до завершения строки
    } else if (input != '\n' && input != '\r') {
      inputBuffer[s_len++] = input;
    } else {
      // Получили символ LF или CR

      // ВСТАВЬТЕ ВАШ КОД ЗДЕСЬ ДЛЯ ОБРАБОТКИ ПОЛУЧЕННЫХ ДАННЫХ //
      // ВЫ МОЖЕТЕ КОПИРОВАТЬ В НОВУЮ ПЕРЕМЕННУЮ С ПОМОЩЬЮ strncpy() ИЛИ //
      // УСТАНОВИТЬ ФЛАГ, ЧТОБЫ СКАЗАТЬ О НАЧАЛЕ ДРУГОЙ ЗАДАЧИ //
      Serial.print("RECEIVED MSG: ");
      Serial.println(inputBuffer);

      memset(inputBuffer, 0, sizeof(inputBuffer));
      s_len = 0;             // Сбросьте входной буфер здесь, если вы
                             // уже скопировали данные.
                             // Если вы не сбросите здесь, то
                             // вы не можете начать получать больше
                             // данные последовательного порта. Это ваши
                             // «программный» последовательный буфер, контраст
                             // с аппаратным последовательным буфером.
    }
  }
}
,

0

Думаю, ваш второй подход с использованием readBytes() был верным. Если вы отправляете от 1 до 90 символов через последовательный монитор, readBytes(), похоже, продолжает читать аппаратный буфер и записывать данные в «ваш» буфер до тех пор, пока аппаратный буфер не опустеет, не будет достигнуто ограничение в 90 символов или не истечёт тайм-аут по умолчанию (1000 мс).

const byte BufferSize = 90;
char Buffer[BufferSize + 1];

void setup(){
  Serial.begin(9600);
}

void loop(){

  if(Serial.available() > 0){

    while(Serial.available() > 0){
      // "readBytes" завершается, если определенная длина была прочитана, или
      // истекает время ожидания. Он заполняет «Буфер» данными от 1 до 90 байт. Чтобы изменить
      // использование тайм-аута: Serial.setTimeout() в setup(). Тайм-аут по умолчанию — 1000 мс.
      Serial.readBytes(Buffer, BufferSize);
    }

    // Распечатать содержимое «вашего» 90-символьного буфера.
    Serial.print(Buffer);
    Serial.println("");

    // Вы можете использовать Serial.peek() для проверки, больше ли 90 символов
    // были в последовательном буфере и «ваш» буфер имеет обрезанные данные.
    // Этого никогда не должно произойти, потому что вы знаете максимальную длину
    // входящие данные и ваш входной буфер имеет достаточный размер.
    if(Serial.peek() != -1){
      Serial.print("90 byte Buffer Overflowed. ");
    }

    // Очищаем содержимое «вашего» буфера.
    memset(Buffer, 0, sizeof(Buffer));
  }
}
,

3

Но у Arduino последовательный буфер всего на 64 байта. Из-за этого ограничения я не могу принимать больше байтов.

Это утверждение — чушь. Буфер, конечно, есть, но он позволяет принимать до 64 байтов (помещаемых туда процедурой обработки прерываний последовательного порта), прежде чем вы извлечёте хотя бы один.

Всё, что вам нужно сделать, — это быстро извлечь данные (то есть выполнить Serial.read()) достаточно быстро, чтобы удалить данные из буфера и сохранить их в памяти.

Вам необходимо опубликовать минимальный, полный и проверяемый пример (MCVE), демонстрирующий вашу проблему. Например, вы используете delay(1000) перед попыткой чтения последовательных данных?

См. мою публикацию о получении последовательных данных без блокировки, а также асинхронном (последовательном) периферийном интерфейсе — для Arduino.

,