In che modo Arduino gestisce l'overflow del buffer seriale?


27

In che modo Arduino gestisce l'overflow del buffer seriale? Elimina i dati in entrata più recenti o i più vecchi? Quanti byte può contenere il buffer?

serial 

Risposte:


13

Per le porte seriali hardware è possibile vedere in HardwareSerial.cpp che la dimensione del buffer varia in base alla quantità di RAM disponibile sul particolare AVR:

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

Per una porta seriale del software in SoftwareSerial.h, la dimensione del buffer del ricevitore _SS_MAX_RX_BUFFè definita come 64 byte. In entrambi i casi smette di tentare di inserire i dati ricevuti nella coda quando è pieno, quindi è possibile ottenere un mix di dati vecchi e nuovi a seconda di come si stanno recuperando i dati dalla coda.

Idealmente, sarebbe meglio assicurarsi che il buffer venga sempre svuotato in modo rapido per evitare il riempimento del buffer. Forse dai un'occhiata ai timer e all'implementazione di una semplice macchina a stati se il tuo problema è legato ad altri codici che bloccano il ciclo principale.


Ho l'impressione che se trasmetto dati ad Arduino e non ho un "puller" attivo di dati sul lato Arduino, se arrivano più dati di quanti ne possano stare nel buffer, verranno scartati. Puoi confermarlo? Avevo ingenuamente supposto che il trasmettitore si sarebbe bloccato fino a quando non fosse stato disponibile lo spazio disponibile per contenere i dati.
Kolban,

Ho appena guardato tutto quel codice (sotto / usr / share / arduino / hardware / arduino / core / arduino / HardwareSer‌ ial.cpp) e posso confermare ciò che hai scritto qui. L'unica cosa che aggiungerei è che, poiché SRAM è 2K (RAMEND> 1000), allora se l'istruzione if utilizzerà sempre 64 anziché 16 su un Nano o Uno. Quindi, se si desidera espandere la dimensione del buffer ad anello, sarebbe il posto giusto per cambiarlo
SDsolar,

5

ricevente

Dalla sorgente di HardwareSerial puoi vedere che se un byte in arrivo trova pieno il buffer dell'anello, viene scartato:

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;
  }
}

Ho l'impressione che se trasmetto dati ad Arduino e non ho un "puller" attivo di dati sul lato Arduino, se arrivano più dati di quanti ne possano stare nel buffer, verranno scartati. Puoi confermarlo?

Sì, verrà scartato. Non esiste alcun controllo del flusso di software o hardware, a meno che non si implementi il ​​proprio.

Tuttavia, con un buffer a 64 byte e ricevendo dati a (diciamo) 9600 baud, si ottiene un byte ogni 1,04 ms, e quindi ci vogliono 66,6 ms per riempire il buffer. Su un processore a 16 MHz dovresti essere in grado di controllare il buffer abbastanza spesso da non riempire. Tutto quello che devi fare è spostare i dati dal buffer HardwareSerial al tuo, se non vuoi elaborarli in questo momento.

Dal #if (RAMEND < 1000)controllo si può vedere che i processori con oltre 1000 byte di RAM ottengono il buffer da 64 byte, quelli che avranno meno RAM ottengono il buffer da 16 byte.


invio

I dati scritti vengono inseriti in un buffer della stessa dimensione (16 o 64 byte). Nel caso di invio se il buffer riempie il codice "blocchi" in attesa di un interrupt per inviare il byte successivo dalla porta seriale.

Se gli interrupt sono disattivati, ciò non accadrà mai, quindi non si eseguono stampe seriali all'interno di una routine di servizio di interrupt.


Credo che tu sia fuori di un ordine di grandezza: a 9600 baud, ottieni un byte ogni ~ 0,1 ms, quindi ci vogliono solo 6,6 ms per riempire il buffer.
Eric Dand,

1
A 9600 baud ottieni 9600 bit al secondo. Poiché ogni byte è 10 bit (8 dati + 1 bit di inizio + 1 bit di arresto), si ottengono 960 byte al secondo. 1/960 = 0.001042 s- ovvero un byte ogni 1,04 ms.
Nick Gammon

Ahh certo, bit non byte! Grazie per la correzione.
Eric Dand,

Quindi Nick, per favore, rispondi a me: se ho un Pi che esegue Python seduto su un ser.readline () in attesa di input come data logger, ed è alimentato via seriale da Arduino prendendo le letture quindi inviandole come batch con tab delimitatori, quindi utilizzando il ritardo (120000) in modo che i batch arrivino ogni due minuti, le interiora di Python probabilmente leggono immediatamente in ogni carattere fino a quando non incontra una nuova riga, a quel punto rilascia l'intera riga come valore di ritorno. Quindi non devo preoccuparmi delle dimensioni del buffer di Arduino anche se invio 80 caratteri in totale, eh? Sarebbe una buona supposizione?
SDsolar,

Sì, la dimensione del buffer di invio non avrà importanza in questo scenario. Un buffer di dimensioni ridotte rallenterebbe l'invio (leggermente), ma se si sta eseguendo un ritardo prolungato, non ci si preoccuperà.
Nick Gammon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.