Seriyvolk писал(а): Заводишь просто таймер. По его прерыванию делаешь с ногами всё, что тебе нужно. Хоть с одной, хоть с несколькими. Николай тебе об этом говорил. Просто таймер с прерыванием по переполнению + прерывания по совпадениям с OCR1A, OCR1B. Устанавливаем ножки в прерывании по переполнению, сбрасываем в прерываниях по совпадению TCNT1 с OCR1A(B). Это работает, но косяк - на высоких частотах увеличивается ошибка фактического рабочего цикла ШИМ относительно установленного, вплоть до неприличной (смотря по осциллу). А как еще можно? Без настройки сравнений TCNT1 с OCR1A(B), не вкурю, как можно обойтись одним прерыванием по переполнению TCNT=TOP? Можно перезаводить таймер в каждом цикле на новые значения, но тогда с больше чем одним каналом будет каша какая-то. Добавлено: Sat Feb 05, 2022 11:40 pm |
Денис писал(а): Это работает, но косяк - на высоких частотах увеличивается ошибка фактического рабочего цикла ШИМ относительно установленного, вплоть до неприличной (смотря по осциллу). Прости, но на каком языке ты пытаешься это всё реализовать? И почему у тебя увеличивается ошибка цикла ШИМ, если последний жёстко привязан к таймеру? Единственный вариант, который мне с дивана видно - ты пытаешься запихать простыни в прерывания. Ну или не ты, а компилятор, что по факту то же самое. Добавлено: Sun Feb 06, 2022 2:05 am |
В общем, остановился пока на штатном режиме таймера с ШИМ где ТОП=0х03FF. Для охвата нужного диапазона частот, с таким низким разрешением (счет до 03FF против FFFF) приходится использовать все допустимые делители, с частотой тактирования таймера от 16МГц до 62,5 кГц. Если бы был аппаратный режим двухканального ШИМ с ТОП=FFFF, ограничился бы двумя частотами 16 МГц и 2 МГц и этого бы хватило. Почему сбивается заполнение на аппаратно-программном варианте, не знаю точно, но видимо неправильно выбирал режимы и оставалось слишком мало тактов счёта на высоких частотах, из-за чего такты потраченные на прерывания (а прерываний же три - попереполнению и два посовпадению с OCRx). В самих прерываниях предельно просто и без кустов. Вопрос такой, давно не прогал и подзабыл битовые операции. Как проще всего часть регистра сделать равной битовой маске, а оставшуюся часть оставить нетронутой? Например есть регистр REG = 10101ххх, есть маска вида 110, нужно чтобы стало в таком случае REG = 10101110. Так пойдет? (REG & 0b11111000) | 0b110 Добавлено: Tue Feb 08, 2022 12:00 am |
Пойдет Добавлено: Tue Feb 08, 2022 5:46 am |
в прерываниях вообще пяток байт максимум. все остальное за пределами него. но... причес тут время проведенное в прерывании? таймер то тикает (должен) всегда. даже когда в прерывании сидишь. Добавлено: Tue Feb 08, 2022 8:42 am |
Николай писал(а): в прерываниях вообще пяток байт максимум. все остальное за пределами него. Ну это таки от задачи зависит Правильнее будет сказать: находясь в прерывании надо понимать, к чему это приведет и сколько мы можем в нем висеть... Добавлено: Tue Feb 08, 2022 8:47 am |
Сейчас в командировке, вернусь скину пример кода, хочу посоветоваться. Всё-таки остаются для меня непонятные моменты. Добавлено: Tue Feb 08, 2022 9:04 am |
сидя в прерывании мы как минимум можем проебать другое. лучше все делать за пределами. Добавлено: Tue Feb 08, 2022 9:09 am |
Николай писал(а): сидя в прерывании мы как минимум можем проебать другое. лучше все делать за пределами. Другое можно проебать, если их придет два. А иначе флаг запроса повиснет и вполне оно потом обработается Николай писал(а): лучше все делать за пределами. Ну вот у меня допустим сейчас just4fun проект, куда я воткнул валявшийся у меня без дела HCPL-786J. Есть буфер, куда DMA складывает данные. Данные он берет из SPI, а в SPI они валятся из сигма-дельта модулятора. Соответственно SPI в слейве, модулятор генерит клок 10МГц, буфер 250 байт, DMA валит данные по кольцу, попутно генерит прерывание когда половина (125) пришла, затем когда вторая половина пришла. Соответственно каждые 100 мкс я получаю прерывание. После этого мне надо прокрутить полученную половину буфера (125 байт) через фильтр, пока DMA не нафигачил поверху следующую порцию. Ну ничего, все в цикле считается прямо внутри прерывания. Помимо этого есть еще прерывание синхры с сетью для симмисторов и от таймера, который углы отпирания выставляет. Норм все в принципе. Единственное, что синхра стоит приоритетом повыше и может вклиниться в предыдущее прерывание. Но в принципе и без этого для периода сети 20мс ошибка получалась небольшая и особого джиттера я не видел, приоритет поднял уже после, просто прикинул что так правильнее Добавлено: Tue Feb 08, 2022 10:03 am |
N1X писал(а): А иначе флаг запроса повиснет и вполне оно потом обработается дорога ложка к обеду, а прерывание к моменту его наступления. просто идеологически более правильно чтобы прерывание всегда заканчивалось раньше чем может наступить следующее. очередь из прерываний это так себе конструкция. каюсь. есть у меня такой костыль, когда одно прерывание прерывает другое. по входу в первое принудительно sei() и тогда по приходу байта в uart он обрабатывается, даже если первое прерывание не кончилось. но это криво и так не стоит делать Добавлено: Tue Feb 08, 2022 10:28 am |
Николай писал(а): просто идеологически более правильно чтобы прерывание всегда заканчивалось раньше чем может наступить следующее. Ну это даже теоретически сложно реализуемо. Ибо чисто статистически при минимально коротких прерываниях 2 собития могут наступить почти одновременно. Так что как по мне - это нормальная ситуация, просто если архитектура устройства это учитывает - ничего плохого в этом нету. Т.е. если у нас есть прерывание, которое не может ждать и при этом есть место, где прерывания блокируются (будь то другое прерывание или di в программе с какой-то целью) на достаточно долгий срок - это уже проблема. А если чего-то из этих двух условий нет (в смысле второе прерывание может ждать, допустим уарт на скорости 9600 нам гарантированно быстрее чем время приема байта второе прерывание точно не сгенерит) - ничего не случится. Уж что-то а коммуникаця вообще имеет приоритет где-то под ковром... Ну а если нам может прилететь что-то вроде сигнала аварийного тока в силе и нужно рубить концы - тогда про эту ситуацию помнить нужно (хотя и здесь притянуто зауши, ибо рубить концы должен кто-то еще до микроконтроллера, либо хотя-бы без участия ядра, а он уже по факту об этом узнает). Добавлено: Tue Feb 08, 2022 11:27 am |
Николай писал(а): просто идеологически более правильно чтобы прерывание всегда заканчивалось раньше чем может наступить следующее. очередь из прерываний это так себе конструкция. Не совсем. На очереди прерываний вполне можно сделать аппаратное подобие RTOS, если правильно расставить прерыванием приоритеты. Например, у меня в одном проекте все относительно важные задачи сидят в прерываниях, а в мейновском while(1) сидят задачи, которые выполняются при появлении свободного процессорного времени. Добавлено: Tue Feb 08, 2022 8:12 pm |
Денис писал(а): Сейчас в командировке, вернусь скину пример кода, хочу посоветоваться. Всё-таки остаются для меня непонятные моменты. В общем, упростил уже донельзя содержимое прерывания по переполнению таймера №1. ШИМ чисто аппаратный здесь. Просто напрямую устанавливаем в прерывании значение TCNT, с которого начнется следующий цикл счета, и значение при котором сбрасывается ножка шим-выхода. Сброс ровно при половине счета, т.е. заполнение должно быть ~50%. Комменты в коде есть. Смотрю на осциллограмму, видно рабочий цикл примерно 60%. Схрена ли? Ничего лишнего в коде нет. Пробовал уже while(1); вместо основного кода программы, то есть МК работал только на прерывание, никакой разницы. В чем собака зарыта?
Добавлено: Sun Feb 13, 2022 4:14 pm |
А может это чип такой? Кривой. Добавлено: Sun Feb 13, 2022 4:32 pm |
а другие прерывания не мешают? может что-то срабатывает и затягивает время? в протеусе запусти и глянь как в симуляторе работает и почему оно так работает Добавлено: Sun Feb 13, 2022 4:36 pm |
Блин, ну я вот хз что думать уже. Может и кривой. Попробую другую платку прошить. Других прерываний нет, и другие таймеры отключены. В Протеус не умею Добавлено: Sun Feb 13, 2022 4:39 pm |
освой протеус. самая важная программулина при работе с аврками. кинь целиком код. вместе с инициализацией суну в протеус. . вообщем кидай код целиком Добавлено: Sun Feb 13, 2022 4:48 pm |
Всегда думал, что искать баги через протеус бессмысленно, он и своих добавит. Или что-то поменялось, он может симулировать реалтайм? Добавлено: Sun Feb 13, 2022 5:01 pm |
нет. он охуенен. реально. я в нем такие недокументированные вещи тестировал, как одновременная работа пина и на выход и на вход ацп, или подключение диф-ацп одним выводом к ресету, и измерение падения напряжения на внутренем фете пина этим ацп. не реалтайм, он работае медленнее на сложных вещах, но просто дольше... а моделирует идеально. по крайней мере 328р и тини85. прям вообще идеально. даже когда ацп заводишь на вдвое большей частоте чем документировано - и в протеусе и в жизни совпадает разрабатываю и обкатываю все в протеусе. больше ни какого софта не испольщую. потом финальную прошивку из него лью в контроллер и он работает абсолютно также. даже когда с костылями. прям совсем совсем рекомендую. с жизнью сходится на сто процентов. модели авр там идеальные Добавлено: Sun Feb 13, 2022 5:26 pm |
Блин, где-то теряются такты, не могу понять где. С такими вводными, как ниже (старт счета с 1003, сброс ШИМ-вывода на 1004, счет до 1023) - заполнение получается ~45%, хотя должно быть ~5%.
Добавлено: Sun Feb 13, 2022 7:36 pm |
Вот так меняется заполнение, при тех же условиях старт TCNT=1003, TOP=1023, OCR1A меняем от 1004 до 1023 и так в цикле. Просто чтобы наглядно понять, как оно реагирует на разные значения OCR1A. А должно получаться заполнение от 5 до 100%. ps проверил на другом МК, купленным с разницей в годы. Все аналогично, т.е. дело не в лыжах Добавлено: Sun Feb 13, 2022 8:27 pm |
гляну утром Добавлено: Sun Feb 13, 2022 9:31 pm |
Становится заметно только на высоких частотах ШИМ. Есть косвенное подозрение, что таймер просирает где-то ощутимое время от момента переполнения до выхода из обработчика переполнения (или даже от переполнения до входа в обработчик). Просираемое время при этом фиксировано, и на десятках кГц ШИМ эффект уже на осцилле не заметен. А на сотнях, ну выше осцилограмма, "вижу лошадь у крыльца, где быть должна моя" (с) Хой. Добавлено: Sun Feb 13, 2022 10:14 pm |
А торможение через while точно работает? У меня оптимизатор сам убирает подобные конструкции, а если его отключить, то библиотеки задержек перестают работать Добавлено: Mon Feb 14, 2022 9:48 am |
если вставишь nop в тело то оставит. Он выкидывает потому, что в теле ничего не выполняется... Ну или переменную, которую модифицируешь в цикле объяви как volatile, тоже должно быть норм Добавлено: Mon Feb 14, 2022 9:59 am |
Лицензионное соглашение (c)Flyback.org.ru Российское общество любителей высоких напряжений. Использование материалов с данного сайта и форума возможно только с разрешения администрации. |