STM Урок 10. HAL. Изучаем PWM (ШИМ). Мигаем светодиодами плавно



Урок 10

HAL. Изучаем PWM (ШИМ). Мигаем светодиодами плавно

 

Сегодня мы продолжим использование библиотеки HAL. Также сегодня мы коснёмся такой технологии, как PWM (ШИМ).

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

Мы изучим, как именно широтно-импульсная модуляция реализована в контроллерах STM32, в частности в STM32F407, с которым мы и будем продолжать работать.

Проще всего управлять технологией PWM у данных контроллеров посредством таймеров. Урок по таймерам у нас уже был. Какой таймер чем занимается, мы уже кратко ознакомились, поэтому нам будет намного проще.

В качестве таймера для ШИМ мы возьмём таймер 4. Данный таймер является 16-битным. Доступно до 4 раздельных канала. Также в технической документации на контроллер указано, что таймер может выступать в роли PWM-генератора

 

image00

 

Точно также как и раньше проект создаем из самого первого (TEST001), называем его MYPWM

Запускаем Cube MX, отключим. во-первых все ножки портов светодиодов, а также ножку кнопки

 

image01image02

 

Включаем таймер, выбрав в выпадающем списке внутреннее тактирования, и включаем в нем каналы – все 4, выбрав там PWM

 

image03

 

 

Как мы видим, ножки портов, отвечающих за светодиоды на плате, включились сами в определенный альтернативный режим

 

image06

 

В настройках таймера в Configuration параметр Counter Period выставляем в 65535

 

image04

 

На всякий случай включим прерывания и всем 4м портам выставим скорость high. Генерируем проект

 

image05

image07

 

 

 

Добавляем код инициализации

 

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_TIM4_Init();

 

  /* USER CODE BEGIN 2 */

        HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);

        HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);

        HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);

        HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);

  /* USER CODE END 2 */

 

В функцию main пишем также

 

  /* USER CODE BEGIN 1 */

        uint32_t i,d;

  /* USER CODE END 1 */

 

И в бесконечный цикл пишем

 

/* USER CODE BEGIN 3 */

                for(i=0;i<=524288;i++)

                {

                        if(i<65536)        TIM4->CCR1=i;

                        else if ((i>65535)&&(i<131072)) TIM4->CCR1=131071-i;

                        else if((i>131071)&&(i<196608))        TIM4->CCR2=i-131072;

                        else if ((i>196607)&&(i<262164)) TIM4->CCR2=262164-i;

                        else if((i>262163)&&(i<327680))        TIM4->CCR3=i-262164;

                        else if ((i>327679)&&(i<393216)) TIM4->CCR3=393216-i;

                        else if((i>393216)&&(i<458752))        TIM4->CCR4=i-393216;

                        else TIM4->CCR4=524288-i;

                        for(d=0;d<300;d++)

                        {

                                        

                        }

                }

  }

  /* USER CODE END 3 */

 

Теперь соберём код, прошьём контроллер.

После этого мы должны видеть следующую картину

 

image08

 

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

 

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Купить плату можно здесь STM32F4-DISCOVERY

 

Смотреть ВИДЕОУРОК

 

STM32 HAL. Изучаем PWM (ШИМ). Мигаем светодиодами плавно

 

32 комментария на “STM Урок 10. HAL. Изучаем PWM (ШИМ). Мигаем светодиодами плавно
  1. Дмитрий:

    Здравствуйте! Хотел у вас спросить, можете ли вы пояснить запись "TIM4->CCR1=i;" что происходит на ножке порта? В один пин выводится четырехбайтовое число?! Где можно посмотреть за что отвечает регистр ССRx?   

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

  2. Дмитрий:

    ведь период ограничен 65535, а в CCRх передаеется 524288

    • Нигде такое число не передаётся. Число передаётся от 0 до 65535. Внимательно просчитайте в каждой строке, чему может быть равно i, а затем посчитайте разность в правых частях равенств. Мы нигде ни разу не превысили допустимый интервал.

  3. Дмитрий:

    Спасибо большое!)) дурацкая невнимательность всй губит!) Разобрался! 

  4. Стефан:

    Здравствуте Владимир!

    Огромное спасибо за ваши уроки. Все подробно объясняете.  Я уже много чего успел сделать и запустить, благодаря вам, хотя раньше с STM32  не сталкивался. 

    Не подскажете — как можно запустить ШИМ на частоту примерно 7kHz, а потом плавно менять частоту (не скважность) вверх — вниз, используя, например, две кнопки?

    Привет с Болгарии. Вы здесь тоже популярны 🙂

  5. Вячеслав:

    И где тут управление шим через HAL?
    Вы пишете в регистры напрямую.

  6. Seba:

    Что то автор уроков гонит мне кажется, причем в наглую.

  7. streloc:

    Спасибо за уроки. Подскажите как можно сделать плавное включение лампы на 220в. и 12 в.

    • Посредством PWM, только надо будет организовать для ламп отдельное питание постоянным током и в качестве ключа использовать один или два транзистора с изолированным затвором (MOSFET). А какие именно, можно посмотреть в даташитах соответствующих транзисторов. На 12 вольт например подойдёт вот этот — IRL3103N. На 220 вольт будет посложнее, скорей всего придется ставить два. Так как далеко не все транзисторы откроются при напряжении на затворе ниже 3 вольт.

  8. Max:

    А не подскажите, нет ли случаем в HAL метода задающего значение скважности?

    • Такой функции нет.
      Можно только через заполнение структуры переменной типа структуры TIM_OC_InitTypeDef с последующей передачей в качестве параметра функции HAL_TIM_PWM_ConfigChannel. А в структуре есть поле Pulse, которое и задаст скважность.
      Только не думаю, что это будет хорошим решением, так как будет выполняться долго, лучше всё-таки через регистр.

  9. А зачем включать прерывание таймера 4 на avr так я не делаю? если мы его используем как шим?

  10. Argonec:

    Добрый день ! Спасибо огромное за уроки ! У меня вопрос следующего характера , у таймеров есть пункт » pwm generation no output » . Правильно ли я понимаю что это просто обработчик и в него мы можем засунуть любые ноги МК ? Если да , тогда возникает следующий вопрос — ка это реализуется в жизни ? Спасибо еще раз .

    • Вам также спасибо за интерес к ресурсу!
      Не совсем понятен вопрос.
      Вы про какой регистр и про какой бит говорите (или битовое поле)?

      • Argonec:

        В Кубе , при выборе режима таймера ( в данном случае 4 канал второго таймера , просто для примера ) , есть такой пункт pwm generation no output см. картинку (ссылка) Гугл молчит на эту тему . Вот я и сделал предположение , может и ошибочное . По мотивам ваших видео сделал паяльную станцию на ili9341 , если интересно видео (ссылка) . Еще раз большое спасибо !

        • Спасибо! (ссылки на сторонние ресурсы подчистил). Все ссылки мне в личку в контакте, так как я работаю один и не могу проследить за всеми ссылками. А попадаются всякие, можно запросто лишиться сайта.

          • Argonec:

            Черт с ними с ссылками ))) Все таки вопрос остался открытым : В Кубе , при выборе режима таймера , есть такой пункт pwm generation no output . Если это просто обработчик , тогда по идее мы можем засунуть в него любые ноги МК . Если это верно , то как с этим работать ? Спасибо .

          • Я лично, к сожалению, с данной функцией не работал. Но подозреваю, что в момент совпадений мы будем попадать в определённые обработчики прерываний, где и можем изменить уровень тех или иных контактов какого-либо порта.

  11. Валера:

    Могли бы уже трехфзный шим показать

  12. Николай Прижимин:

    То HAL, то запись регистры — винегрет какой-то.
    Если необходимо менять величину заполнения, то в HAL следует использовать __HAL_TIM_SET_COMPARE

  13. W4d1m:

    Здравствуйте! Подскажите пожалуйста, как с помощью таймеров можно прерывать PWM. У меня выход PWM 300Гц на TIM2 и его нужно прерывать, скажем, с частотой 10 Гц. Как это можно сделать?

    • A-Soft:

      Непонятно что значит «прерывать PWM с частотой 10Гц». Что вы имеете ввиду? Какой сигнал хотите получить?
      Исходя из своих теоретических предположений по вашему запросу:
      В обработчик прерывания по переполнению добавьте переменную-счётчик.
      На 300 Гц досчитали до 30:
      TIM2->CCR1 = 0; //предположил что у вас TIM2 Channel1
      // или TIM2->CCR1 = TIM2->ARR — смотря чем вы хотите «прервать» — нулём или единицей на выходе.
      досчитали еще до 30:
      TIM2->CCR1 = PWM_Value;
      но возможно я неправильно понял задачу. не экстрасенс.

      • W4d1m:

        Спасибо за ответ! Я хотел получить ШИМ пачками. Искал другие варианты чтоб не через коллбэки. Думал, может можно всё это аппаратно будет заставить работать. Выставить таймер в режим ШИМ и как слейв а второй таймер в режим счётчика или ШИМ без выхода. Таким образом прерывать работу ШИМ'а без коллбэка, но чтот не выходит. Видимо проще завести ещё один ШИМ и решить проблему внешним лог. вентилем AND.

        • A-Soft:

          Можно и аппаратно. Частота таймеров 72 МГц.
          TIM2 конфигурация:
          Slave Node = Gated Mode
          Trigger Source = ITR2
          Channel1 = PWM Generation CH1
          TIM2 настройки:
          Prescaler = 2399
          Counter Period = 99
          PWM -> Pulse = 50 (скважность PWM)

          TIM3 конфигурация:
          Channel1 = PWM Generation No Output
          TIM3 настройки:
          Prescaler = 2399
          Counter Period = 2999
          Trigger Event Selection = Output Compare (OC1REF)
          PWM -> Pulse = 1500

          запуск в программе:
          HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
          HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

          • W4d1m:

            Ах, вот почему не работало у меня. Я забыл выставить Out Compare в Trigger Event Selelection 😀 Большое Вам спасибо за помощь!

  14. Plty4:

    Доброго времени суток, возможно осуществить с одного канала чтобы дрыгало несколько ножек? Чтобы можно было отключить/включить независимо любую?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*