Размер кольцевого буфера FIFO через UART

Я пытаюсь реализовать протокол UART для связи между двумя платами. данные кодируются ascii, а длина сообщений является переменной. Я решил реализовать пакет, чтобы «инкапсулировать» информацию.

Пакет: {STX, DATA, ETX}.

STX — это «Начало текста» в таблице ASCII. Его шестнадцатеричный код — 0x02, ETX — «Конец текста». Его шестнадцатеричный код 0x03. Каждый байт в поле DATA может принимать любое значение от 0x00до 0x7Fкроме 0x02и 0x03.

Проблема 1: Длина данных
Как отправить данные переменной длины по UART?
Пример: {STX, Hello\0, RTX} и {STX, Это длинный текст\0, RTX}

Я копался в Интернете и обнаружил, что лучший подход — использовать циклический буфер FIFO. Проблема в том, как исправить BUFFER_SIZEв этом случае? Допустим, я провел некоторые математические расчеты и выяснил, что самое длинное сообщение, которое я собираюсь передать по UART, составляет 90 байт, а самое короткое — 4 байта. я должен #define BUFFER_SIZE 90или мне нужно взять больший буфер?

В обоих случаях, как работает FIFO в этих случаях:
Случай 1: длина данных < BUFFER_SIZE.
Пример: {STX, ABCD, ETX} и BUFFER_SIZE = 90 байт.

Случай 2: Буфер полон, но данные все еще поступают.
Пример: BUFFER_SIZE = 13

Пакет: {STX, READ_X, ETX}{STX, REMOVE_Y,ETX}.

В HEX эти сообщения имеют вид
0x02 0x52 0x45 0x41 0x44 0x5f 0x58 0x00 0x03 0X02 0x52 0x45 0x4d 0x4f 0x56 0x45 0x5f 0x59 0x00 0x03

Буфер заполнен, когда мы достигаем 0x4d(курсивом). Как он справляется с этой ситуацией?

В вопросе вы сказали: « Буфер заполнен, когда мы достигаем0x04 ». Разве вы не имеете в виду, что буфер заполнен, когда мы достигаем0x4d ?
@SamGibson Да! Виноват

Ответы (2)

Очевидно, вам нужен какой-то процесс, который извлекает данные из FIFO всякий раз, когда обнаруживает, что он не пуст. Затем FIFO должен быть достаточно глубоким, чтобы позаботиться о наихудшем несоответствии между ставкой ввода и ставкой выбытия.

Вообще говоря, UART обычно достаточно медленны, чтобы другие действия ЦП могли не отставать, а это означает, что FIFO может быть относительно неглубоким, но если ваше приложение достаточно сложное, вы можете обнаружить, что требуется больший буфер.

Например, если вы знаете, что потребляющий процесс может быть заблокирован на некоторое время, FIFO должен быть достаточно глубоким, чтобы вместить как минимум то количество символов, которое может быть получено за это время.

Подпрограмма, которая читает UART и помещает символы в FIFO (обычно это прерывание), должна проверять флаг DATA_AVAILABLE перед выходом (и запускаться снова, если данные). UART RX обычно имеют двойную буферизацию и могут иметь 2 байта, особенно к моменту завершения кода fifo-push.

Первым прибыл, первым обслужен. Какие бы данные ни поступали, они будут храниться в FIFO последовательно, начиная с ячейки памяти. Предположим, что ширина данных FIFO составляет один байт, а общий размер памяти составляет 90 байт, это означает, что он имеет 90 ячеек памяти и будет хранить каждый входящий байт последовательно в ячейках памяти. Вы читаете байты с него в режиме "First Written First Read". Когда вы читаете байт, это место теперь «свободно» для перезаписи. FIFO считается заполненным, когда вы записали байты на полную мощность, но еще не прочитали ни одного байта. Предположим, что FIFO заполнен, а данные все еще поступают, что происходит, так это то, что новые байты будут перезаписывать самые старые данные (из первого местоположения) последовательно. Таким образом происходит потеря данных. Таким образом, вы должны прочитать буфер, прежде чем он заполнится. Скажем, 90 байт поступают в FIFO приемника UART с некоторой скоростью передачи данных. Он будет заполнен через определенное время, в зависимости от скорости передачи данных, прежде чем будет получено все сообщение. Если вы используете FIFO с размером < 90 байт, вы должны убедиться, что вы читаете байты до того, как он заполнится. Если размер FIFO превышает 90 байт и больше байтов не поступает, данные останутся в FIFO, и вы сможете прочитать эти байты в любое время.