Arduino는 직렬 버퍼 오버플로를 어떻게 처리합니까? 최신 수신 데이터 또는 가장 오래된 데이터를 버립니까? 버퍼는 몇 바이트를 유지할 수 있습니까?
Arduino는 직렬 버퍼 오버플로를 어떻게 처리합니까? 최신 수신 데이터 또는 가장 오래된 데이터를 버립니까? 버퍼는 몇 바이트를 유지할 수 있습니까?
답변:
하드웨어 직렬 포트의 경우 HardwareSerial.cpp 에서 버퍼 크기가 특정 AVR에서 사용 가능한 RAM의 양에 따라 달라지는 것을 확인할 수 있습니다 .
#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.04ms마다 1 바이트를 얻으므로 버퍼를 채우는 데 66.6ms가 걸립니다. 16MHz 프로세서에서는 채워지지 않을 정도로 버퍼를 자주 확인할 수 있어야합니다. 실제로 처리하지 않으려면 HardwareSerial 버퍼에서 자신의 데이터로 데이터를 이동하기 만하면됩니다.
#if (RAMEND < 1000)
1000 바이트 이상의 RAM을 가진 프로세서가 64 바이트 버퍼를 얻는다는 것을 확인할 수 있습니다. RAM은 16 바이트 버퍼를 덜받습니다.
작성하는 데이터는 동일한 크기의 버퍼 (16 또는 64 바이트)에 배치됩니다. 버퍼가 버퍼를 채우면 전송하는 경우 다음 바이트를 직렬 포트로 보내기 위해 인터럽트를 기다리는 "블록"코드를 채 웁니다.
인터럽트가 꺼져 있으면이 문제가 발생하지 않으므로 인터럽트 서비스 루틴 내부에서 직렬 인쇄 를 수행 하지 마십시오.
1/960 = 0.001042 s
-1.04ms마다 1 바이트입니다.