Получить сообщение неопределенного размера в UART на C

Пишу свои драйверы для LPC2148 и в голову пришел вопрос. Как мне получить сообщение неопределенного размера в UART?

На ум приходят только 2 вещи: 1 - Настроить сторожевой таймер и прекратить прием, когда время истечет. 2- сделайте так, чтобы всякий раз, когда ему отправляется сообщение, должен быть символ конца сообщения.

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

Большое тебе спасибо


person morcillo    schedule 27.12.2012    source источник


Ответы (5)


Это похоже на неправильное использование сторожевого пса. Я нашел три решения этой проблемы:

  1. Используйте пакеты фиксированного размера и DMA; Итак, вы получаете один пакет за транзакцию. Видимо, в вашем случае это невозможно.
  2. Получать сообщение по символам до тех пор, пока не будет получен символ конца сообщения. Вид подвержен ошибкам, поскольку, вероятно, в данных может появиться символ EOM.
  3. Перед каждым пакетом используйте заголовок фиксированного размера. В заголовке сохраните размер полезной нагрузки и / или идентификатор типа сообщения.

Третий подход, наверное, лучший. Вы можете объединить его с первым, то есть использовать DMA для получения заголовка, а затем данных (во второй транзакции, после того, как размер данных станет известен из заголовка). Это также один из самых гибких подходов.

Еще одна вещь, о которой нужно беспокоиться, - это синхронизация байтового потока. Во входных буферах UART может лежать мусор, который может считываться как данные, или вы можете получить только часть пакета после того, как ваш MCU включен (т.е. начало пакета уже было отправлено к тому времени). Чтобы этого избежать, вы можете добавить магические байты в заголовок вашего пакета и, возможно, CRC.

ИЗМЕНИТЬ

Хорошо, еще один вариант :) Просто сохраните все, что вы получаете, в растущем буфере для дальнейшего использования. Это в основном то, что делают драйверы для ПК.

person Roman Dmitrienko    schedule 27.12.2012
comment
Мне понравились ваши ответы, но я хотел чего-то еще более общего. Пример: получить строку неизвестного размера без конца сообщения и без каких-либо заголовков. Когда дело касается протокола (Modbus и т. Д.), Its very easy to receive n bytes because there is a file for that, but my question was for unknown sizes since Ive всегда интересовался, как работает последовательный порт ПК, он может получать любую строку любого размера без какого-либо заголовка, и он по-прежнему работает каждый раз. - person morcillo; 27.12.2012
comment
@morcillo Отредактировано :) Серьезно, вы можете взглянуть на драйверы Linux UART. Однако они не совсем очевидны и просты. Большая часть этого не требуется во встроенной системе. - person Roman Dmitrienko; 27.12.2012
comment
Я знаю, что встроенной системе это не нужно. Но я всегда хотел узнать, как это происходит. Но спасибо, вы очень помогли - person morcillo; 28.12.2012
comment
Я бы поставил другой подход. Вы можете запустить таймер и каждый полученный байт сбросить этот таймер. Если таймер достигает некоторого порога, вы признаете, что больше нет данных для приема. Это своего рода подход timeOut. - person Leandro Lima; 06.12.2013

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

person David Schwartz    schedule 27.12.2012

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

person Community    schedule 27.12.2012

лучше выбрать вариант 2) добавить символ конца передачи в строку передачи.

но я предлагаю добавить начало передачи также, чтобы убедиться, что вы получаете фактическую передачу.

person Kinjal Patel    schedule 27.12.2012

Сторожевой таймер используется для сброса системы при неожиданном поведении устройства. Я думаю, что лучше использовать буфер, который может хранить объем данных, который требуется вашему приложению.

person linuxchip    schedule 27.12.2012