ШИМ при помощи таймера на STM32
Добрый день.
Недавно приехала посылка из Китая, и я не смог удержаться, что бы не познакомиться с новой игрушкой.
Представляю вашему вниманию STM32G030F6P6.
Сейчас быстренько соберу их этого набора отладочную плату, и мы на новой железке будем знакомиться с тем, что такое ШИМ, и как его можно использовать.
Так же для имитации настоящего устройства - нагрузку мы будем подключать при помощи транзисторов. Это обыкновенные NPN транзисторы. Их маркировку сейчас вы видите на экране.
Вот такая красота получилась. Если кто-то считал что эти платки не подходят для транзисторов - то пожалуйста, они отлично тут стоят. Пока что мне этим микроконтроллеры нравятся больше, чем F0 серия. У них более удобно разведено питание. Но это мелочи - для начала начнём из далека. По какой причине вообще при управлении нагрузкой используются транзисторы. Без разницы какие полевые, или биполярные, или вообще IGBT. Если открыть product specification, и найти там электрические характеристики, то мы увидим, что максимально микроконтроллер может потреблять от источника питания 100 миллиампер, а каждый вывод должен пропускать через себя ток - не более 15 миллиампер. И получается, что к одному выводу можно подключить нагрузку, не мощнее светодиода, да и в целом - 4 светодиода - это максимум, что можно подключить. Вот и получается, что да решения этой проблемы - очень удобно использовать транзисторы. Способы включения транзисторов не будем сейчас разбирать.
С этим разобрались, далее - ШИМ - что это такое, и для чего он вообще нужен:
Если вспомните занятие, на котором мы управляли частотой мерцания светодиода, то там, при частоте более 40 герц глазом казалось что светодиод светится равномерно, и не моргает. При этом мы управляли частотой импульсов подаваемых на светодиод. Другими словами - использовали ЧИМ - частотно импульсную модуляцию. ШИМ - В своей основе так же содержит импульсную модуляцию, но управляется в этом случае не частота, а ширина следующих импульсов, частота при этом остаётся неизменной.
Для сегодняшних экспериментов возьмём вот такую светодиодную матрицу. Единственное что я о ней знаю - это то, что на ней написано 12 вольт.
Для её питания наших 3,3 вольта, выдаваемых микроконтроллером будет точно недостаточно, по этому запитаем её от ЛБП, но через транзисторный ключ. Пока собирал схему - понял что для транзисторов надо добавить ещё и базовый резистор, по этому быстренько за кадром доработал свой блок транзисторов. Ограничением же тока через коллектор, и как следствие через матрицу, и будет заниматься ЛБП.
Для проверки что наша схема работает, создадим новый проект в CubeMX, укажем всё необходимое, и пока просто в цикле подёргаем ножкой, к которой подключена наша светодиодная матрица. Удивительно, но ничего не сгорело, и мощная светодиодная матрица управляется маломощным выводом микроконтроллера.
Теперь давайте сделаем, что бы матрица не просто мигала, а плавно регулировала свою яркость.
Ну и как же я мог забыть, задача на сегодня:
К выводу микроконтроллера подключен фоторезистор, требуется в зависимости от освещенности, устанавливать яркость свечения светодиодной матрицы. Управление матрицей реализовать при помощи ШИМ с частотой 100 килогерц.
Добавим в нашу схему фоторезистор, и подключим его к первому выводу микроконтроллера.
Запускаем CubeMX, и указываем, что мы хотим использовать АЦП на этой ножке. И тут нас встречает интересная особенность нового микроконтроллера - а именно этот вывод может быть как PB7, так и PB8. Пока что оставим на потом разбор что это такое, и зачем может использоваться. Находим АЦП, и активируем его.
Далее - настройка АЦП. Тут тоже стало чуть больше пунктов, но мы их пока не будем трогать. Да и в целом, помня как на предыдущем занятии мы настраивали АЦП - для работы в режиме софт старта - ничего менять не требуется.
Далее - переходим к ШИМ. Воспользуемся для этого нам уже знакомым таймером - TIM14. Активируем его, и помимо просто активации - укажем что его первый, и единственный канал будет являться выводом для генерации ШИМ. При этом видим что PA4 активировался, и у него появилось название.
Получается мы не угадали с тем, куда подключить светодиод, но это не большая проблема - подключим его к нужному выводу.
Переходим к настройке таймера - первая часть уже нам знакома. Проверим частоту, поступающую на вход таймера. Тут уже не 8 мегагерц, а 16.
Так как нам по условиям требуется довольно высокая частота - прескейлер не меняем. Counter Period ставим - 159. Остальное в первом блоке - не меняем.
Далее новое.
  • Mode - лучше бы назвали инвертирование - суть, в режиме 1 выходной сигнал не инвертируется, в режиме 2 - инвертируется. Нам подходит первый вариант.
  • Pulse - Собственно это и есть значение, в котором устанавливается досчитав до какого значения таймер изменит полярность на выходе. То есть соотношение этого значения к Couner Period-у и будет являться процентом заполнения ШИМ. Поставим сюда 80, что даст на выходе Шим с заполнением 50%.
  • Output compare preload - по аналогии - с auto-reload preload. Если мы в программе изменим Pulse - то изменения вступят в силу только после того, как таймер досчитает до своего максимального значения.
  • Fast mode - этот пункт я так и не смог понять. Пока разбирался что это такое - приходил то к I2C, то к тому будет ли канал являться входом или выходом. Так что пока что оставим как есть.
  • CH Polarity - Ещё один вариант инвертирования. Я пока плохо представляю себе зачем это может понадобиться, но будем знать что такое есть.
Как мне кажется - на этом всё - перегенерируем проект.
В первую очередь - будем считывать состояние на входе ацп. Как и в предыдущем занятии - создадим переменную, запустим калибровку АЦП, после чего запускаем преобразование. Далее в цикле - ждём окончания конвертации, получаем значение, и перезапускаем преобразование. Пока что ничего нового.
Теперь нам необходимо полученное значение использовать в качестве значения для ширины импульсов, генерируемых ШИМ.
К стати, запустим наш таймер, и запустим генерацию ШИМ на нём. Осталось только привести полученное от ацп значение к диапазону от нуля до Counter Period, который у нас составляет 160, и передать полученное значение в таймер.
Для того, что бы понять куда именно передать - запустим отладку, и остановим выполнение программы.
в глобальных переменных видим наш таймер, и открыв его Instance видим ранее установленное в кубе значение 80. Ему соответствует регистр CCR1. Дописываем. программу, исходя из новых данных.
Запускаем и проверяем полученный результат.
На камеру плохо видно, из-за того, что она пытается автоматически регулировать освещенность.
Для большей наглядности хорошо бы было показать это на осциллографе, но и логическим анализатором тоже можно посмотреть, хоть и менее удобно.
Странно, почему-то заполнение ШИМ не поднимается выше 20%.
Посмотрел внимательно на макетку, и тут баг в железе. Один из выводов фоторезистора не подсоединён, исправляем. Светодиод визуально стал светить сильно ярче. проверяем логическим анализатором.
Вот теперь более наглядно.
Тут мы не затеняли датчик, и длительность высокого уровня - большая.
А здесь - затенили, и длительность высокого уровня стала очень низкой.
 
А на этом всё, спасибо за внимание.