Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Аппаратное управление таймером состоянием вывода

Пн окт 10, 2022 07:48:30

Добрый день, необходимо сформировать сигнал (как на приложенном рисунке) на пине мк от прерывания. Т.е. по событию EXTI каждый раз на пине формируется сигнал постоянной формы (50мксек высокий уровень, 50 - низкий, 500 - высокий и потом низкий до следующего EXTI).
Программно это сделать не проблема, завести таймер и в его прерываниях переключать пин. Но хотелось бы реализовать это аппаратно. Так и временные промежутки будут поточнее и время срабатывания.

Как это реализовать я пока не представляю. В самом сигнале самым важным является первый промежуток 50 мк сек и начало его срабатывания. Можно было бы включить один из таймеров в режиме One Pulse Mode, он бы отработал первые 50 мксек, а дальше вторым таймером в прерывании переключать оставшиеся промежутки, но при настройке пина в режим одиночного срабатывания PWM в дальнейшем у меня не получается менять его состояние, т.е. отработал он импульс, перешел в LOW и перевести его в HIGH вручную уже не получается.

Есть ли тут какие-либо варианты или же только переключать в прерываниях от таймера?
Вложения
Безымянный.png
(6.35 KiB) Скачиваний: 85

Re: Аппаратное управление таймером состоянием вывода

Пн окт 10, 2022 09:16:45

OPM режим с прерыванием по UEV: в прерывании EXTI запускаешь таймер, он дает тебе два первых импульса. Затем перенастраиваешь в прерывании UEV на 500мкс, опять запускаешь, уже отключив прерывание UEV.
Тольког 50мкс - маловато, из-за накладных расходов второй импульс будет больше (но можно экспериментально определить нужные настройки, а прерыванию UEV поставить наивысший приоритет).
Еще более разумный вариант — запусить передачу при помощи DMA, пусть он в CC1/ARR и пишет нужные значения. Тогда проблемы с длительностью будут минимальными.
Вот так, например. В конкретном случае нет нужды ни CC1, ни ARR дергать: можно прескалером поиграться.

Re: Аппаратное управление таймером состоянием вывода

Пн окт 10, 2022 10:04:43

Интересная задачка, а что если такой вариант прикинуть (конечно, расход таймеров большой, но их вроде как много): объединить выход двух таймеров, первый настроить на двойной OPM (продвинутые так умеют) и период в 50мкс, второй сделать слейвом с делением на 2 и тоже OPM, тогда на второй переход первого таймера запустится второй, то есть вообще ничего изменять не надо?

Re: Аппаратное управление таймером состоянием вывода

Пн окт 10, 2022 14:43:55

Eddy_Em,
OPM режим с прерыванием по UEV: в прерывании EXTI запускаешь таймер, он дает тебе два первых импульса. Затем перенастраиваешь в прерывании UEV на 500мкс, опять запускаешь, уже отключив прерывание UEV.

Идея понятна, но смущает ручной запуск таймера в EXTI ..., ну ладно, как вариант.

Но вопрос, если пин настроен как OPM таймера, то менять состояние этого пина по ходу программы я не могу?

Еще более разумный вариант — запусить передачу при помощи DMA, пусть он в CC1/ARR и пишет нужные значения. Тогда проблемы с длительностью будут минимальными.

Мне кажется вызов DMA или в прерывании перезаписать CC1/ARR примерно то на то и выйдет?

Тут еще минус в том, что сейчас таймер срабатывает от EXTI автоматически, а если делать на перезапуске в прерываниях, то придется перенастраивать на программный запуск таймера, что скорее всего скажется на времени старта первого импульса

azhel12,
объединить выход двух таймеров
А разве так можно делать? Я чет даже не знаю...

Re: Аппаратное управление таймером состоянием вывода

Вт окт 11, 2022 01:07:55

Но хотелось бы реализовать это аппаратно.
В чём проблема?
Берём XMC4500 или XMC4700 или XMC4800. Внешний сигнал заводим на вход любого таймера (CCU). На этот вход программируем функцию запуска таймера (по нужному событию: фронт/спад/фронт_или_спад). Пассивный уровень выхода таймера устанавливаем = LOW. Таймер настраиваем в режим PWM: период = 100мкс, длина импульса =50мкс. Также внутри этого периода настраиваем генерацию прерывания, в ISR которого будем производить запись новых периода/длины_импульса в теневые регистры. Во 2-м входе в ISR настроим новое прерывание на точку 500мкс от начала 2-го периода. В 3-м входе в ISR - выключим таймер.
Всё! Все интервалы будут выдержаны с точностью до такта CPU, так как ни один не зависит от задержек выполнения CPU/DMA.

PS: Если сильно нужно, то операции производимые в ISR, можно заменить на DMA (направив сигналы прерываний на линии DMA-запросов).
PPS: А если ещё немного подумать и немного доработать алгоритм, то даже целый CCU не нужен, можно обойтись его 1/4 частью.

Re: Аппаратное управление таймером состоянием вывода

Вт окт 11, 2022 09:47:45

Есть ли тут какие-либо варианты или же только переключать в прерываниях от таймера?


Попробуйте использовать не таймер, а модуль SPI. Ваш сигнал, это 12-битное слово 0b101111111111 на скорости 20kbps.

Re: Аппаратное управление таймером состоянием вывода

Вт окт 11, 2022 11:53:54

jcxz, Ваша идея мне нравится, я даже не знал, что в режиме PWM можно генерировать прерывания.
Только пока с реализацией не получилось. Использую stm32f7 и из-за некоторых соображений настройку делаю на HAL

В main запускаю:
Код:
  HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_4);
  State = 1;


В прерывании меняю CCR и ARR:
Код:
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
   if(htim->Instance == TIM3)
   {
      switch (State)
      {
         case 1:
            TIM3->CCR4 = 24999;
            TIM3->ARR = 49999;
            TIM3->EGR = TIM_EGR_UG;
            State++;

            break;

         case 2:
            TIM3->CCR4 = 4999;
            TIM3->ARR = 9999;
            TIM3->EGR = TIM_EGR_UG;

            HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_4);
            State = 1;

            break;

         default:
            __NOP();
      }
   }
}

Если я не ошибаюсь, то прерывание генерируется по достижению счета ARR, поэтому в case 1 меняю значения ARR и CCR на более длительные, т.е. на этот момент у меня уже 2 тайминга по 50 мксек должно отработать. Дальше отрабатывают новые ARR и CCR, генерируется прерывание и в case 2 я возвращаю прошлые значения и останавливаю PWM.

Но что-то работает не так

PWM настроен на запуск от EXTI
Вложения
2.png
(30.4 KiB) Скачиваний: 57
1.png
(30.28 KiB) Скачиваний: 45

Re: Аппаратное управление таймером состоянием вывода

Вт окт 11, 2022 13:01:20

F7 разные бывают. Какая модель?

Re: Аппаратное управление таймером состоянием вывода

Вт окт 11, 2022 13:03:01

>TEHb<, 746

Re: Аппаратное управление таймером состоянием вывода

Вт окт 11, 2022 15:52:03

Вот собака, он без HRTIM! Тогда как вариант использовать
Eddy_Em писал(а):запусить передачу при помощи DMA, пусть он в CC1/ARR и пишет нужные значения.


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

Re: Аппаратное управление таймером состоянием вывода

Вт окт 11, 2022 22:42:12

jcxz, Ваша идея мне нравится, я даже не знал, что в режиме PWM можно генерировать прерывания.
У таймеров XMC регистр сравнения (который определяет точку переключения выхода PWM) точно также может на этом же значении вызывать генерацию прерывания (если соответствующий бит разрешения установлен), либо можно отдельно разрешить прерывания в конце и/или в середине периода PWM (для этого регистр сравнения не используется). А если использовать таймер с двумя CR (регистрами сравнения), то можно одним CR задать точку переключения выхода PWM, а вторым CR - точку генерации прерывания в произвольном месте периода (никак не привязанном к моментам переключения выхода PWM).

Итого: один CCU8 (таймер с двумя регистрами сравнения) позволяет генерировать до 6-ти прерываний на период в разных точках периода: начале/конце, в середине, по 1-му CR при счёте вверх и при счёте вниз, и то же самое - по 2-му CR.
Для этих 6 источников прерываний можно назначить до двух разных сигналов прерывания к NVIC. Это не считая того, что для многих событий таймера (старт или стоп, захват, сигнал разрешения тактирования, изменения направления счёта, перезагрузка и др.) если они вызываются внешними сигналами, то по ним тоже таймер может дополнительно генерить прерывания по назначенным линиям NVIC.

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 13:47:42

>TEHb<, jcxz, Ваши два совета в целом похожи и в целом они работают.
Настроить PWM на запуск от EXTI и в прерывании от таймера менять ARR и CCR, дальше останавливать таймер, возвращать ARR и CCR на место и разрешать повторное срабатывание по следующему EXTI.

Одна только проблема с этим: как только отрабатывают все 3 тайминга (50, 50 и 500 мксек), выставляем низкий уровень и при следующем EXTI у нас первые 50 мк сек опять должны быть HIGH, но они будут LOW, и из-за этого все уровни поменяются местами и так будет происходить циклично

Добавлено after 2 minutes 27 seconds:
Код:
if(htim->Instance == TIM2)
   {
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);      // WorkTest

      switch (State)
      {
         case 1:
            State++;

            break;

         case 2:
            TIM2->CCR4 = 50000 - 1;
            TIM2->ARR = 50000 - 1;
            TIM2->EGR = TIM_EGR_UG;
            State++;

            break;

         case 3:
            HAL_TIM_OC_Stop_IT(&htim2, TIM_CHANNEL_4);

            TIM2->CCR4 = 5000 - 1;
            TIM2->ARR = 5000 - 1;
            TIM2->EGR = TIM_EGR_UG;
            HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_4);
            State = 1;

            break;

         default:
            __NOP();
      }
   }


Ну и почему-то правильные тайминги выставляются при ARR = 5000 и CCR = 5000;

Я канал настроил как output compare CH, но с PWM по-моему то же самое
Вложения
3.png
(19.64 KiB) Скачиваний: 40
2.png
(23.13 KiB) Скачиваний: 41
1.png
(21.91 KiB) Скачиваний: 39

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 13:50:21

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

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 14:08:47

DmitryR, предлагаю для начала от кала отказаться. Все равно ведь часть вещей делается напрямую регистрами!
Ну и еще раз напомню о DMA. А также, видимо, мимо пролетело: было же предложение SPI или I2C использовать, чтобы данную последовательность импульсов воспроизвести.
P.S. А код реально жуткий. Дрыгать ногодрыгом в прерывании от таймера, когда можно напрямую в ШИМ-режиме… Да еще и ты учти, что есть приличные накладные расходы на вход в прерывание и исполнение кода в нем. Таким образом честных 50мкс ты никак не получишь. Кстати, каловская HAL_GPIO_TogglePin - это тебе не макрос и даже не true_inline, а самая настоящая функция со всеми вытекающими!\
Если тебе так хочется кала, то напиши на С++ с шаблонами свою обертку, и будет тебе щассье. Так как минимум пара человек с форума делала.

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 14:22:49

>TEHb<,
Настраивайте однозначно в какой точке устанавливать высокий уровень, а в какой низкий

Дело в том, что там нет таких настроек, могу только выбрать с какого уровня будет это все стартовать CH Polarity.
Хотя я тогда не понимаю, почему при повторном запуске он стартует не с указанного HIGH, а с предыдущего уровня

Eddy_Em,
Там стоит FreeRTOS, но вроде как не планируется ее взаимодействие с этим таймером, поэтому можно и без HAL...

Ну и еще раз напомню о DMA

Попробую на DMA, но мне кажется тут дело не в том, как менять ARR и CRR

А также, видимо, мимо пролетело: было же предложение SPI или I2C использовать

Как-то диковато звучит реализовать функции таймера посредством SPI, но можно попробовать)

Добавлено after 3 minutes 44 seconds:
Eddy_Em,
P.S. А код реально жуткий. Дрыгать ногодрыгом в прерывании от таймера, когда можно напрямую в ШИМ-режиме…

Если Вы про это
Код:
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);      // WorkTest

То не, это не тот пин, который должен сигнал формировать, это я просто поставил, чтобы отследить на осциллографе когда срабатывает прерывание и не убрал.
А так в прерывании только ARR и CRR меняется, больше там ничего не делается, ну кроме State++

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 14:32:03

Ну вот, чтобы не было проблем, нужно делать все более-менее аппаратно. И, кстати, предложение Andrey_B использовать SPI - очень даже дельная идея (если есть в системе 1 ненужный SPI и его нога MOSI свободная). И таймер на это тратить не придется, и канал DMA.
А ртось - это фу. Если приложение для МК невозможно без ртоси сделать, то дешевле купить одноплатник за две тысячи рублей и реализовать всю многозадачность на нормальном линуксе, а для RT выделить какой-нибудь недорогой камушек (зачастую даже F030 сгодится).

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 14:50:56

Eddy_Em,
А ртось - это фу

РТОС фу, HAL фу, LWIP фу, если так на все фукать на одних регистрах придется сидеть писать кучу времени)))
Да там FreeRTOS поставлена чисто из-за LWIP (уж что, а ethernet я точно на регистрах писать не готов).
На ОС я скидываю всякие медленные задачи не первой необходимости, а все RT делаю на приоритете выше чем у ОС и не взаимодействующими с ОС. Ну и стараюсь делать их аппаратно.
Камень 746 - таймеров, SPI, DMA, всего полно.

Тут знаете, дело-то даже и не в регистрах, это уже довольно заезженная тема, отношение к HAL давно понятно...
Тут скорее вопрос в принципе в функциональной возможности реализации тем или иным способом.
Вот, например, сейчас задача практически решена, за исключением подмеса ARR и CRR переключения пина происходит аппаратно, но он начинает свой новый цикл со значения предыдущего. Предполагаю, что так построена архитектура, что что он при первом запуске выставляет настроенный уровень, а дальше делает toggle и когда вмешиваешься в этот процесс, система себя так ведет. Может тогда помимо старт/стоп надо еще делать какую-нибудь переинициализацию состояния пина...
Добавить DMA можно, но на данном этапе это изменит лишь способ перезадания ARR и CRR

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 15:06:22

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



PS:А фукателя не слушайте. Он F4 то ещё не освоил, до F7 к пенсии не доберётся точно со своими фу.

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 15:22:24

VladislavS, Видимо мне надо поглубже покапатьcя в Reference manual.
Опять же, как Вы и написали, это настройки на событие сравнения, а по событию сравнения надо менять ARR и ССR. Не знаю даже... Надо мне почитать сначала

PS: Для себя я сделал вывод, что все, что не критично на HAL или LL, критичные функции на CMSIS или, в некоторых случаях, LL. Типа золотая середина по-моему мнению

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 15:55:09

ARR может быть буферизирован и новое значение будет активироваться при достижении текущего.
Изображение
изображение_2022-10-12_155430452.png
(9.92 KiB) Скачиваний: 288
Ответить