Как Arduino справляется с переполнением последовательного буфера? Он выбрасывает новейшие входящие данные или самые старые? Сколько байтов может содержать буфер?
Как Arduino справляется с переполнением последовательного буфера? Он выбрасывает новейшие входящие данные или самые старые? Сколько байтов может содержать буфер?
Ответы:
Для аппаратных последовательных портов вы можете увидеть в 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 байта. В обоих случаях прекращается попытка вставить полученные данные в очередь, когда она заполнена, поэтому вы можете получить смесь старых и новых данных в зависимости от того, как вы извлекаете данные из очереди.
В идеале было бы лучше убедиться, что буфер всегда очищается быстро, чтобы избежать заполнения буфера. Может быть, посмотрите на таймеры и реализацию простого конечного автомата, если ваша проблема связана с другим кодом, блокирующим основной цикл.
Вы можете видеть из источника 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 байта). В случае отправки, если буфер заполняет код, «блокирует» ожидание прерывания для отправки следующего байта через последовательный порт.
Если прерывания отключены, этого никогда не произойдет, поэтому вы не выполняете последовательную печать внутри подпрограммы обработки прерываний.
1/960 = 0.001042 s
- это один байт каждые 1,04 мс.