Làm thế nào để Arduino xử lý tràn bộ đệm nối tiếp?


27

Làm thế nào để Arduino xử lý tràn bộ đệm nối tiếp? Liệu nó có vứt bỏ dữ liệu mới nhất hoặc cũ nhất? Bộ đệm có thể chứa bao nhiêu byte?

serial 

Câu trả lời:


13

Đối với các cổng nối tiếp phần cứng, bạn có thể thấy trong Phần cứngSerial.cpp rằng kích thước bộ đệm thay đổi tùy thuộc vào dung lượng RAM có sẵn trên AVR cụ thể:

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

Đối với cổng nối tiếp phần mềm trong SoftwareSerial.h kích thước bộ đệm bộ thu _SS_MAX_RX_BUFFđược xác định là 64 byte. Trong cả hai trường hợp, nó dừng cố gắng chèn dữ liệu đã nhận vào hàng đợi khi nó đầy, do đó bạn có thể nhận được kết hợp với dữ liệu cũ và mới tùy thuộc vào cách bạn truy xuất dữ liệu từ hàng đợi.

Lý tưởng nhất là tốt nhất để đảm bảo bộ đệm luôn được dọn sạch một cách kịp thời để tránh làm đầy bộ đệm. Có thể xem bộ tính giờ và thực hiện một máy trạng thái đơn giản nếu vấn đề của bạn liên quan đến mã khác chặn vòng lặp chính.


Tôi có ấn tượng rằng nếu tôi truyền dữ liệu tới Arduino và không có "trình kéo" dữ liệu đang hoạt động ở phía Arduino thì nếu có nhiều dữ liệu đến hơn có thể nằm gọn trong bộ đệm, nó sẽ bị loại bỏ. Bạn có thể xác nhận điều đó? Tôi đã ngây thơ cho rằng máy phát sẽ chặn cho đến khi không gian trống để chứa dữ liệu có sẵn.
Kolban

Tôi chỉ xem qua tất cả các mã đó (dưới / usr / share / arduino / phần cứng / arduino / core / arduino / HardwareSer‌ ial.cpp) và có thể xác nhận những gì bạn đã viết ở đây. Điều duy nhất tôi muốn nói thêm là vì SRAM là 2K (RAMEND> 1000) nên câu lệnh if sẽ luôn sử dụng 64 thay vì 16 trên Nano hoặc Uno. Vì vậy, nếu người ta muốn mở rộng kích thước của bộ đệm vòng sẽ là nơi để thay đổi nó
SDsolar

5

Nhận

Bạn có thể thấy từ nguồn của Phần cứngSerial rằng nếu một byte đến tìm thấy bộ đệm vòng đầy thì nó sẽ bị loại bỏ:

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

Tôi có ấn tượng rằng nếu tôi truyền dữ liệu tới Arduino và không có "trình kéo" dữ liệu đang hoạt động ở phía Arduino thì nếu có nhiều dữ liệu đến hơn có thể nằm gọn trong bộ đệm, nó sẽ bị loại bỏ. Bạn có thể xác nhận điều đó?

Có nó sẽ bị loại bỏ. Không có kiểm soát luồng phần mềm hoặc phần cứng, trừ khi bạn tự thực hiện.

Tuy nhiên, với bộ đệm 64 byte và nhận dữ liệu ở (giả sử) 9600 baud, bạn nhận được một byte mỗi 1,04 ms, và do đó, phải mất 66,6 ms để lấp đầy bộ đệm. Trên bộ xử lý 16 MHz, bạn sẽ có thể kiểm tra bộ đệm đủ thường xuyên để nó không lấp đầy. Tất cả những gì bạn thực sự phải làm là chuyển dữ liệu từ bộ đệm Phần cứng sang của riêng bạn, nếu bạn không muốn xử lý nó ngay bây giờ.

Bạn có thể thấy từ #if (RAMEND < 1000)kiểm tra rằng bộ xử lý có hơn 1000 byte RAM có bộ đệm 64 byte hay không, những bộ xử lý sẽ ít RAM hơn có bộ đệm 16 byte.


Gửi

Dữ liệu bạn viết được đặt trong bộ đệm có cùng kích thước (16 hoặc 64 byte). Trong trường hợp gửi nếu bộ đệm lấp đầy mã "khối" đang chờ một ngắt để gửi byte tiếp theo ra khỏi cổng nối tiếp.

Nếu các ngắt bị tắt thì điều này sẽ không bao giờ xảy ra, do đó bạn không thực hiện in nối tiếp bên trong Định tuyến dịch vụ ngắt.


Tôi tin rằng bạn đang giảm một mức độ lớn: ở 9600 baud, bạn nhận được một byte mỗi ~ 0,1 ms, do đó, chỉ mất 6,6 ms để lấp đầy bộ đệm.
Eric Dand

1
Với tốc độ 9600 baud, bạn nhận được 9600 bit mỗi giây. Vì mỗi byte là 10 bit (8 dữ liệu + 1 bit start + 1 bit stop) nên bạn nhận được 960 byte mỗi giây. 1/960 = 0.001042 s- đó là một byte mỗi 1,04 ms.
Nick Gammon

Tất nhiên, bit không byte! Cảm ơn vì sự đúng đắn của bạn.
Eric Dand

Vì vậy, Nick, vui lòng trả lời câu hỏi này cho tôi: Nếu tôi có một Pi đang chạy Python ở ser.readline () đang chờ nhập dữ liệu dưới dạng bộ ghi dữ liệu và nó được đưa qua serial bởi Arduino lấy các bài đọc sau đó gửi chúng dưới dạng một lô với tab phân tách, sau đó sử dụng độ trễ (120000) để các lô xuất hiện cứ sau hai phút, các bộ phận Python có thể ngay lập tức đọc trong mỗi ký tự cho đến khi gặp dòng mới, tại đó nó giải phóng toàn bộ dòng dưới dạng giá trị trả về. Vì vậy, tôi không phải lo lắng về kích thước bộ đệm Arduino ngay cả khi tôi đang gửi tổng cộng 80 ký tự, eh? Đó sẽ là một giả định tốt?
SDsolar

Có, kích thước bộ đệm gửi sẽ không thành vấn đề trong kịch bản này. Một bộ đệm nhỏ sẽ làm chậm việc gửi (một chút) nhưng nếu bạn đang trì hoãn lâu thì bạn sẽ không quan tâm.
Nick Gammon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.