0
«Не поймите меня неправильно», разумеется. :D
  • avatar
  • _YS_
  • 08 января 2018, 17:21
+1
Ради интереса, когда (и, если не секрет) для чего вам было необходимо получать произвольный сдвиг между каналами ШИМ? :)

Но это ладно. Я выше писал в предположении, что мы используем один таймер. Если разрешить себе использовать два таймера, то все сводится к конфигурации ШИМ-каналов от разных таймеров и задании разных начальных значений для этих двух таймеров. Дальше все будет происходить само по себе.

Надо сказать, что в STM32 это делается гораздо спокойнее, потому что таймеров там, как правило, больше, и потратить два не так жалко. :)

Вместо SBI/CBI в STM32 есть механизм bit-banding (отображение битов на индивидуальные адреса памяти). Для портов там вообще есть специальные регистры атомарной установки/снятия битов.

Не поймите меня правильно, я не продвигаю STM32 (или какую-то другую) архитектуру как абсолют. Если бы какая-то архитектура была абсолютом, то уже давно осталась бы она одна. Просто мы с вами разговариваем именно о STM32 и AVR, потому и примеры на STM32. С тем же успехом я мог бы приводить примеры на MSP430. Просто мы о них пока не говорим.

Кстати, у MSP430 мне как раз таки очень нравится ассемблер. Писать на нем — одно удовольствие! Вот это супер-архитектура для ассемблерного кода. Попробуйте, не пожалеете. Из них можно многое выжать.

А так, контроллер надо выбирать под задачу. В разных задачах разные архитектуры имеют преимущество. Скажем, в AVR мне нравится АЦП, а в STM32 — таймеры, особенно поддержка инкрементального энкодера.
  • avatar
  • _YS_
  • 08 января 2018, 17:19
0
Отписался в комментарии ниже.
  • avatar
  • _YS_
  • 08 января 2018, 16:44
0
Вы знаете, я еще раз подумал над вашими и Lifelover'а словами про края и серединки. Тут, конечно, надо рисовать, чтобы всем все стало понятно. Но если имеется в виду получение совсем произвольного сдвига между каналами (зачем?), то для этого можно сделать следующее (даже не трогая остальные аппаратные возможности):

— настроить прерывание по обнулению (при счете вниз) и переполнению (при счете вверх) таймера;
— в этом прерывании при достижении максимального значения таймера прибавлять значение сдвига к основному значению CCR канала, а при счете вниз и достижении нуля — вычитать.

Таким образом можно получить любой сдвиг.
  • avatar
  • _YS_
  • 08 января 2018, 16:44
0
Интересно, спасибо.
  • avatar
  • _YS_
  • 08 января 2018, 12:44
0
Нутк, без MOE (TIM_BDTR_MOE) действительно ничего не будет работать. :))
  • avatar
  • _YS_
  • 07 января 2018, 17:30
0
Еще одну статью, чтобы показать остальные режимы, кроме PWM1 и PWM2, я писать не буду. ;)
  • avatar
  • _YS_
  • 07 января 2018, 16:33
0
  • avatar
  • _YS_
  • 07 января 2018, 16:14
0
Расчехлю отладку, то есть.
  • avatar
  • _YS_
  • 07 января 2018, 12:29
0
Не знаю как можно удачней нарисовать.

Не так симметрично. Первая картинка напоминает комплементарный сигнал с большим защитным интервалом.

Ох. Я, наверное, по свободе расчехлю и попробую сам проверить, кто из нас неправ. :)

Может быть даже статьей отпишусь.
  • avatar
  • _YS_
  • 07 января 2018, 12:28
+1
Действительно, ошибаетесь. Лет пять-шесть назад я тоже был студентом, второго-третьего курса. Преподом я был года три-четыре назад. :) Наверное, вы все же меня с кем-то путаете. :D
  • avatar
  • _YS_
  • 07 января 2018, 01:59
0
А, до меня дошло, чего вы хотите. Картинки не совсем удачные. Я наконец-то прочел подписи на них. :D

Да, навскидку я бы делал такое с помощью двух каналов.
  • avatar
  • _YS_
  • 06 января 2018, 22:09
+1
Вы предлагаете мне за вас углубиться в даташит и поэкспериментировать, чтобы развеять ваши сомнения? :) Честно, мне лень. Сейчас мне не нужен этот режим. Когда понадобится — освою. Вполне вероятно, что я неправильно вспомнил бит, который нужно выставить. Я использовал только комплементарный режим.

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

Но в любом случае, таймер 1, например, имеет четыре ШИМ-канала с управляемой инверсией, которые, естесственно, можно задействовать одновременно в любой комбинации. Так что если и не с одного канала, то с двух можно получить любой сигнал. Это то, что я могу сказать навскидку.
  • avatar
  • _YS_
  • 06 января 2018, 21:48
0
Тогда надо еще раз инвертировать комплементарный канал. Или инвертировать основной канал. Это, если мне не изменяет память, бит CCxP в регистре CCER.
  • avatar
  • _YS_
  • 06 января 2018, 20:29
+1
Да-да, сигнал именно такой, как на картинке. Генерация такого сигнала — стандартная возможность некоторых каналов в таймерах STM32.

В том отрывке кода, который я привел, я включаю комплементарный канал (бит TIM_CCER_CC3NE), после чего просто задаю ненулевой защитный интервал (DEADTIME_CONF — дефайн, объявленный выше по тексту программы).

Ну и как бы все. Остальное стандартная настройка режима ШИМ, включение генерации сигнала (TIM1_BDTR_MOE) и так далее. Естесственно, в полной программе есть еще настройка GPIO и тактирования.

Да, действительно все так просто. И не нужны никакие STM32Cube и прочие HAL с StdPeriphLib. Просто надо внимательно читать даташит.
  • avatar
  • _YS_
  • 06 января 2018, 20:11
+1
Когда я говорил про ATtiny5/10, я имел в виду двухфазный сигнал, т.е. типа пуш-пулл — симметричный с регулировкой коэффициента заполнения. Не получишь его на одном канале в хвалёном стм…

Прямо сейчас на столе у меня лежит устройство, которое генерирует именно такой сигнал на одном канале таймера 1 в STM32F030F4P6. Код инициализации (взят прямо из проекта):


    /** TIM1 setup for complementary PWM on pin PA10/TIM1_CH3 & PB1/TIM1_CH3N */
    TIM1->CCMR2=TIM_CCMR2_OC3PE | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; //Fast PWM on TIM1_CH3
    TIM1->BDTR=TIM_BDTR_MOE | DEADTIME_CONF;
    TIM1->PSC=PWM_PRESCALER;
    TIM1->ARR=PWM_ARR;
    TIM1->CCR3=0;
    TIM1->CNT=0;
    TIM1->CCER=TIM_CCER_CC3E | TIM_CCER_CC3NE; //Enable complementary output
    TIM1->CR1=TIM_CR1_ARPE | TIM_CR1_CEN;
    TIM1->EGR=TIM_EGR_UG;


На выходе (PA10/PB1) именно push-pull сигнал. Коэффициент заполнения управляется значением TIM1_CCR3 (да, сразу для двух каналов с учетом защитного интервала).

Кстати, банального компаратора в стм тоже не положили.

Вы постоянно обобщаете применительно к каким-то абстрактным STM32, в то время как я уже не раз указывал, что это семейство негомогенно, вопреки заверениям маркетологов ST. Пожалуйста, уточняйте, о каком кристалле идет речь…

Скажем, в упомянутой мной ATtinyX61A компаратор даже можно использовать совместно с TC1 для защиты — видно, что люди думали прежде чем делать…

В STM32L152, например, компараторов целых два, и, не поверите, их тоже можно использовать для защиты:

The COMP2 output can be redirected to TIM2/TIM3/TIM4’s input capture 4 (IC4) or OCREF_CLR inputs, or to the TIM10s input capture 1 (IC1). — см. даташит.

Более того, из этих двух компараторов можно собрать оконную схему, выбрать из нескольких предустановленных уровней опорного напряжения или вообще использовать ЦАП для опоры, и т.д., и т.п.

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

В Си есть стандартная библиотека sys/time.h, которая тебе спокойно распакует time_t в struct tm.

И сколько оно занимает в памяти МК?
  • avatar
  • _YS_
  • 06 января 2018, 18:23
0
Не могу сказать что это хорошо, можно и самому ограничивать коэффициент заполнения.

Вы немного не поняли. Таймер, о котором я говорю, немного более продвинут, чем вы себе представляете. :)

Ограничение коэффициента заполнения сработает, если используются два канала ШИМ. Тогда, действительно, можно следить, чтобы значения не перекрывались (и не оказывались слишком рядом).

В STM32 описанное реализуется одним каналом сравнения. То есть, коэффициент заполнения задается один, и из него получается два выходных сигнала: один как есть, а второй комплементарный, задержанный на указанное время (защитный интервал).

Такие дела.

Много говорят про дешёвый стм, но не видел я чтобы они были намного дешевле.

Вот пара примерных аналогов:

STM32F030F4 — 48 руб.
ATmega168PA-AU — 140 руб.

Почти в три раза…

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

В сущности, да. Тут уже дело в том, что я, э-э-э, не совсем любитель. Ну а для себя в таком случае проще использовать то, с чем и так работаешь.

Написанный вручную код как правило 4 и более раз быстрее и гораздо компактнее.

Здесь есть искушение попросить какой-нибудь стоящий пример. Скажем, ваши варианты FFT на Си и на ассемблере. Или сравнение реализаций чего-нибудь в духе LU-разложения, обращения матрицы, решения СЛАУ, свертки, на худой конец.

Я бы результаты АЦП сперва через медианно-усредняющий фильтр пропустил.

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

Ну и никто не заставляет использовать именно эту фичу. Можно, скажем, с помощью циклического режима DMA складывать этак по десятку значений в память, а дальше по прерываниям half transfer/full transfer быстро их усреднять и уже тогда, в прерывании, делать вывод. Все равно экономия времени за счет того, что прерывание вызывается не после каждой выборки.

Просто правильнее.

Это не технический аргумент. :) Это, знаете ли, гуманитарии могут спокойно аргументировать, что, например, так играть Шопена, как они, «просто правильнее», потому что они так видят. :)

А у нас есть четкий критерий — объем кода. И аппаратный блок RTC с календарем его очень сокращает. Не нужен календарь? Возьмите чип без календаря! Нужен и календарь, и счетчик UNIX time? Возьмите чип с календарем и затактируйте один из счетчиков от LSE!

Проблемы ведь, на самом деле, просто нет. Каждому применению — свой чип.

преобразовать в любой формат

Вы же смотрели то видео, ссылку на которое я давал? :)

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

Они связаны с настройкой и никак не влияют на собственно функционал. Написали просто для полноты картины.
  • avatar
  • _YS_
  • 06 января 2018, 16:31
+1
причём коэффициент заполнения — это не дедтайм, его можно менять от 0 до 100/50%

Не, ну в том таймере, о котором я говорил, коэффициент заполнения, естесственно, тоже можно менять. :D Я об этом не писал как об очевидном.

Кстати защитный интервал там тоже можно настраивать по вкусу. А еще полярность выходов и много-много всего.

Правда программирование TPI, а не SPI.

Да, именно поэтому я до этих прикольных чипов пока что так и не добрался. Хотя AVRISP-mkII поддерживает его, вроде бы. А еще они больно дорогие в местных магазинах… Стоили бы они по 30 — 50 р., как серия F030, было бы интереснее.

Да, STM32 несмотря на всю свою уродливость

Здесь есть нюанс. Если вы вчитаетесь в документацию на разные серии (да хотя бы F100 и F0xx), вы сразу поймете, что это по большей части разные контроллеры. Разгадка проста — их делали разные люди. Мне рассказывали инсайдерскую информацию насчет того, что после F100 в ST просто разогнали дизайн-отдел и набрали его заново.

Так что документацию на STM32 надо читать ОЧЕНЬ внимательно. Сколько бы ни кричали представители ST и их адепты про фантастическое единство и полную взаимозаменяемость чипов всей линейки, это неправда. Серия STM32 на деле состоит из достаточно разных чипов, и это надо учитывать.

Ну и да, в некоторых местах документация не блещет прозрачностью, что есть, то есть…

Также очень большой минус — кривой и неудобный ассемблер. Без ассемблера не раскроешь мощь ядра по полной, что бы там не вопили любители ЯВУ.

Здесь, опять же, есть нюанс. Для чипов на ARM надо применять немного другую парадигму разработки. Лезть руками в тамошний ассемблер нет особого смысла уже потому, что за счет системы предвыборки команд из FLASH (ART accelerator), серьезного конвейера и out-of-order execution время выполнения команд и очередность доступа к памяти (кроме выделенных областей), вообще говоря, непредсказуемы (так что, например, писать на ассемблере Cortex-M3 протокол 1-Wire я бы не стал). Ну, если только не ставить после каждой инструкции data memory barrier.

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

Сила этих чипов — мощная периферия, которая может делать многое просто сама по себе (как, например, АЦП, автоматически проверяющий преобразованное значение на попадание в диапазон). Потому все задачи, критичные к таймингам, надо перекладывать на нее. Возвращаясь к примеру с 1-Wire — на STM32 его логично реализовывать на базе UART. Их там много, потому один вполне можно отдать под 1-Wire, и это не ударит по ресурсам так, как это было бы в AVR, скажем.

То есть идеал — настроил периферию, она сама работает, а ядро вообще выключено.

Немного другой подход, немного другая парадигма. Непривычная, да.

В DMA — реквесты фиксировано замаплены на несколько источников, и включив один источник остальные уже использовать нельзя.

Нельзя на одном канале. На других можно. Недостающее можно ремапить.

прилепить её к RTC геморно

Конкретно в STM32F051 для этой цели есть RTC_SHIFTR, который позволяет аккуратненько двигать часы с субсекундным разрешением.

Да и вообще подход с календарным RTC — отстой. В технике время — это линейно нарастающая скалярная величина, именно так с ней работать удобно и правильно.

Ну, это все же субъективно. Удобно — это как когда. Чем тащить в контроллер библиотеку, которая будет корректно обрабатывать все это (сколько десятков килобайт она займет?), проще иметь аппаратный модуль RTC с календарем…

Насколько я помню еррату

На какой чип? В errata на STM32F100 про это я ничего не нашел.

Если говорить про F0, то там ошибка совершенно смешная. Кому может понадобиться программно выключать tamper detection, если уж ее включили? Обычно в таких случаях функционал конфигурируется раз и надолго.

И ещё ломать голову как сделать это атомарно…

Ломать голову не надо. Теневое копирование уже реализовано за вас, аппаратно.

И ядро и периферия и элекртические параметры и как всё это сделано.

Ага. До сих пор ржу с их регистра установки скорости UART (по-моему, дело было с STM8S103F3). У меня только один вопрос: ПОЧЕМУ ТАК? :D Зато они дешевые.
  • avatar
  • _YS_
  • 06 января 2018, 14:06
0
Не знаю насчет наших уважаемых коллег, но, действительно, я познал различие между скоростными и «часовыми» кварцами трудным путем, ценой одного проекта-позора. :D
  • avatar
  • _YS_
  • 06 января 2018, 13:21
0
На TI1 оно заведено. Это input capture. Ну а MCO можно выбрать. Видимо, сделали потому, что могли.
  • avatar
  • _YS_
  • 05 января 2018, 22:09