Реализовать контроллер кадров UART
Я программирую на плате STM32, и я не понимаю, как использовать мои периферийные устройства: опрос, прерывание, DMA, прерывание DMA...
На самом деле, я кодировал модуль UART, который отправляет базовые данные, и он работает в режиме опроса, прерывания и DMA.
Но я хотел бы иметь возможность отправлять и получать конкретные кадры с переменной длиной, например:
[НАЧАЛО | LGTH | CMD_ID | ДАННЫЕ (LGTH) | CRC ]
У меня также есть датчики, и я хотел бы взаимодействовать полученные данные в этих кадрах UART с датчиками.
Итак, я не понимаю:
как запрограммировать модуль UART для работы в режиме "кадр"? (буфер? круговой DMA? прерывание? где, когда..)
когда я могу отправить или получить кадр с помощью моего UART, каков наилучший способ взаимодействия с датчиками? (внутри прерывания таймера "в автомате" с переменной extern? ...)
В будущем, идея заключается в том, чтобы нести это приложение в свободном доступе.
Спасибо!
2 ответа
Абсолютно в DMA, когда это доступно.
У вас есть один большой (хорошее решение циклическое) буфер, и вы просто пишете данные с одной стороны. Если DMA еще не работает, вы запускаете DMA с вашим буфером.
Если DMA работает, вы просто записываете свои данные в буфер и ждете полного прерывания передачи DMA.
Позже в этом прерывании вы увеличиваете указатель чтения буфера (поскольку вы уже отправили некоторые данные) и проверяете, доступны ли какие-либо данные для отправки через DMA. Установите адрес памяти в DMA и количество байтов в буфере для отправки.
Опять же, когда происходит DQ TC IRQ, повторите процесс.
FRAME не поддерживается, но только в виде простых байтов. Это означает, что вы должны "изобрести" свой собственный протокол фрейма и использовать его в приложении.
Позже, когда вы захотите отправить эту FRAME через UART, вы должны:
- Записать начальный байт в буфер
- Напишите другие байты заголовка
- Напишите фактические данные
- Запишите стоп-байты /CRC/ что угодно
- Проверьте, не работает ли DMA, если нет, запустите его.
Обычно я использую эту концепцию фрейма:
[СТАРТ, АДРЕС, CMD, LEN, ДАННЫЕ, CRC, СТОП]
- START: начальный байт, указывающий начало кадра
- АДРЕС: адрес устройства, когда на шине используется несколько устройств
- CMD: идентификатор команды
- LEN: 2 байта для длины данных
- ДАННЫЕ: фактические данные в байтах переменной длины
- CRC: 2 байта для CRC, включая: адрес, cmd, len, данные
- STOP: стоп-байт, указывающий конец кадра
Вот как я делаю это в каждом проекте, где это необходимо. Это не использует процессор для отправки данных, просто устанавливает DMA и начинает передачу.
С точки зрения приложения, вам просто нужно создать send_send(data, len)
функция, которая создаст кадр и поместит его в буфер для передачи.
Размер буфера должен быть достаточно большим, чтобы соответствовать вашим требованиям:
- Сколько данных в определенное время (это продолжается или много данных за небольшое время)
- UART скорость передачи
По конкретному вопросу, спросите, и, возможно, я могу предоставить некоторые примеры кода из моих библиотек в качестве ссылки.
В этом случае, когда вам нужно реализовать этот протокол, я, вероятно, использовал бы простые прерывания и в обработчике использовал бы побайтовый конечный автомат для разбора входящих байтов в буфер кадра.
Только когда будет получен полный, действительный кадр, необходимо сигнализировать о каком-то семафоре / событии и запрашивать запуск планировщика, в противном случае вы можете обработать любую ошибку протокола, как вам требуется - возможно, передать какое-нибудь сообщение "error-repeat" и сбросить состояние -машина, чтобы дождаться начала байта Nexx.
Если вы используете DMA для этого, то переменная длина кадра будет неудобной, и вам все равно придется повторять полученные данные для проверки вашего протокола:(
Мне кажется, что DMA не подходит для этого...
РЕДАКТИРОВАТЬ: если нет вытесняющей многозадачности, тогда забудьте обо всех вышеупомянутых семафорах:) Тем не менее, легче проверить логический флаг 'validFrameRx', чем анализировать данные блока DMA.