Как получить больше 64 байт на Arduino?
Я получаю около 90 байтов через последовательный порт. Но у Arduino последовательный буфер всего на 64 байта. Из-за этого ограничения я не могу принимать больше байтов.
char c;
void read_response() {
while(Serial.available > 0) {
c=Serial.read();
Serial.print(c,HEX);
Serial.print(",");
}
}
Я попытался использовать указанную выше функцию для чтения последовательных данных, но она способна читать только 64 байта.
Я попробовал еще один подход:
char rxdata[]={};
void read_response() {
while(Serial.available > 0) {
int len= Serial.readBytes(rxdata, 90)
}
}
При таком подходе я тоже получал только 64 байта.
Serial.flush() также не работает, так как ожидает завершения текущей передачи. И у меня нет управления передачей. Передатчик непрерывно отправляет 90 байт.
Пожалуйста, дайте мне несколько предложений.
@Pratik Katwate, 👍2
3 ответа
Вам потребуется скорректировать концепцию последовательной связи, чтобы не полагаться на передачу всех 90 байт данных в последовательный входной буфер перед их считыванием в ОЗУ.
Вместо этого вам нужно постоянно очищать аппаратный буфер в ОЗУ так часто, как вы проходите через loop(), и избегать использования delay(), которое не позволит вашей программе очистить буфер.
Чтобы узнать, когда вы достигли конца передачи, вам следует либо убедиться, что входящий последовательный поток имеет маркер в конце (например, символ '\n'), либо всегда имеет фиксированную длину (например, всегда ровно 90 байт).
В качестве примера, вот программа, которая ищет '\n' как маркер конца данных:
#DEFINE MAX_INPUT 90
char inputBuffer[MAX_INPUT+1]; // Обрабатывает до 90 байт в строке в стиле C с завершением нулевым символом.
void setup()
{
Serial.begin(115200); // инициализация
inputBuffer[0] = '\0'; //Инициализируем строку как пустую.
Serial.println("Begin:");
}
void loop() {
if (Serial.available()>0)
{
char input = Serial.read();
static int s_len; // статические переменные по умолчанию равны 0
if (s_len>=MAX_INPUT) {
// Уже получено максимальное количество символов
// Игнорировать все новые входные данные до завершения строки
} else if (input != '\n' && input != '\r') {
inputBuffer[s_len++] = input;
} else {
// Получили символ LF или CR
// ВСТАВЬТЕ ВАШ КОД ЗДЕСЬ ДЛЯ ОБРАБОТКИ ПОЛУЧЕННЫХ ДАННЫХ //
// ВЫ МОЖЕТЕ КОПИРОВАТЬ В НОВУЮ ПЕРЕМЕННУЮ С ПОМОЩЬЮ strncpy() ИЛИ //
// УСТАНОВИТЬ ФЛАГ, ЧТОБЫ СКАЗАТЬ О НАЧАЛЕ ДРУГОЙ ЗАДАЧИ //
Serial.print("RECEIVED MSG: ");
Serial.println(inputBuffer);
memset(inputBuffer, 0, sizeof(inputBuffer));
s_len = 0; // Сбросьте входной буфер здесь, если вы
// уже скопировали данные.
// Если вы не сбросите здесь, то
// вы не можете начать получать больше
// данные последовательного порта. Это ваши
// «программный» последовательный буфер, контраст
// с аппаратным последовательным буфером.
}
}
}
Думаю, ваш второй подход с использованием readBytes() был верным. Если вы отправляете от 1 до 90 символов через последовательный монитор, readBytes(), похоже, продолжает читать аппаратный буфер и записывать данные в «ваш» буфер до тех пор, пока аппаратный буфер не опустеет, не будет достигнуто ограничение в 90 символов или не истечёт тайм-аут по умолчанию (1000 мс).
const byte BufferSize = 90;
char Buffer[BufferSize + 1];
void setup(){
Serial.begin(9600);
}
void loop(){
if(Serial.available() > 0){
while(Serial.available() > 0){
// "readBytes" завершается, если определенная длина была прочитана, или
// истекает время ожидания. Он заполняет «Буфер» данными от 1 до 90 байт. Чтобы изменить
// использование тайм-аута: Serial.setTimeout() в setup(). Тайм-аут по умолчанию — 1000 мс.
Serial.readBytes(Buffer, BufferSize);
}
// Распечатать содержимое «вашего» 90-символьного буфера.
Serial.print(Buffer);
Serial.println("");
// Вы можете использовать Serial.peek() для проверки, больше ли 90 символов
// были в последовательном буфере и «ваш» буфер имеет обрезанные данные.
// Этого никогда не должно произойти, потому что вы знаете максимальную длину
// входящие данные и ваш входной буфер имеет достаточный размер.
if(Serial.peek() != -1){
Serial.print("90 byte Buffer Overflowed. ");
}
// Очищаем содержимое «вашего» буфера.
memset(Buffer, 0, sizeof(Buffer));
}
}
Но у Arduino последовательный буфер всего на 64 байта. Из-за этого ограничения я не могу принимать больше байтов.
Это утверждение — чушь. Буфер, конечно, есть, но он позволяет принимать до 64 байтов (помещаемых туда процедурой обработки прерываний последовательного порта), прежде чем вы извлечёте хотя бы один.
Всё, что вам нужно сделать, — это быстро извлечь данные (то есть выполнить Serial.read()) достаточно быстро, чтобы удалить данные из буфера и сохранить их в памяти.
Вам необходимо опубликовать минимальный, полный и проверяемый пример (MCVE), демонстрирующий вашу проблему. Например, вы используете delay(1000) перед попыткой чтения последовательных данных?
См. мою публикацию о получении последовательных данных без блокировки, а также асинхронном (последовательном) периферийном интерфейсе — для Arduino.
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- В чем разница между библиотеками Software Serial? Какая из них совместима с Arduino Nano?
- Как отправить команду AT на sim800l с помощью SoftwareSerial
- Проблемы с последовательной связью от Arduino к Bluetooth HC-05
- Как Arduino может проверить, подключен ли он к ПК и включен ли компьютер?
- Как отправлять и получать беззнаковые целые (unsigned int) от одного arduino к другому arduino
- Использование последовательных контактов TX/ RX для связи по USB
- Как отправить int[][] как массив байтов через Serial