Верить main.c .Рапорт более ранней версии. Да и тики таймера с PWM2 я ещё не проверил.
Помнится в Keil-е я мог без железа сэмулировать работу программы. Более того, подписав небольшую служебную программку, читающую значения с выхода и передающая их на вход АЦП, посмотреть, что же натворено на интересующем выходе. Здесь такое возможно?
Взяв за основу варианты nik182 и mixail844 родил такую структуру. Её удобство в том, что, пользуясь всего двумя параметрами ППо и n, можно играться с частотой опроса и усреднением меняя их всего в двух местах программы.
Теперь её надо правильно вписать в Куб. Думается, что это не намного труднее, чем в квадрат. Хотя для меня всё едино. Львиную долю nik182 уже сделал. А мне всё ещё точить и точить саблю. Теперь вплотную надо разбираться с Atollic. Да и Си, можно сказать, с нуля.
Непонятна конечная цель. Если АЦП пишет каждые 2 мкс, да если ещё после каждой записи как то пытаться обрабатывать полученные значения, то только вход и выход из прерывания АЦП, где собственно в режиме реального времени возможно получить текущие данные АЦП, займет 0.5 мкс. На обработку и анализ остается совсем мало времени. Буквально 100 циклов процессора. Учитывайте это при составлении тех. задания на устройство.
Непонятна конечная цель. Если АЦП пишет каждые 2 мкс, да если ещё после каждой записи как то пытаться обрабатывать полученные значения, то только вход и выход из прерывания АЦП, где собственно в режиме реального времени возможно получить текущие данные АЦП, займет 0.5 мкс. На обработку и анализ остается совсем мало времени. Буквально 100 циклов процессора. Учитывайте это при составлении тех. задания на устройство.
Перечитал несколько раз, но не смог уловить, что вас настораживает. То, что вы предложили ранее, как мне кажется, говорит о понимании. Как то я особо и не собирался делать какую либо обработку с темпом опроса АЦП, вернее мысль такая была, но вы уже мне на неё ответили и я принял ваше решение проводить обработку по оканчании всего цикла записи измерений в буфер, а потом всё по новой. Единственное, что пришло на ум так это, что не надо останавливать процесс генерации, чтобы при новом запуске избежать переходных процессов непосредственно в датчике. То есть, генератор и АЦП пусть работают постоянно, а запуск записи выборки в буфер (работа по ПДП) переодически после окончания обработки. Единственно надо засинхронизировать с каким ни будь фронтом генератора. А что касается 0,5 мкс, так это что бы цикл преобразования АЦП не разрезался фронтом генератора, то есть быть уверенным, что точка попала не на фронт.
Теперь о структуре. Всё же структура, представленная ниже более красива. В ней использовалось предложение mixail844, пост 44.
Что мне пока не ясно, так это поведение тригера. Тригер есть тригер - на значение ему наплевать, для него важна команда изменить его. В каком состоянии он может оказаться при запуске таймера? Это всегда одно и то же значение или оно может и поменяться. Вот, если его можно предварительно установить в заданное состояние, то такая схема приобретает дополнительную функциональность. То есть таким образом можно задавать фазу квадратурного сигнала для всех четырёх квадрантов. Сдаётся мне, что это можно сделать простой установкой соответствующего выхода в нужное состояние. Выскажитесь, пожалуйста, по поводу того, как можно установить тригер в нужное состояние.
Можно по окончании одного цикла делать deinit - init (см. datasheet по HAL) таймеров. Обещали, что после такой процедуры все внутренние тригеры обнулятся и жинь начнётся сначала.
Вот ещё препятствие. Для Output Compare есть варианты:
Frozen (used for Timing base)
Active Level on match
Inactive Level on match
Toggle on match
Forced Active
Forced Inactive
Toggle on match понятно это тригерный выход. Остальное только догадываюсь. Forced Active это положительный импульс, а Forced Inactive это отрицательный импульс, правда какой длительности не понятно. А что касается Active Level on match и Inactive Level on match, вообще не могу представить, что это может быть. Достойного описания на таймеры нет. Переводчик даёт какую то ерунду. Даа, чувствую, что совсем отстал от жизни. И ещё меня ввёл в ступор такой момент. Для одного таймера для разных каналов Куб допускает задание ШИМ с разными модами - выравниванием по фронту и по центру. Ну как это может быть? Я что то не понимаю или Куб не блокирует такие ситуации? Начинаю чувствовать какую то неловкость за столько вопросов, может, для кого то совсем тривиальных.
Вот ещё препятствие. Для Output Compare есть варианты:
Frozen (used for Timing base)
Active Level on match
Inactive Level on match
Toggle on match
Forced Active
Forced Inactive
Toggle on match понятно это тригерный выход. Остальное только догадываюсь. Forced Active это положительный импульс, а Forced Inactive это отрицательный импульс, правда какой длительности не понятно. А что касается Active Level on match и Inactive Level on match, вообще не могу представить, что это может быть. Достойного описания на таймеры нет. Переводчик даёт какую то ерунду. Даа, чувствую, что совсем отстал от жизни.
не волнуйстесь ,у STM хоть и хорошая документация ,но не все и всегда ясно сразу.если не понимаете как все работает в General-purpose timer cookbook (AN4776) или STM32 cross-series timer overview(AN4013),то всегда есть Referenca Manual ...хотя там тоже иногда черт ногу сломит.и еще надо "перводить " как оно должно быть в STM32CubeMx
в сети есть много примеров.кто то да разобрался с разными режимами OutputCompare,если была надобность.
Для одного таймера для разных каналов Куб допускает задание ШИМ с разными модами - выравниванием по фронту и по центру. Ну как это может быть? Я что то не понимаю или Куб не блокирует такие ситуации? Начинаю чувствовать какую то неловкость за столько вопросов, может, для кого то совсем тривиальных.
Куб далеко далеко не идеален и генерирует много оверхеда,что бы оптимизировать все надо либо писать на чистых регистрах(с обертками) либо использовать генерацию не в HAL а в LL(Low Level) drivers.
а почему должна быть блокировка ? я с таймерами в OutputCompare режиме прям плотно не работал,но кмк,это не противоречит..счетчик у таймера один а OutputCompareRegister у каждого канала свой ,могу ошибаться и тут реально баг Куба.
Для одного таймера для разных каналов Куб допускает задание ШИМ с разными модами - выравниванием по фронту и по центру. Ну как это может быть?
Такого быть не может и вы это придумали. Выравнивание задается для всего тамера целиком. Режимы, те, да, можно поканально выставлять, но режимы это не выравнивание.
mixail844 пишет:
но кмк,это не противоречит..счетчик у таймера один а OutputCompareRegister у каждого канала свой ,могу ошибаться и тут реально баг Куба.
При выравнивании по фронту, счетчик должен считать в одну сторону, при выравнивании по центру, в обе. Счетчик у таймера только один, т.ч. для разных каналов этот параметр может быть только одинаковым.
Вот ещё препятствие. Для Output Compare есть варианты:
Frozen (used for Timing base)
Active Level on match
Inactive Level on match
Toggle on match
Forced Active
Forced Inactive
Toggle on match понятно это тригерный выход. Остальное только догадываюсь. Forced Active это положительный импульс, а Forced Inactive это отрицательный импульс, правда какой длительности не понятно. А что касается Active Level on match и Inactive Level on match, вообще не могу представить, что это может быть.
да тут все просто -
Active/Inactive Level on match - при совпадении счетчика с регистром выход канала становится HIGH или LOW, соответсвенно
Toggle on match - при совпадении логический уровень инвертируется
Forced Active- Inactive - состояние выхода насильно установлено HIGH илиLOW и от таймера вообще не зависит
Для одного таймера для разных каналов Куб допускает задание ШИМ с разными модами - выравниванием по фронту и по центру. Ну как это может быть?
Такого быть не может и вы это придумали. Выравнивание задается для всего тамера целиком. Режимы, те, да, можно поканально выставлять, но режимы это не выравнивание.
Думаю, что это сообщение относится ко мне, правда заинтересовало, что такое ТС. Уверен, что вы правы, поскольку до конца не понял, что такое PWM1 PWM2 mode. Буду разбираться, но, если не сложно, растолкуйте в чём разница и тогда где и чем задаётся параметр выравнивания.
Правильно ли я понял, что блок Ouput control в режиме Toggle on match по приходу импульса со счётчика просто берёт текущее состояние выхода и его инвертирует? Тогда моё предположение в конце поста 54 верно и можно таким образом инициализировать начальную фазу меандра на этом выходе. Если же у него есть внутренняя память, которую он инвертрует и уж потом подаёт на выход, то тогда начальная установка возможно только одним значением, определяемым общим сбросом -0. А что же на самом деле?
Думаю, что это сообщение относится ко мне, правда заинтересовало, что такое ТС. Уверен, что вы правы, поскольку до конца не понял, что такое PWM1 PWM2 mode. Буду разбираться, но, если не сложно, растолкуйте в чём разница
у меня сейчас под рукой мануала нет, но в принципе PWM1 и 2 практически одно и то же, отличаются только состоянием выхода. В одном из режимов выход имеет низкий уровень, когда значение счетчика меньше регистра сравнения и высокий, когда счетчик больше регистра. А во втором режиме наоборот. Вот и вся разница.
добавка - ТС = топик-стартер, то есть тот, кто начал тему, в данном случае Вы
Если же у него есть внутренняя память, которую он инвертрует и уж потом подаёт на выход, то тогда начальная установка возможно только одним значением, определяемым общим сбросом -0. А что же на самом деле?
А на самом деле это железный автомат, который щелкает синхронно с тактовой частотой. Если сказано, что Toggle on match, то это самое Toggle произойдет ровно по тому же фронту тактовой частоты, как и match. Все растактовки есть в референсе в картинках. Надо только не лениться разглядывать.
А на самом деле это железный автомат, который щелкает синхронно с тактовой частотой. Если сказано, что Toggle on match, то это самое Toggle произойдет ровно по тому же фронту тактовой частоты, как и match. Все растактовки есть в референсе в картинках. Надо только не лениться разглядывать.
Чего чего а картинок то уж понаразглядывался. Это самое то для меня - поизучать именно картинкки и, наверно, обратили внимание, что и сам я не ленюсь их порисовать. Другое дело, что набор их не полный. Спасибо вот mixail844 дал наводку того что у меня не было AN4776, очень полезно.
То, что всё железно и происходит ровно по фронту и у меня не вызывает сомнения. Только этим для режима Toggle on match нельзя однозначно сказать - какое же значение будет на выходе при приходе фронта, но однозначно можно сказать, что оно изменит своё состояние. Меня то всё беспокоит вопрос можно ли и как сделать так, что бы в этом режиме при старте генератора на выходе были значения, заданные мной , а не по умолчению. И что бы эти значения были не сами по себе, а являлись начальными для работы режима Toggle on match.
И ещё вопрос, прямо не относящийся к теме, но всё же. Дайте, пожалуйста, ссылочки какими справочными данными пользуетесь при программировании. В первую очередь интересуют сжатые материалы.
Меня то всё беспокоит вопрос можно ли и как сделать так, что бы в этом режиме при старте генератора на выходе были значения, заданные мной , а не по умолчению. И что бы эти значения были не сами по себе, а являлись начальными для работы режима Toggle on match.
Вместо того что сидеть и рассуждать, как это вас беспокоит :) - что мешает взять и попробовать? Выходы каналов таймера - это обычные GPIO Думаю, что если задать начальное значение выхода так же, как вы хажигаете светодиод :) - это будет именно то, что вы хотите.
Меня то всё беспокоит вопрос можно ли и как сделать так, что бы в этом режиме при старте генератора на выходе были значения, заданные мной , а не по умолчению. И что бы эти значения были не сами по себе, а являлись начальными для работы режима Toggle on match.
То, какие состояния изначально, зависит от PWM Mode. Для первого режима активное состояние до совпадения, неактивное после. Для второго режима наоборот. Кроме Toggle, реакцией на совпадение может быть "001: Set channel to active level on match" и "010: Set channel to inactive level on match". Тобишь, по совпадению можно переключаться из любого режима в любой, причем, несколькими способами.
Вместо того что сидеть и рассуждать, как это вас беспокоит :) - что мешает взять и попробовать? Выходы каналов таймера - это обычные GPIO Думаю, что если задать начальное значение выхода так же, как вы хажигаете светодиод :) - это будет именно то, что вы хотите.
Да у меня самого давно руки чешуться поиграться, но, видимо, такой характер. Долго запрягаю, но быстро езжу. Да ещё накладывается то, что тропинка то ещё не протоптана. Сейчас буду учиться таким тривиальным вещам, как, например, лучше оформить отображение программы, скрыть или показать всю эту лабуду с инициализацией, разбираться в синтаксисе, заливка программы, отладка и т.д. К стате о заливке и отладке. Буду пользоваться ST-Link. Наверняка что то надо будут настроить в Кубе. Что?
Меня то всё беспокоит вопрос можно ли и как сделать так, что бы в этом режиме при старте генератора на выходе были значения, заданные мной , а не по умолчению. И что бы эти значения были не сами по себе, а являлись начальными для работы режима Toggle on match.
Можно задать любые значения для кадого вывода. Вот чуть модифицировал тот же пример, что я вам уже давал. Тут поднимаются обе аппаратные ноги таймера (14 строка), и остаются поднятыми до момента старта генерации (16 строка).
То, какие состояния изначально, зависит от PWM Mode. Для первого режима активное состояние до совпадения, неактивное после. Для второго режима наоборот. Кроме Toggle, реакцией на совпадение может быть "001: Set channel to active level on match" и "010: Set channel to inactive level on match". Тобишь, по совпадению можно переключаться из любого режима в любой, причем, несколькими способами.
a5021, спасибо. Когда я говорил о своём беспокойстве, не имел ввиду режим PWM - понял, что он мне уже не нужен. А говорил о режиме обычного компарирования.
dimax, здорово. Смотришь и душа радуется - всего 17 строчек и такая красота. Ну, вот никак не хочет банда Ардуино отпускать из своих сетей в мафию Куба и иже с ним. Опять я сильно заколебался. Если вы мне ещё покажете как засинхронизировать со сдвигом опрос АЦП (DMA) по отношению к фронтам генератора и запуск выборки по отношению, опять же, к какому из фронтов, то точно останусь у вас. Большое спасибо, что показали и утвердили в правильности моих предположений о работе Toggle on match.
Юрий48, c АЦП мне кажется вам стоит пересмотреть свои изначальные хотелки. Одним "взмахом пера", то бишь желанием ненароком не попасть на фронт меандра вы многократно усложнили себе задачу. А надо ли оно вам? Я бы просто программно "выбросил" подозрительный семпл, и делов-то. Пусть АЦП-шка строчит со своей комфортной скоростью и без привязки к таймерам. Потом разбирайте её буфер по какому-нибудь медианному алгоритму и усредняйте если надо. Думаю, что результат получится не хуже, чем тот, на который вы изначально рассчитывали..
Юрий48, c АЦП мне кажется вам стоит пересмотреть свои изначальные хотелки. Одним "взмахом пера", то бишь желанием ненароком не попасть на фронт меандра вы многократно усложнили себе задачу. А надо ли оно вам? Я бы просто программно "выбросил" подозрительный семпл, и делов-то. Пусть АЦП-шка строчит со своей комфортной скоростью и без привязки к таймерам. Потом разбирайте её буфер по какому-нибудь медианному алгоритму и усредняйте если надо. Думаю, что результат получится не хуже, чем тот, на который вы изначально рассчитывали..
Тут возникает много вопросов:
1. как понять, что точка попала на фронт?
2. А если все семплы окажутся подозрительными?
3. Если выкидывать только подозрительную точку, то тогда надо будет для каждой четверти подсчитывать количество правильных. Это, конечно, возможно но не лучший вариант.
4. Возможен и такой вариант. Выкидывать без объяснений первую и последнюю точки из четверти. Но это уж из за полной безысходности.
Да, и ещё. Поскольку я пока не представляю (по физике), что в конечном итоге получится, то очень желательно, чтобы в каждой четверти по всей выборке их было одинаковое количество и они были одинаково расставленны.
Что то упустил самое главное. Ведь обработка должна вестись по четвертям полностью аналогично синхронному фильтру. А если АЦП и генератор будут асинхронны, то тогда нужно каким то образом параллельно формировать массив импульсов синхронизации. Согласитесь, что это ....
Active/Inactive Level on match - при совпадении счетчика с регистром выход канала становится HIGH или LOW, соответсвенно
Ну, выставился он в соответствующее состояние. А для нового цикла в исходное состояние как или чем он возвращается? Речь идёт не о режиме PWM, а о режиме простого сравнения.
Вот ещё вопрос. Что то не могу понять какие значения надо задавать для предделителя, автоперезагрузки, компарирования. Имеется ввиду, что их надо или не надо уменьшать на единицу. Просто натыкался на противоречивые варианты.
Ну, выставился он в соответствующее состояние. А для нового цикла в исходное состояние как или чем он возвращается?
Что есть новый цикл? Если таймер перевести в режим idle, то ноги тотчас займут то положение, которое определено для этого статуса.
Юрий48 пишет:
Вот ещё вопрос. Что то не могу понять какие значения надо задавать для предделителя, автоперезагрузки, компарирования. Имеется ввиду, что их надо или не надо уменьшать на единицу. Просто натыкался на противоречивые варианты.
В регистрах счёт с ноля. Поэтому если нужно досчитать до 1000 то записываем 999.
Ну, выставился он в соответствующее состояние. А для нового цикла в исходное состояние как или чем он возвращается?
Что есть новый цикл? Если таймер перевести в режим idle, то ноги тотчас займут то положение, которое определено для этого статуса.
Скажем, режим компарирования. Счётчик дошёл до уровня компарирования, выход выставился, скажем, в состояние 1. дальше счётчик досчитал то уровня перезагрузки и пошёл считать по новой до уровня компарирования. Что, всё это время выход так и находится в 1?
Юрий48, да, а какие тут могут быть варианты? Переключение в рабочем порядке происходит только при совпадении регистров.
Ну да. На следующем совпадении - опять в единицу и т.д. И на данный момент в моём представлении получается, что на выходе будет всегда единица. Но это же не так. Между совпадениям должно происходить нечто, что выход опять выставляет в 0. Или это должен делать я программно?
eще вариант , можно подсчитать сколько времени берет одна конверсия АЦП (зависит от частоты его работы , от киличества сэмплов на конверсию и от выбраной резолюции .как то считал,получалось от долей микросекунд до десятков микросекунд) сохранять конверсии при помощи DMA(ПДП)в (кольцевой) буффер(можно даже double buffering организовать) и потом подсчитать(исходя из времени концерсии) номер какой конверсии совпадал с фронтом таймера .double buffering для того что бы с одним работать а в другой при помощи DMA конвертировать
eще вариант , можно подсчитать сколько времени берет одна конверсия АЦП (зависит от частоты его работы , от киличества сэмплов на конверсию и от выбраной резолюции .как то считал,получалось от долей микросекунд до десятков микросекунд) сохранять конверсии при помощи DMA(ПДП)в (кольцевой) буффер(можно даже double buffering организовать) и потом подсчитать(исходя из времени концерсии) номер какой конверсии совпадал с фронтом таймера .double buffering для того что бы с одним работать а в другой при помощи DMA конвертировать
Double buffering хороший вариант и я о нём тоже думал, но не актуален. Может, со временем он и будет воплощён. Хотя, если о нём будет полное понимание, то почему же и нет. На счёт подсчёта номера совпадения конверсии - не прочувствовал. Я то планирую сделать так. Генератор и АЦП молотят постоянно. А запись в ПДП-буфер с перерывами на обработку и индикацию. При чём возобновление записи в ПДП строго засинхронизировать с одним из фронтов генератора. Длину буфера брать равной требуемому усреднению помноженному на количество точек, приходящихся на период генератора. В соответствии с моей картинкой это У*4*n, где У - количество усреднений, а n - количество точек (по вашему конверсия) на четверть периода. Тогда обработка становится совсем прозрачной и значительно упрощается.
ну а если тогда сделать срабатывание DMA по генерации события одного из таймеров(можно внутрисхемно настроить таймер так чтобы он генерировал событие для DMA которое в свою очередь начнет процесс конверсии), и подобрать время конверсии так что бы последующие ни совпадали с фронтом другого таймера ? тогда конверсия начнется вместе с одним из таймеров и продлиться какое то время,таймер уже переключит вывод.
ну а если тогда сделать срабатывание DMA по генерации события одного из таймеров(можно внутрисхемно настроить таймер так чтобы он генерировал событие для DMA которое в свою очередь начнет процесс конверсии),
Это понятно и это есть хорошо.
mixail844 пишет:
и подобрать время конверсии так что бы последующие ни совпадали с фронтом другого таймера ? тогда конверсия начнется вместе с одним из таймеров и продлиться какое то время,таймер уже переключит вывод.
А с этим не понтно. Чего подбирать время конверсии? Задать его изначально, меньше времени опроса (точками) АЦП. А сам опрос тоже постоянный, такой, что бы на период генератора априходилось 4*n точек.
Ну да. На следующем совпадении - опять в единицу и т.д. И на данный момент в моём представлении получается, что на выходе будет всегда единица. Но это же не так. Между совпадениям должно происходить нечто, что выход опять выставляет в 0. Или это должен делать я программно?
Мне кажется мы всё время говорили о режиме "Toggle on compare match" Разве само название не говорит о том, что при каждом совпадении выход переключиться на противоположное значение? Юрий, скажу прямо -сомневаюсь что у вас что-то выйдет. Вы уже строите планы по увязке всей периферии в некую систему, но о принципах работы и особянностях программирования этой периферии не знаете ничего. Как же можно что-то планировать без знания "железа", с которым будете работать?
Мне кажется мы всё время говорили о режиме "Toggle on compare match" Разве само название не говорит о том, что при каждом совпадении выход переключиться на противоположное значение?
Да ладно, поскольку я так и не понял до конца этот режим, то и не буду его использовать. То же самое могу получить, используя ШИМ.
dimax пишет:
Юрий, скажу прямо -сомневаюсь что у вас что-то выйдет. Вы уже строите планы по увязке всей периферии в некую систему, но о принципах работы и особянностях программирования этой периферии не знаете ничего. Как же можно что-то планировать без знания "железа", с которым будете работать?
Вот, вы мне скажите. Постановка задачи вам ясна, реализовать её на этом чипе на аппаратном уровне можно? Если да, то мало по малу это будет сделано. Если же нет, то подскажите, пожалуйста, где, что не так.
Да ладно, поскольку я так и не понял до конца этот режим, то и не буду его использовать. То же самое могу получить, используя ШИМ.
И это печально, потому что режим PWM тут совершеннно ни к чему. Дело ваше конечно, но мне кажется имея рабочий пример гораздо проще начать писать свою программу, чем не имея такого примера. А пример у вас есть, вам нужно всего лишь разобрать что делает каждая из 17 строк.
Юрий48 пишет:
Вот, вы мне скажите. Постановка задачи вам ясна, реализовать её на этом чипе на аппаратном уровне можно? Если да, то мало по малу это будет сделано. Если же нет, то подскажите, пожалуйста, где, что не так.
Можно, особенно если вы не будете себе усложнять задачу. С теми планами что у вас сейчас у вас могут уйти многие месяцы на написание и отладку этой программы.
И это печально, потому что режим PWM тут совершеннно ни к чему. Дело ваше конечно, но мне кажется имея рабочий пример гораздо проще начать писать свою программу, чем не имея такого примера. А пример у вас есть, вам нужно всего лишь разобрать что делает каждая из 17 строк.
Я тоже считаю, что печально, и можно обойтись без режима PWM. Но уверяю вас, что, если бы я увидел, что этот режим наносит ущерб чему ни будь, например, быстродействию, то я бы добил бы до конца вариант с компарированием. А мне печально то, что я не смог донести, что мне не понятно и слил продолжение дискуссии по этому вопросу. С примерами как раз никаких проблем нет, Да, работает, но ответа на мой вопрос не даёт.
dimax пишет:
Можно, особенно если вы не будете себе усложнять задачу. С теми планами что у вас сейчас у вас могут уйти многие месяцы на написание и отладку этой программы.
Собственно вторая версия. Оказалось что HAL не имеет возможности одновременного запуска таймеров. Команда поднятия канала таймера этот таймер и запускает. Пришлось использовать LL драйвера куба для таймера. И ещё засада оказалась с тем что центрированный PWM требует на один тик больше. Результат порадовал. LL драйвера это практически CMSIS обёрнутый в буквы. Местами даже удобнее STL. При этом генерится кубом.
И результат работы. Осцилограф двухлучевой, поэтому сначала два канала со сдвигом 90 градусов, потом соотношение старта АЦП - по восходящим фронтам - к фронту канала. На третьей фото видно что цифрует точно за 1мкс до и 1 мкс после фронта.
nik182, Спасибо огромное. Со второй картинкой не понятно. На вид это просто растянутая первая картинка и по этому не соответствует тому, что сказано в тексте. Третья картинка заставила меня задуматься. Я, когда в начале описывал задачу, представлял, что на фронт генератора не должен попадать цикл преобразования АЦП. Поэтому думал, что для гарантии запуск АЦП должен быть сдвинут не просто на 1 мкс, а на 0,5 мкс с тем что бы фронт генератора пришёлся не на отрицательный фронт запуска АЦП, а на середину низкого уровня. Если цикл преобразования АЦП больше 1 мкс, то замер этой точки исказится. Если равно, то тут трудно сказать что либо определённое, может, и не страшно. Сейчас как раз разбираюсь с АЦП и подсчётом времени преобразования. Ваше решение беру за основу, буду работать с ним и, если хватит терпения, то попробую перейти к варианту из поста №54, который мне очень по душе. Код программы вы выложили, за что ещё раз огромное спасибо. И, если вам не надоели "спасибо", то скинте ещё, пожалуйста, файл для Куба.
АЦП сейчас работае 1.5 цикла или 0.1 мкс. Это не та цифра из за которой нужно переживать.
Понятно. Я то думал, что время пробразования 1 мкс. А как же так, везде встречал, что мнимальное время преобразования для этого АЦП 1 мкс, а тут 0,1. Как это понимать?
АЦП сейчас работае 1.5 цикла или 0.1 мкс. Это не та цифра из за которой нужно переживать.
Подразобрался. Время преобразования составляет 12,5 циклов тактирования, а минимальное время выборки, выраженное в тактах, определяется как сумма времени преобразования (12,5) и заданной паузой, в данном случае 1,5. 12,5+1,5 =14 тактов. То есть, даже, если принять во внимание только преобразование (12,5) без паузы, то его время при частоте тактирования 12 мГц будет чуть больше 1 мкс, что не есть хорошо.
В кубе при настройке АЦП можно выбрать количество циклов на преобразование. Минимальное 1.5 , максимальное 239.5 - при цикле 12МГц или 0.08333мкс. Множим и получаем что преобразование может быть до 20 мкс. Зато выходное сопротивление источника сигнала при этом может быть большим. Кроме того после преобразования полученный результат нужно передать в выходной регистр, а цепи АЦП подготовить к следующему преобразованию. На это тоже уходит время и полный цикл от одного преобразования до другого на может быть меньше 1 мкс. Больше может. Всё это описано в datasheet.
В кубе при настройке АЦП можно выбрать количество циклов на преобразование. Минимальное 1.5 , максимальное 239.5 - при цикле 12МГц или 0.08333мкс. Множим и получаем что преобразование может быть до 20 мкс.
Указанное время -- это не время преобразования, а время семплирования -- время, которое отводится на заряд емкости УВХ. Для расчета полного времени преобразования к времени семплирования надо добавить 12.5 тактов цифрования.
Цитата:
Кроме того после преобразования полученный результат нужно передать в выходной регистр, а цепи АЦП подготовить к следующему преобразованию. На это тоже уходит время и полный цикл от одного преобразования до другого на может быть меньше 1 мкс.
То есть, даже, если принять во внимание только преобразование (12,5) без паузы, то его время при частоте тактирования 12 мГц будет чуть больше 1 мкс, что не есть хорошо.
Вот именно. Вообще в datasheet указывается что максимальная частота внешнего тактирования не более 823кГц при самплинге АЦП 14 МГц. У нас 12МГц - на 1 мкс для одного АЦП это ни как не тянет. И то эти цифры идут под грифом: параметры дизайна, в реальных устройствах не гарантируется.
Вот именно. Вообще в datasheet указывается что максимальная частота внешнего тактирования не более 823кГц при самплинге АЦП 14 МГц. У нас 12МГц - на 1 мкс для одного АЦП это ни как не тянет. И то эти цифры идут под грифом: параметры дизайна, в реальных устройствах не гарантируется.
Эти моменты я чувствую и держу под вниманием и для реальных условий их скорректирую. Главное что бы база была правильной. В свзи с этим проверте пожалуйста код, представленный в посте 92. Там что то в конце на мой взгляд не так, поскольку после генерации в Кубе строки 459-466 пропадают. Всё, что дописано перед этим нормально. Предполагаю по не опытности, что при удалении чего то ненужного зацепили строчку /* USER CODE END 4 */
Верить main.c .Рапорт более ранней версии. Да и тики таймера с PWM2 я ещё не проверил.
Помнится в Keil-е я мог без железа сэмулировать работу программы. Более того, подписав небольшую служебную программку, читающую значения с выхода и передающая их на вход АЦП, посмотреть, что же натворено на интересующем выходе. Здесь такое возможно?
Взяв за основу варианты nik182 и mixail844 родил такую структуру. Её удобство в том, что, пользуясь всего двумя параметрами ППо и n, можно играться с частотой опроса и усреднением меняя их всего в двух местах программы.
Теперь её надо правильно вписать в Куб. Думается, что это не намного труднее, чем в квадрат. Хотя для меня всё едино. Львиную долю nik182 уже сделал. А мне всё ещё точить и точить саблю. Теперь вплотную надо разбираться с Atollic. Да и Си, можно сказать, с нуля.
Непонятна конечная цель. Если АЦП пишет каждые 2 мкс, да если ещё после каждой записи как то пытаться обрабатывать полученные значения, то только вход и выход из прерывания АЦП, где собственно в режиме реального времени возможно получить текущие данные АЦП, займет 0.5 мкс. На обработку и анализ остается совсем мало времени. Буквально 100 циклов процессора. Учитывайте это при составлении тех. задания на устройство.
Непонятна конечная цель. Если АЦП пишет каждые 2 мкс, да если ещё после каждой записи как то пытаться обрабатывать полученные значения, то только вход и выход из прерывания АЦП, где собственно в режиме реального времени возможно получить текущие данные АЦП, займет 0.5 мкс. На обработку и анализ остается совсем мало времени. Буквально 100 циклов процессора. Учитывайте это при составлении тех. задания на устройство.
Перечитал несколько раз, но не смог уловить, что вас настораживает. То, что вы предложили ранее, как мне кажется, говорит о понимании. Как то я особо и не собирался делать какую либо обработку с темпом опроса АЦП, вернее мысль такая была, но вы уже мне на неё ответили и я принял ваше решение проводить обработку по оканчании всего цикла записи измерений в буфер, а потом всё по новой. Единственное, что пришло на ум так это, что не надо останавливать процесс генерации, чтобы при новом запуске избежать переходных процессов непосредственно в датчике. То есть, генератор и АЦП пусть работают постоянно, а запуск записи выборки в буфер (работа по ПДП) переодически после окончания обработки. Единственно надо засинхронизировать с каким ни будь фронтом генератора. А что касается 0,5 мкс, так это что бы цикл преобразования АЦП не разрезался фронтом генератора, то есть быть уверенным, что точка попала не на фронт.
Теперь о структуре. Всё же структура, представленная ниже более красива. В ней использовалось предложение mixail844, пост 44.
Что мне пока не ясно, так это поведение тригера. Тригер есть тригер - на значение ему наплевать, для него важна команда изменить его. В каком состоянии он может оказаться при запуске таймера? Это всегда одно и то же значение или оно может и поменяться. Вот, если его можно предварительно установить в заданное состояние, то такая схема приобретает дополнительную функциональность. То есть таким образом можно задавать фазу квадратурного сигнала для всех четырёх квадрантов. Сдаётся мне, что это можно сделать простой установкой соответствующего выхода в нужное состояние. Выскажитесь, пожалуйста, по поводу того, как можно установить тригер в нужное состояние.
Можно по окончании одного цикла делать deinit - init (см. datasheet по HAL) таймеров. Обещали, что после такой процедуры все внутренние тригеры обнулятся и жинь начнётся сначала.
Вот ещё препятствие. Для Output Compare есть варианты:
Frozen (used for Timing base)
Active Level on match
Inactive Level on match
Toggle on match
Forced Active
Forced Inactive
Toggle on match понятно это тригерный выход. Остальное только догадываюсь. Forced Active это положительный импульс, а Forced Inactive это отрицательный импульс, правда какой длительности не понятно. А что касается Active Level on match и Inactive Level on match, вообще не могу представить, что это может быть. Достойного описания на таймеры нет. Переводчик даёт какую то ерунду. Даа, чувствую, что совсем отстал от жизни. И ещё меня ввёл в ступор такой момент. Для одного таймера для разных каналов Куб допускает задание ШИМ с разными модами - выравниванием по фронту и по центру. Ну как это может быть? Я что то не понимаю или Куб не блокирует такие ситуации? Начинаю чувствовать какую то неловкость за столько вопросов, может, для кого то совсем тривиальных.
Вот ещё препятствие. Для Output Compare есть варианты:
Frozen (used for Timing base)
Active Level on match
Inactive Level on match
Toggle on match
Forced Active
Forced Inactive
Toggle on match понятно это тригерный выход. Остальное только догадываюсь. Forced Active это положительный импульс, а Forced Inactive это отрицательный импульс, правда какой длительности не понятно. А что касается Active Level on match и Inactive Level on match, вообще не могу представить, что это может быть. Достойного описания на таймеры нет. Переводчик даёт какую то ерунду. Даа, чувствую, что совсем отстал от жизни.
не волнуйстесь ,у STM хоть и хорошая документация ,но не все и всегда ясно сразу.если не понимаете как все работает в General-purpose timer cookbook (AN4776) или STM32 cross-series timer overview(AN4013),то всегда есть Referenca Manual ...хотя там тоже иногда черт ногу сломит.и еще надо "перводить " как оно должно быть в STM32CubeMx
в сети есть много примеров.кто то да разобрался с разными режимами OutputCompare,если была надобность.
Для одного таймера для разных каналов Куб допускает задание ШИМ с разными модами - выравниванием по фронту и по центру. Ну как это может быть? Я что то не понимаю или Куб не блокирует такие ситуации? Начинаю чувствовать какую то неловкость за столько вопросов, может, для кого то совсем тривиальных.
Куб далеко далеко не идеален и генерирует много оверхеда,что бы оптимизировать все надо либо писать на чистых регистрах(с обертками) либо использовать генерацию не в HAL а в LL(Low Level) drivers.
а почему должна быть блокировка ? я с таймерами в OutputCompare режиме прям плотно не работал,но кмк,это не противоречит..счетчик у таймера один а OutputCompareRegister у каждого канала свой ,могу ошибаться и тут реально баг Куба.
Такого быть не может и вы это придумали. Выравнивание задается для всего тамера целиком. Режимы, те, да, можно поканально выставлять, но режимы это не выравнивание.
При выравнивании по фронту, счетчик должен считать в одну сторону, при выравнивании по центру, в обе. Счетчик у таймера только один, т.ч. для разных каналов этот параметр может быть только одинаковым.
Вот ещё препятствие. Для Output Compare есть варианты:
Frozen (used for Timing base)
Active Level on match
Inactive Level on match
Toggle on match
Forced Active
Forced Inactive
Toggle on match понятно это тригерный выход. Остальное только догадываюсь. Forced Active это положительный импульс, а Forced Inactive это отрицательный импульс, правда какой длительности не понятно. А что касается Active Level on match и Inactive Level on match, вообще не могу представить, что это может быть.
да тут все просто -
Active/Inactive Level on match - при совпадении счетчика с регистром выход канала становится HIGH или LOW, соответсвенно
Toggle on match - при совпадении логический уровень инвертируется
Forced Active- Inactive - состояние выхода насильно установлено HIGH илиLOW и от таймера вообще не зависит
Такого быть не может и вы это придумали. Выравнивание задается для всего тамера целиком. Режимы, те, да, можно поканально выставлять, но режимы это не выравнивание.
я думаю ТС путает выравнивание и PWM1 PWM2 mode
Думаю, что это сообщение относится ко мне, правда заинтересовало, что такое ТС. Уверен, что вы правы, поскольку до конца не понял, что такое PWM1 PWM2 mode. Буду разбираться, но, если не сложно, растолкуйте в чём разница и тогда где и чем задаётся параметр выравнивания.
Правильно ли я понял, что блок Ouput control в режиме Toggle on match по приходу импульса со счётчика просто берёт текущее состояние выхода и его инвертирует? Тогда моё предположение в конце поста 54 верно и можно таким образом инициализировать начальную фазу меандра на этом выходе. Если же у него есть внутренняя память, которую он инвертрует и уж потом подаёт на выход, то тогда начальная установка возможно только одним значением, определяемым общим сбросом -0. А что же на самом деле?
Думаю, что это сообщение относится ко мне, правда заинтересовало, что такое ТС. Уверен, что вы правы, поскольку до конца не понял, что такое PWM1 PWM2 mode. Буду разбираться, но, если не сложно, растолкуйте в чём разница
у меня сейчас под рукой мануала нет, но в принципе PWM1 и 2 практически одно и то же, отличаются только состоянием выхода. В одном из режимов выход имеет низкий уровень, когда значение счетчика меньше регистра сравнения и высокий, когда счетчик больше регистра. А во втором режиме наоборот. Вот и вся разница.
добавка - ТС = топик-стартер, то есть тот, кто начал тему, в данном случае Вы
А на самом деле это железный автомат, который щелкает синхронно с тактовой частотой. Если сказано, что Toggle on match, то это самое Toggle произойдет ровно по тому же фронту тактовой частоты, как и match. Все растактовки есть в референсе в картинках. Надо только не лениться разглядывать.
Чего чего а картинок то уж понаразглядывался. Это самое то для меня - поизучать именно картинкки и, наверно, обратили внимание, что и сам я не ленюсь их порисовать. Другое дело, что набор их не полный. Спасибо вот mixail844 дал наводку того что у меня не было AN4776, очень полезно.
То, что всё железно и происходит ровно по фронту и у меня не вызывает сомнения. Только этим для режима Toggle on match нельзя однозначно сказать - какое же значение будет на выходе при приходе фронта, но однозначно можно сказать, что оно изменит своё состояние. Меня то всё беспокоит вопрос можно ли и как сделать так, что бы в этом режиме при старте генератора на выходе были значения, заданные мной , а не по умолчению. И что бы эти значения были не сами по себе, а являлись начальными для работы режима Toggle on match.
И ещё вопрос, прямо не относящийся к теме, но всё же. Дайте, пожалуйста, ссылочки какими справочными данными пользуетесь при программировании. В первую очередь интересуют сжатые материалы.
Меня то всё беспокоит вопрос можно ли и как сделать так, что бы в этом режиме при старте генератора на выходе были значения, заданные мной , а не по умолчению. И что бы эти значения были не сами по себе, а являлись начальными для работы режима Toggle on match.
Вместо того что сидеть и рассуждать, как это вас беспокоит :) - что мешает взять и попробовать? Выходы каналов таймера - это обычные GPIO Думаю, что если задать начальное значение выхода так же, как вы хажигаете светодиод :) - это будет именно то, что вы хотите.
То, какие состояния изначально, зависит от PWM Mode. Для первого режима активное состояние до совпадения, неактивное после. Для второго режима наоборот. Кроме Toggle, реакцией на совпадение может быть "001: Set channel to active level on match" и "010: Set channel to inactive level on match". Тобишь, по совпадению можно переключаться из любого режима в любой, причем, несколькими способами.
Вместо того что сидеть и рассуждать, как это вас беспокоит :) - что мешает взять и попробовать? Выходы каналов таймера - это обычные GPIO Думаю, что если задать начальное значение выхода так же, как вы хажигаете светодиод :) - это будет именно то, что вы хотите.
Да у меня самого давно руки чешуться поиграться, но, видимо, такой характер. Долго запрягаю, но быстро езжу. Да ещё накладывается то, что тропинка то ещё не протоптана. Сейчас буду учиться таким тривиальным вещам, как, например, лучше оформить отображение программы, скрыть или показать всю эту лабуду с инициализацией, разбираться в синтаксисе, заливка программы, отладка и т.д. К стате о заливке и отладке. Буду пользоваться ST-Link. Наверняка что то надо будут настроить в Кубе. Что?
Меня то всё беспокоит вопрос можно ли и как сделать так, что бы в этом режиме при старте генератора на выходе были значения, заданные мной , а не по умолчению. И что бы эти значения были не сами по себе, а являлись начальными для работы режима Toggle on match.
Можно задать любые значения для кадого вывода. Вот чуть модифицировал тот же пример, что я вам уже давал. Тут поднимаются обе аппаратные ноги таймера (14 строка), и остаются поднятыми до момента старта генерации (16 строка).
Захватил осциллом момент старта генерации:
a5021, спасибо. Когда я говорил о своём беспокойстве, не имел ввиду режим PWM - понял, что он мне уже не нужен. А говорил о режиме обычного компарирования.
Буду пользоваться ST-Link. Наверняка что то надо будут настроить в Кубе. Что?
вкладка SYS->Debug:Serial Wire (Serial Wire вроде как всеми ST-Link'ами потдерживаються и китайскими клонами и оригинальными)
со-но в Atollic выбрать в Configure Debug -> debugger-> Debug Probe :ST-Link
dimax, здорово. Смотришь и душа радуется - всего 17 строчек и такая красота. Ну, вот никак не хочет банда Ардуино отпускать из своих сетей в мафию Куба и иже с ним. Опять я сильно заколебался. Если вы мне ещё покажете как засинхронизировать со сдвигом опрос АЦП (DMA) по отношению к фронтам генератора и запуск выборки по отношению, опять же, к какому из фронтов, то точно останусь у вас. Большое спасибо, что показали и утвердили в правильности моих предположений о работе Toggle on match.
Юрий48, c АЦП мне кажется вам стоит пересмотреть свои изначальные хотелки. Одним "взмахом пера", то бишь желанием ненароком не попасть на фронт меандра вы многократно усложнили себе задачу. А надо ли оно вам? Я бы просто программно "выбросил" подозрительный семпл, и делов-то. Пусть АЦП-шка строчит со своей комфортной скоростью и без привязки к таймерам. Потом разбирайте её буфер по какому-нибудь медианному алгоритму и усредняйте если надо. Думаю, что результат получится не хуже, чем тот, на который вы изначально рассчитывали..
И не забываем, что блоков АЦП там два. Они умеют работать совместно и полностью автономно каждый.
Юрий48, c АЦП мне кажется вам стоит пересмотреть свои изначальные хотелки. Одним "взмахом пера", то бишь желанием ненароком не попасть на фронт меандра вы многократно усложнили себе задачу. А надо ли оно вам? Я бы просто программно "выбросил" подозрительный семпл, и делов-то. Пусть АЦП-шка строчит со своей комфортной скоростью и без привязки к таймерам. Потом разбирайте её буфер по какому-нибудь медианному алгоритму и усредняйте если надо. Думаю, что результат получится не хуже, чем тот, на который вы изначально рассчитывали..
Тут возникает много вопросов:
1. как понять, что точка попала на фронт?
2. А если все семплы окажутся подозрительными?
3. Если выкидывать только подозрительную точку, то тогда надо будет для каждой четверти подсчитывать количество правильных. Это, конечно, возможно но не лучший вариант.
4. Возможен и такой вариант. Выкидывать без объяснений первую и последнюю точки из четверти. Но это уж из за полной безысходности.
Да, и ещё. Поскольку я пока не представляю (по физике), что в конечном итоге получится, то очень желательно, чтобы в каждой четверти по всей выборке их было одинаковое количество и они были одинаково расставленны.
Что то упустил самое главное. Ведь обработка должна вестись по четвертям полностью аналогично синхронному фильтру. А если АЦП и генератор будут асинхронны, то тогда нужно каким то образом параллельно формировать массив импульсов синхронизации. Согласитесь, что это ....
Active/Inactive Level on match - при совпадении счетчика с регистром выход канала становится HIGH или LOW, соответсвенно
Ну, выставился он в соответствующее состояние. А для нового цикла в исходное состояние как или чем он возвращается? Речь идёт не о режиме PWM, а о режиме простого сравнения.
Вот ещё вопрос. Что то не могу понять какие значения надо задавать для предделителя, автоперезагрузки, компарирования. Имеется ввиду, что их надо или не надо уменьшать на единицу. Просто натыкался на противоречивые варианты.
Ну, выставился он в соответствующее состояние. А для нового цикла в исходное состояние как или чем он возвращается?
Что есть новый цикл? Если таймер перевести в режим idle, то ноги тотчас займут то положение, которое определено для этого статуса.
Вот ещё вопрос. Что то не могу понять какие значения надо задавать для предделителя, автоперезагрузки, компарирования. Имеется ввиду, что их надо или не надо уменьшать на единицу. Просто натыкался на противоречивые варианты.
В регистрах счёт с ноля. Поэтому если нужно досчитать до 1000 то записываем 999.
Ну, выставился он в соответствующее состояние. А для нового цикла в исходное состояние как или чем он возвращается?
Что есть новый цикл? Если таймер перевести в режим idle, то ноги тотчас займут то положение, которое определено для этого статуса.
Скажем, режим компарирования. Счётчик дошёл до уровня компарирования, выход выставился, скажем, в состояние 1. дальше счётчик досчитал то уровня перезагрузки и пошёл считать по новой до уровня компарирования. Что, всё это время выход так и находится в 1?
Юрий48, да, а какие тут могут быть варианты? Переключение в рабочем порядке происходит только при совпадении регистров.
Юрий48, да, а какие тут могут быть варианты? Переключение в рабочем порядке происходит только при совпадении регистров.
Ну да. На следующем совпадении - опять в единицу и т.д. И на данный момент в моём представлении получается, что на выходе будет всегда единица. Но это же не так. Между совпадениям должно происходить нечто, что выход опять выставляет в 0. Или это должен делать я программно?
Юрий48 ,
eще вариант , можно подсчитать сколько времени берет одна конверсия АЦП (зависит от частоты его работы , от киличества сэмплов на конверсию и от выбраной резолюции .как то считал,получалось от долей микросекунд до десятков микросекунд) сохранять конверсии при помощи DMA(ПДП)в (кольцевой) буффер(можно даже double buffering организовать) и потом подсчитать(исходя из времени концерсии) номер какой конверсии совпадал с фронтом таймера .double buffering для того что бы с одним работать а в другой при помощи DMA конвертировать
Юрий48 ,
eще вариант , можно подсчитать сколько времени берет одна конверсия АЦП (зависит от частоты его работы , от киличества сэмплов на конверсию и от выбраной резолюции .как то считал,получалось от долей микросекунд до десятков микросекунд) сохранять конверсии при помощи DMA(ПДП)в (кольцевой) буффер(можно даже double buffering организовать) и потом подсчитать(исходя из времени концерсии) номер какой конверсии совпадал с фронтом таймера .double buffering для того что бы с одним работать а в другой при помощи DMA конвертировать
Double buffering хороший вариант и я о нём тоже думал, но не актуален. Может, со временем он и будет воплощён. Хотя, если о нём будет полное понимание, то почему же и нет. На счёт подсчёта номера совпадения конверсии - не прочувствовал. Я то планирую сделать так. Генератор и АЦП молотят постоянно. А запись в ПДП-буфер с перерывами на обработку и индикацию. При чём возобновление записи в ПДП строго засинхронизировать с одним из фронтов генератора. Длину буфера брать равной требуемому усреднению помноженному на количество точек, приходящихся на период генератора. В соответствии с моей картинкой это У*4*n, где У - количество усреднений, а n - количество точек (по вашему конверсия) на четверть периода. Тогда обработка становится совсем прозрачной и значительно упрощается.
ну а если тогда сделать срабатывание DMA по генерации события одного из таймеров(можно внутрисхемно настроить таймер так чтобы он генерировал событие для DMA которое в свою очередь начнет процесс конверсии), и подобрать время конверсии так что бы последующие ни совпадали с фронтом другого таймера ? тогда конверсия начнется вместе с одним из таймеров и продлиться какое то время,таймер уже переключит вывод.
ну а если тогда сделать срабатывание DMA по генерации события одного из таймеров(можно внутрисхемно настроить таймер так чтобы он генерировал событие для DMA которое в свою очередь начнет процесс конверсии),
Это понятно и это есть хорошо.
А с этим не понтно. Чего подбирать время конверсии? Задать его изначально, меньше времени опроса (точками) АЦП. А сам опрос тоже постоянный, такой, что бы на период генератора априходилось 4*n точек.
Время преобразования не удастся задавать произвольным образом. Там есть ряд ограничений, которые придется учитывать.
Ну да. На следующем совпадении - опять в единицу и т.д. И на данный момент в моём представлении получается, что на выходе будет всегда единица. Но это же не так. Между совпадениям должно происходить нечто, что выход опять выставляет в 0. Или это должен делать я программно?
Мне кажется мы всё время говорили о режиме "Toggle on compare match" Разве само название не говорит о том, что при каждом совпадении выход переключиться на противоположное значение? Юрий, скажу прямо -сомневаюсь что у вас что-то выйдет. Вы уже строите планы по увязке всей периферии в некую систему, но о принципах работы и особянностях программирования этой периферии не знаете ничего. Как же можно что-то планировать без знания "железа", с которым будете работать?
Да ладно, поскольку я так и не понял до конца этот режим, то и не буду его использовать. То же самое могу получить, используя ШИМ.
Юрий, скажу прямо -сомневаюсь что у вас что-то выйдет. Вы уже строите планы по увязке всей периферии в некую систему, но о принципах работы и особянностях программирования этой периферии не знаете ничего. Как же можно что-то планировать без знания "железа", с которым будете работать?
Вот, вы мне скажите. Постановка задачи вам ясна, реализовать её на этом чипе на аппаратном уровне можно? Если да, то мало по малу это будет сделано. Если же нет, то подскажите, пожалуйста, где, что не так.
Да ладно, поскольку я так и не понял до конца этот режим, то и не буду его использовать. То же самое могу получить, используя ШИМ.
И это печально, потому что режим PWM тут совершеннно ни к чему. Дело ваше конечно, но мне кажется имея рабочий пример гораздо проще начать писать свою программу, чем не имея такого примера. А пример у вас есть, вам нужно всего лишь разобрать что делает каждая из 17 строк.
Вот, вы мне скажите. Постановка задачи вам ясна, реализовать её на этом чипе на аппаратном уровне можно? Если да, то мало по малу это будет сделано. Если же нет, то подскажите, пожалуйста, где, что не так.
Можно, особенно если вы не будете себе усложнять задачу. С теми планами что у вас сейчас у вас могут уйти многие месяцы на написание и отладку этой программы.
И это печально, потому что режим PWM тут совершеннно ни к чему. Дело ваше конечно, но мне кажется имея рабочий пример гораздо проще начать писать свою программу, чем не имея такого примера. А пример у вас есть, вам нужно всего лишь разобрать что делает каждая из 17 строк.
Я тоже считаю, что печально, и можно обойтись без режима PWM. Но уверяю вас, что, если бы я увидел, что этот режим наносит ущерб чему ни будь, например, быстродействию, то я бы добил бы до конца вариант с компарированием. А мне печально то, что я не смог донести, что мне не понятно и слил продолжение дискуссии по этому вопросу. С примерами как раз никаких проблем нет, Да, работает, но ответа на мой вопрос не даёт.
Можно, особенно если вы не будете себе усложнять задачу. С теми планами что у вас сейчас у вас могут уйти многие месяцы на написание и отладку этой программы.
Вот и хорошо, что можно.
Собственно вторая версия. Оказалось что HAL не имеет возможности одновременного запуска таймеров. Команда поднятия канала таймера этот таймер и запускает. Пришлось использовать LL драйвера куба для таймера. И ещё засада оказалась с тем что центрированный PWM требует на один тик больше. Результат порадовал. LL драйвера это практически CMSIS обёрнутый в буквы. Местами даже удобнее STL. При этом генерится кубом.
И результат работы. Осцилограф двухлучевой, поэтому сначала два канала со сдвигом 90 градусов, потом соотношение старта АЦП - по восходящим фронтам - к фронту канала. На третьей фото видно что цифрует точно за 1мкс до и 1 мкс после фронта.
nik182, Спасибо огромное. Со второй картинкой не понятно. На вид это просто растянутая первая картинка и по этому не соответствует тому, что сказано в тексте. Третья картинка заставила меня задуматься. Я, когда в начале описывал задачу, представлял, что на фронт генератора не должен попадать цикл преобразования АЦП. Поэтому думал, что для гарантии запуск АЦП должен быть сдвинут не просто на 1 мкс, а на 0,5 мкс с тем что бы фронт генератора пришёлся не на отрицательный фронт запуска АЦП, а на середину низкого уровня. Если цикл преобразования АЦП больше 1 мкс, то замер этой точки исказится. Если равно, то тут трудно сказать что либо определённое, может, и не страшно. Сейчас как раз разбираюсь с АЦП и подсчётом времени преобразования. Ваше решение беру за основу, буду работать с ним и, если хватит терпения, то попробую перейти к варианту из поста №54, который мне очень по душе. Код программы вы выложили, за что ещё раз огромное спасибо. И, если вам не надоели "спасибо", то скинте ещё, пожалуйста, файл для Куба.
АЦП сейчас работае 1.5 цикла или 0.1 мкс. Это не та цифра из за которой нужно переживать.
Понятно. Я то думал, что время пробразования 1 мкс. А как же так, везде встречал, что мнимальное время преобразования для этого АЦП 1 мкс, а тут 0,1. Как это понимать?
Подразобрался. Время преобразования составляет 12,5 циклов тактирования, а минимальное время выборки, выраженное в тактах, определяется как сумма времени преобразования (12,5) и заданной паузой, в данном случае 1,5. 12,5+1,5 =14 тактов. То есть, даже, если принять во внимание только преобразование (12,5) без паузы, то его время при частоте тактирования 12 мГц будет чуть больше 1 мкс, что не есть хорошо.
Файл timers.ioc
В кубе при настройке АЦП можно выбрать количество циклов на преобразование. Минимальное 1.5 , максимальное 239.5 - при цикле 12МГц или 0.08333мкс. Множим и получаем что преобразование может быть до 20 мкс. Зато выходное сопротивление источника сигнала при этом может быть большим. Кроме того после преобразования полученный результат нужно передать в выходной регистр, а цепи АЦП подготовить к следующему преобразованию. На это тоже уходит время и полный цикл от одного преобразования до другого на может быть меньше 1 мкс. Больше может. Всё это описано в datasheet.
В кубе при настройке АЦП можно выбрать количество циклов на преобразование. Минимальное 1.5 , максимальное 239.5 - при цикле 12МГц или 0.08333мкс. Множим и получаем что преобразование может быть до 20 мкс.
Указанное время -- это не время преобразования, а время семплирования -- время, которое отводится на заряд емкости УВХ. Для расчета полного времени преобразования к времени семплирования надо добавить 12.5 тактов цифрования.
Первый раз слышу.
Знать у нас разные даташиты.
То есть, даже, если принять во внимание только преобразование (12,5) без паузы, то его время при частоте тактирования 12 мГц будет чуть больше 1 мкс, что не есть хорошо.
Вот именно. Вообще в datasheet указывается что максимальная частота внешнего тактирования не более 823кГц при самплинге АЦП 14 МГц. У нас 12МГц - на 1 мкс для одного АЦП это ни как не тянет. И то эти цифры идут под грифом: параметры дизайна, в реальных устройствах не гарантируется.
Вот именно. Вообще в datasheet указывается что максимальная частота внешнего тактирования не более 823кГц при самплинге АЦП 14 МГц. У нас 12МГц - на 1 мкс для одного АЦП это ни как не тянет. И то эти цифры идут под грифом: параметры дизайна, в реальных устройствах не гарантируется.
Эти моменты я чувствую и держу под вниманием и для реальных условий их скорректирую. Главное что бы база была правильной. В свзи с этим проверте пожалуйста код, представленный в посте 92. Там что то в конце на мой взгляд не так, поскольку после генерации в Кубе строки 459-466 пропадают. Всё, что дописано перед этим нормально. Предполагаю по не опытности, что при удалении чего то ненужного зацепили строчку /* USER CODE END 4 */