Как стать автором
Обновить

Комментарии 16

В выводе данных в GPIO через DMA есть одна проблема. DMA не умеет в «чтение-модификация-запись» и это значит, что теряется целый порт. Ну, если только не заполнять буфер не только состояниями ног интерфейса, но и состоянием всех ног этого порта, настроенных на выход. Но мне кажется, что вывод можно организовать чисто на таймере, настроенном в режим PWM и DMA. Если нужно вывод в две ноги (а-ля дифференциал), то можно задействовать два канала таймера, а заполнять регистры сравнения с помощью DMA можно через регистр TIMx->DMAR и соответствующие настройки таймера. Таймер умеет генерировать пачку запросов DMA, в соответствии с заданным количеством обновляемых регистров, за одно событие (например, переполнение до значения в регистре TIMx->ARR)
Если хорошо подумать, то наверняка можно организовать и приём данных, используя таймер в режиме захвата.
У STM32 очень мощные и крутые таймеры. Разобравшись в их режимах работы, можно очень много чего реализовать.
DMA не умеет в «чтение-модификация-запись» и это значит, что теряется целый порт.

Используйте GPIOx_BSR, и порт теряться не будет.

В разных линейках STM32 эти регистры отличаются по своим битовым картам.
Да и к тому же, один черт нужно тратить таймер что на реализацию через GPIO, что на реализацию на чистом таймере. Мне даже думается, что принимаемые данные таймером в режиме захвата можно писать в буфер как временнЫе диаграммы и потом уже можно подвергать их программному анализу. И тут уже можно и данные вытащить и диагностику с адаптацией сделать.
Работа большая проделана, но по сути это всего лишь реализация приёма-передачи кодом Манчестера. Это не соответствует ни ГОСТу, ни MIL-STD. На уровне сигналов у вас нет никакого обработчика. Надо же анализировать фронты. И в целом контролировать возможные ошибки и сбои. STM32 с этим не справится — медленные прерывания.
Реализацию кода Манчестера можно найти у SiLabs. В их контроллерах есть CLU (configurable logic unit) и PRS (peripheral reflex system). И вроде у Cypress есть что-такое, была тут серия статей. Но для вашей задачи лучше взять Миландр с контроллером МКИО, и Ethernet там есть. Но в любом случае для соответствия стандартам надо по каждому пункту стандарта писать обработчик.
Конкретно для этого интерфейса существуют серийные контроллеры канала. И если делать именно такой и на кристалле — то всё нужно делать по-серьёзному, а не подобным образом.

Однако если Вы имеете ввиду, что для передачи 1 мегабита на 10 метров по дифпаре нужно было по-честному заводить линии на АЦП и делать честный ЦОС — то я считаю, что это избыточно. Это не радиотракт. Здесь нет созвездий, нет фаз, нет уровней амплитуд, нет многолучёвости, АЧХ канала и прочего.
Это просто низкоскоростной поток битов с довольно-таки лютой амплитудой, и перепутать 0 и 1 здесь ох как непросто. И за время пакета максимальной длительности синхронизация здесь никуда не уедет.
Абсолютное большинство интерфейсов вроде SPI, UART и прочих (в том числе параллельных) низкоскоростных (до 10 мбит/с) вполне реализуемы программно и будут работать с достаточным качеством.
Конкретно это устройство было достаточно сурово протестировано, в том числе на диапазонах температур -40/+65 и рядом с шумящими в мегагерцовом диапазоне устройствами (в том числе силовыми).

P.S. Это устройство создавалось, чтобы отказаться от отечественного контроллера производства, если не ошибаюсь, НПП «Модуль».
И за время пакета максимальной длительности синхронизация здесь никуда не уедет.
В манчестере она в принципе никуда уехать не может на любой длительности пакета, так как он является самосинхронизирующимся кодом.
В моей реализации синхронизация происходит однократно — в начале пакета (по первому фронту), а не в каждом слове, и уж тем более бите.
Максимальная длина пакета — (32 слова данных + 1 командное) * 20 бит = 660 бит (то есть 660 микросекунд).
Это нужно было учитывать, однако реальное «уплывание» составило порядка единиц наносекунд на самых длинных пакетах. А допустимое «уплывание» — не более 250 наносекунд. Так что запас вполне себе приличный.
Такой подход, хоть и работоспособен, но сводит на нет одно из основных преимуществ манчестерского кодирования.
при использовании таймера для захвата (в режиме захвата) вполне можно сделать внутрибитовую автоподстройку.
Я думал на этот счёт. А именно — завести два пина, которые бы реагировали один на фронт, другой на спад. И скорее всего, для манчестера это вполне прокатило бы.
Однако позже было добавлено требование помимо манчестера реализовать как раз-таки доморощенный интерфейс в той же железяке (для обратной совместимости с особенно древним железом). И вот там уже никакой внутрибитовой синхронизации нет, только стартовый синхроимпульс и линия данных.
Поэтому было решено делать всё по одной схеме с таймером+DMA.
Не надо два пина, можно два канала таймера настроить на срабатывание по разным фронтам одного сигнала:
  // ...

  LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI1FP1);
  LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_FALLING);
  LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);

  // ...

Этот же таймер по переполнению может ловить таймауты внутри пакета (когда не пришел очередной фронт на заданном интервале). Правда я не пробовал для этого задействовать DMA — скорости у меня были на три порядка меньше Ваших. Поэтому работал по прерываниям от таймера, ловя флаги от каналов и флаг переполнения для отработки таймаута. Можно ли это разогнать до Ваших скоростей — сказать не берусь, надо пробовать, но код, вызываемый по прерыванию достаточно короткий, да и процессор у Вас помощней моего, может и прокатит.

Только 1 вопрос: почему не взять 1582ВЖ3Г-0291 (контроллер протокола МКИО с выходом на шину SPI), пристыковать его к вашей системе и забыть про работу с МКИО, а заниматься только обработкой/транслированием данных? Там ведь предусмотрена вся работа в соответствии с ГОСТ.
Хотя этот вопрос, наверное, к вашему руководителю.

Как я уже писал в комментарии чуть выше, реализовывать пришлось не только МКО, но и старинный «велосипедный» интерфейс.
Кроме того, смысл статьи не в том, как реализовать именно МКО на костылях, а как сделать практически любой программный контроллер (приблизительно до 10 МГц). В том числе и такой, который не выпускают серийно.
На мой взгляд, именно связка TIM+DMA+GPIO является самой функциональной. Об этом и статья.

Понятно, интересно в целом!

Задача слишком простая, чтобы решать её столь сложным способом. Для преобразования манчестера в spi — достаточно PIC10F204T в корпусе sot23-6 за 26 рублей.
А Вы обратили внимание, что автор обрабатывает поток 1 МБит/с?
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.