Arduino seri tampon taşmasını nasıl işlemektedir?


27

Arduino seri tampon taşmasını nasıl işlemektedir? En yeni gelen mi yoksa en eski olanı mı atıyor? Arabellek kaç bayt tutabilir?

serial 

Yanıtlar:


13

Donanım seri bağlantı noktaları için, HardwareSerial.cpp’te , arabellek boyutunun belirli AVR’de bulunan RAM miktarına bağlı olarak değiştiğini görebilirsiniz :

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

SoftwareSerial.h içindeki bir yazılım seri portu için alıcı tampon büyüklüğü _SS_MAX_RX_BUFF64 bayt olarak tanımlanır. Her iki durumda da, doluyken alınan verileri kuyruğa girmeyi denemeyi durdurur, böylece sıradan verileri nasıl aldığınıza bağlı olarak eski ve yeni verilere bir karışım elde edebilirsiniz.

İdeal olarak, tampon dolumunu önlemek için tamponun her zaman hızlı bir şekilde boşaltılmasını sağlamak en iyisi olacaktır. Sorununuz ana döngüyü engelleyen diğer kodlarla ilgiliyse, zamanlayıcılara ve basit bir durum makinesine bakabilirsiniz.


Arduino'ya veri iletirsem ve Arduino tarafında aktif bir "çekiciye" sahip olmazsam, o zaman arabellekte sığabilecek olandan daha fazla veri gelirse atılacağı izlenimini edindim. Bunu onaylayabilir misin? Nadiren vericinin, verileri elde etmek için uygun alan bulunana kadar bloke edeceğini varsaymıştım.
Kolban

Ben sadece tüm bu kodlara baktım (/ usr / share / arduino / hardware / arduino / core / arduino / HardwareSer‌ ial.cpp altında) ve burada yazdıklarınızı onaylayabilirim. Ekleyeceğim tek şey, SRAM'ın 2K (RAMEND> 1000) olması, ardından ifadenin bir Nano veya Uno'da 16 yerine 64 kullanması gerektiğidir. Eğer biri halka tamponunun boyutunu genişletmek
isterse

5

kabul

HardwareSerial kaynağından, gelen bir baytın yüzük arabelleğini dolu bulduğunda, atıldığını görebilirsiniz:

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'ya veri ilettiğimde ve Arduino tarafında aktif bir "çekiciye" sahip olmadığımda, tamponun sığabileceğinden daha fazla veri geldiğinde, atılacağı izlenimini edindim. Bunu onaylayabilir misin?

Evet atılacak. Kendinizinkini uygulamadığınız sürece yazılım ya da donanım akış kontrolü yoktur.

Bununla birlikte, 64 baytlık bir tamponla ve (örneğin) 9600 baud'dan veri alarak, her 1.04 ms'de bir bayt alırsınız ve bu nedenle tamponu doldurmak 66.6 ms sürer. 16 MHz'lik bir işlemcide, arabellek doldurmayacak kadar sık ​​sık kontrol edebilmelisiniz. Yapmanız gereken tek şey, şu anda işlemek istemiyorsanız, verileri HardwareSerial arabelleğinden kendinize taşımak.

Sen görebilirsiniz #if (RAMEND < 1000)olanlar daha az RAM 16 bayt tampon alacak, RAM 1000+ byte ile işlemciler 64 baytlık tampon olsun o çek.


gönderme

Yazdığınız veriler aynı boyutta bir arabellekte (16 veya 64 bayt) yerleştirilir. Arabellek, "bloklar" kodunu doldurursa gönderilmesi durumunda, bir sonraki baytı seri porttan göndermek için bir ara verilmesini bekler.

Kesmeler asla olmayacak bu kapatılırsa, böylece do not bir kesme hizmet yordamı içine Seri baskılar yapmak.


Büyüklük sırasına göre inanıyorum: 9600 baud'da, her ~ 0,1 ms'de bir bayt alırsınız, bu nedenle tamponu doldurmak yalnızca 6,6 ms sürer.
Eric Dand

1
9600 baud'da saniyede 9600 bit alıyorsunuz . Her bir bayt 10 bit (8 veri + 1 başlangıç ​​biti + 1 durdurma biti) olduğundan, saniyede 960 bayt alırsınız. 1/960 = 0.001042 s- bu her 1.04 ms'de bir bayttır.
Nick Gammon

Ahh, tabii ki, bayt değil bit! Düzeltme için teşekkürler.
Eric Dand

Nick, lütfen bunu benim için cevaplayın: Eğer bir veri kaydedici olarak girişi bekleyen bir ser.readline'da () oturan bir Piton çalışan Pi varsa ve Arduino tarafından okumaları alarak bir toplu iş olarak göndererek Arduino tarafından seri olarak beslenir. Sınırlayıcılar, sonra gecikmeyi (120000) kullanarak gruplar her iki dakikada bir gelir, Python doğurucuları yeni bir çizgiyle karşılaşıncaya kadar hemen hemen her karakterde okumaya başlar, bu noktada tüm çizgiyi bir geri dönüş değeri olarak serbest bırakır. Yani toplam 80 karakter gönderiyor olsam da Arduino'nun tampon boyutu hakkında endişelenmeme gerek yok, ha? Bu iyi bir varsayım olur mu?
SDsolar

Evet, gönderen arabellek boyutu bu senaryoda önemli olmaz. Küçük bir arabellek göndermeyi yavaşlatır (biraz), ancak yine de uzun bir gecikme yapıyorsanız umursamazsınız.
Nick Gammon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.