Як Arduino обробляє переповнення послідовного буфера?


27

Як Arduino обробляє переповнення послідовного буфера? Це викидає найновіші вхідні дані чи найдавніші? Скільки байтів може містити буфер?

serial 

Відповіді:


13

Для апаратних послідовних портів ви можете побачити в HardwareSerial.cpp, що розмір буфера змінюється в залежності від обсягу оперативної пам’яті, доступного для конкретного AVR:

#if (RAMEND < 1000)
    #define SERIAL_BUFFER_SIZE 16
#else
    #define SERIAL_BUFFER_SIZE 64
#endif

Для послідовного порту програмного забезпечення в SoftwareSerial.h розмір буфера приймача _SS_MAX_RX_BUFFвизначається як 64 байти. В обох випадках він припиняє спробу вставити отримані дані у чергу, коли вона заповнена, тож ви можете отримати суміш зі старими та новими даними залежно від того, як ви отримуєте дані з черги.

В ідеалі було б найкраще забезпечити, щоб буфер завжди спорожнявся оперативно, щоб уникнути заповнення буфера. Можливо, подивіться на таймери та реалізуйте просту машину стану, якщо ваша проблема пов’язана з іншим кодом, що блокує основний цикл.


У мене складається враження, що якщо я передаю дані Arduino і не матиму активного "знімача" даних на стороні Arduino, то, якщо в буфер надійде більше даних, ніж може вміститися, вони будуть відкинуті. Ви можете це підтвердити? Я наївно припускав, що передавач блокується, поки не стане доступним місця для зберігання даних.
Колбан

Я просто переглянув увесь код (під / usr / share / arduino / hardware / arduino / core / arduino / HardwareSer‌ ial.cpp) і можу підтвердити те, що ви тут написали. Єдине, що я хочу додати, це те, що оскільки SRAM становить 2K (RAMEND> 1000), тоді, якщо оператор завжди буде використовувати 64, а не 16 для Nano або Uno. Тож якщо ви хочете розширити розмір буфера кільця, це було б місцем його змінити
SDsolar

5

Отримання

З джерела HardwareSerial видно, що якщо вхідний байт знаходить буфер кільця повним, він відкидається:

inline void store_char(unsigned char c, ring_buffer *buffer)
{
  int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != buffer->tail) {
    buffer->buffer[buffer->head] = c;
    buffer->head = i;
  }
}

У мене складається враження, що якщо я передаю дані в Arduino і не матиму активного "знімача" даних на стороні Arduino, то якщо в буфер надійде більше даних, ніж може вміститися, вони будуть відкинуті. Ви можете це підтвердити?

Так, це буде відкинуто. Немає програмного або апаратного контролю потоку, якщо ви не реалізуєте свій власний.

Однак, використовуючи 64-байтовий буфер і отримуючи дані при (скажімо, 9600 бодах), ви отримуєте один байт кожні 1,04 мс, а значить, для заповнення буфера потрібно 66,6 мс. На процесорі 16 МГц ви повинні мати можливість перевіряти буфер досить часто, щоб він не заповнювався. Все, що вам потрібно зробити - це перемістити дані з буфера HardwareSerial до свого власного, якщо ви не хочете обробляти їх зараз.

З #if (RAMEND < 1000)перевірки видно, що процесори з 1000+ байтами оперативної пам’яті отримують 64-байтовий буфер, тим менше ОЗУ отримає 16-байтовий буфер.


Відправлення

Дані, які ви записуєте, розміщуються в буфері одного розміру (16 або 64 байти). У разі надсилання, якщо буфер заповнює код "блокує", чекаючи переривання, щоб відправити наступний байт з послідовного порту.

Якщо переривання буде вимкнено, цього ніколи не відбудеться, значить, ви не робите послідовних роздруківків всередині програми переривання служби.


Я вважаю, що ви вимкнетесь на порядок: при 9600 бодах ви отримуєте байт кожні ~ 0,1 мс, тому для заповнення буфера потрібно лише 6,6 мс.
Ерік Данд

1
При 9600 бодах ви отримуєте 9600 біт за секунду. Оскільки кожен байт становить 10 біт (8 даних + 1 початковий біт + 1 стоп-біт), то ви отримуєте 960 байт в секунду. 1/960 = 0.001042 s- це один байт кожні 1,04 мс.
Нік Гаммон

Ах, звичайно, біти не байти! Дякуємо за виправлення.
Ерік Данд

Тож Нік, будь ласка, відповідь на це мені: Якщо у мене Pi, який працює під управлінням Python, сидить на сервері. деліметрів, потім, використовуючи затримку (120000), тому партії приходять кожні дві хвилини, внутрішньості Python, ймовірно, негайно читаються в кожному символі, поки він не зустріне новий рядок, і в цей момент він випускає весь рядок як зворотне значення. Тож мені не потрібно турбуватися про розмір буфера Arduino, навіть якщо я надсилаю загально 80 символів, так? Це було б гарне припущення?
SDsolar

Так, розмір буфера для відправки не матиме значення в цьому сценарії. Невеликий буфер уповільнить надсилання (трохи), але якщо ви все-таки зробите тривалу затримку, вам не буде байдуже.
Нік Гаммон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.