Обновить
10
0

Пользователь

Отправить сообщение

Таймеры как раз хороши тем, что выставили сигнал прерывания, сбросили счётчик в ноль и им до лампочки, что там микроконтроллер тупит, они пошли следующий интервал считать :) То есть интервалы у него постоянные (с точностью до постоянства тактовой частоты, разумеется) Причём тут ШИМ вообще не понял, ШИМ в простейшем случае это тупо компаратор, на входе которого две шины — состояние счётчика таймера и значение регистра управления коэффициентом заполнения, и его выход a > b (или a < b, или a <= b, или a >= b, это уже детали) подключён к ножке. Это если сильно упрощать. Он же никак на работу самого таймера не влияет (опять же, в простейшем случае. Не знаю, что там STM накрутили в advanced control таймерах)

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

Вот с этим как раз сложности. В теории связка DMA+UART эту задержку если не устраняет, то хотя бы уменьшает и делает более предсказуемой.

но если вам не могут подсказать преподаватели как тут правильно поступать - использовать таймеры, это печально

Там с преподавателем вышла ситуация, я начал трассировать печатную плату как мезонину под его отладочную плату, а она на F303. И когда уже моя плата была отправлена на производство, я понял, что неплохо было бы добавить таймеры сброса фазы. Они заняли два оставшихся таймера на микроконтроллере. А потом оказалось, что хорошо бы иметь ещё таймеры сброса фазы, просто потому что. В результате пригодился третий таймер в демонстрационной музыке, ну а в тестах прекрасно работали все шесть, из которых четыре были сделаны как раз на UARTах. Если бы я заранее понял, к чему сойдётся функционал конечного устройства, то сразу бы трассировал под мою отладочную плату на H743, там бы таймеров как раз хватило с запасом. Преподаватель немного фалломорфировал от решения использовать UARTы ТАК, но в результате смирился, поскольку работает же.

У меня такого таймера нет. Но есть набор из n других таймеров, каждый из которых работает на частотах от 100 Гц до 1 кГц. И их частоты могут быть какими угодно в этом диапазоне. Так как речь о музыке и звуках, я должен очень точно выдерживать частоты. Пусть и будет небольшой джиттер, но средняя за время частота вызова определённой функции должна быть постоянна и выдерживаться настолько точно, что слушатель не заметит уплывания темпа (в случае с тикрейтом движка) и частоты (в случае с таймерами сброса фазы). В решении с одним таймером для обеспечения требуемого диапазона и точности задания частот нужно, навскидку, этот таймер запускать на частоте, которая хотя бы на порядок выше верхней границы, что для моего оптимистичного случая 10 кГц. И теперь представьте, кто кушает (в среднем) больше процессорного времени — шесть таймеров с прерываниями, каждое не чаще 1 кГц, или один таймер с прерываниями в 10 кГц и относительно сложным обработчиком, который как-то (например, имея шесть счётчиков и вызывая нужные функции по достижении каждым счётчиком определённого значения) в нужные срабатывания этого одного прерывания вызывает нужные функции. Я люблю в таком случае искать аппаратные решения вопроса, просто потому что вижу в этом некую красоту. Возможно, я бы обошёлся и без такого извращения, поставив один таймер на частое срабатывание.

Я хотел сказать, что мы по формуле насчитали период, допустим, 1 мс. Запустили. Через 1 мс UART дал сигнал прерывания. Но микроконтроллер мгновенно отреагировать не может, поскольку ему требуется несколько тактов на уход в прерывание и несколько тактов в самом прерывании до записи непосредственно в регистр BRR, и именно с момента записи в регистр BRR пойдёт отсчёт следующей миллисекунды. Т.е. период будет равен не 1 мс, а 1 мс + некоторое время, около 100 нс — 1 мкс, пока микроконтроллер уходит в прерывание и кладёт новые данные. Причём это в идеальном случае. Что если контроллер DMA занял шину для транзакции? Что если код прерывания и сам вектор лежат в медленной памяти (флэш с тактами задержки доступа, QSPI-флэш?) Что если это произошло в момент исполнения обработчика прерывания более высокого приоритета? Всё это внесёт дополнительные задержки. В представленном случае они всё ещё достаточно малы по сравнению с периодом прерывания, однако они будут накапливаться с каждым срабатыванием, и 1000 прерываний произойдёт уже не за одну условную секунду (условную, поскольку неизвестна стабильность источника тактовых импульсов), а за, например, 1.001 секунду, что уже может быть существенно в каких-то задачах. Поскольку я заявляю данное решение как альтернативу таймеру, который этих недостатков лишён (ведь он считает постоянно и ничто его не задерживает в момент срабатывания прерывания переполнения счётчика), я попытался описать недостаток этого решения.

Согласен. Но вот у меня конкретно в этом проекте получилось наоборот. Кустарный UART, по крайней мере, на передачу, можно сделать через GPIO+TIM+DMA. На небольших скоростях гарантированно будет работать передача. С приёмом сложнее, но можно через такую же схему с запуском в прерывании той же связки, только в обратную сторону, из GPIOx->IDR в оперативу, по заднему фронту (т.е. по стартовому биту). Конечно, на больших скоростях такая штука не будет успевать «разгребать» принятые данные. Но в теории можно извратиться.

В курсовом проекте я на свою голову ограничил себя платой преподавателя, а там стоял STM32F303... Притом что у меня уже тогда валялась платка с H743 от WeAct. Знал бы, что придётся так извращаться — делал бы на H743.

Ayugram, скорее всего

 зачем нам четыре таймера для ШИМ-ов, если на каждом таймере можно сделать четыре ШИМ-а на одной частоте

Четыре звуковых канала, и у каждого своя частота должна быть. Я бы тоже был рад повесить всё на один таймер, но нужна разная частота, причём точно настраиваемая (точность 1 Гц или выше)

Для меня «абстрактная задача для собеса или экзамена» — выражение достаточно ругательное. Поскольку сам через такой экзамен проходил. Поэтому представил реальное применение описанного (ссылка в самом начале статьи).

В проекте не сильно нужна была синхронизация событий. А вот средняя частота должна была регулироваться очень точно, поскольку музыка. Если бы я сделал на одном таймере, то были бы прерывания с частотой минимум 10 кГц, а это уже ест довольно много процессорного времени. Посмотрите код, там в принципе описано, зачем сделано именно так.

Я не смотрел серию G, каюсь. Сейчас поправлю.

Четыре таймера генерят ШИМ. Каждый такой сигнал должен иметь свою независимую частоту, поэтому четыре. Ещё один таймер делает ШИМ, который тактирует генератор шума. Два таймера используются для задания сэмплрейта того, что играет через внутренний двухканальный ЦАП, по одному таймеру на канал. Ещё один таймер задаёт тикрейт движка исполнения команд. Ещё два таймера делают костыльный ШИМ-ЦАП, один с фиксированным периодом молотит ШИМ, от второго идёт, опять же, сэмплрейт этого канала (он инициирует пересылки DMA). И после всего этого у меня остались только TIM20 и SysTick. Они были пущены на таймеры сброса фазы. И потом оказалось, что двух таких таймеров недостаточно, пришлось искать что-то, что смогло бы их заменить.

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

Железка интересная! Вот только печально, что не могу найти даташиты на СнК VRTech. Кто-то может поделиться? Особенно интересует реализация синтеза звука, поскольку дендевский звук знаю вдоль и поперёк (включая все чипы расширения)

Опять же, АЦП в теории тоже случайные должен давать в младшем бите. Но проверить их случайность оборудования и знаний не хватает, поэтому написал аккуратно.

В принципе можно, что-то не подумал об этом. В принципе получится почти то же самое, только амплитуду как в первом способе можно будет регулировать.

2

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность