Продолжим осваивать периферию STM32. На этот раз научимся плавно включать и выключать светодиод.
Про ШИМ было сказано уже достаточно в статье «Как работает ШИМ». Поэтому здесь лишь представлена реализация и краткое описание. Стоит отметить, что у семейства STM32F407xx среди фич указано «Up to 17 timers: each up to 4 pwm…» в общем проблем с количеством таймеров и каналов ШИМ не должно быть.
Задача — плавное изменение яркости светодиода, т.е. получить регулируемое напряжение. Поэтому нам нужен таймер, который будет делать отсчеты. На основе этих отсчетов мы формируем сигнал с определенной частотой(периодом). Регулируя заполнение импульса(скважность), мы изменяем напряжение.
В качестве примера будем использовать ножку PD12, потому что на ней светодиод. При этом помним, что на любую произвольную ножку нельзя назначить ШИМ канал, только на те у которых есть в качестве альтернативной функции можно использовать таймер. У PD12 используется TIM4.
TIM4 имеет 16 битный счетчик, которой умеет считать как вверх, так и вниз. Можно использовать 16 битный предделитель. Кроме того имеется 2 режима Edge- and Center-aligned, выравнивание по центру и фронту, фишка специфичная помогает снизить помехи, для управления светодиодом разницы нет какой использовать.
В качестве прошивки — плавно зажигаем, затем плавно тушим светодиод. Для этого придется настроить ножку на альтернативный режим, включить таймер и настроить ШИМ
#include <stm32f4xx.h> #include <stm32f4xx_gpio.h> #include <stm32f4xx_rcc.h> #include <stm32f4xx_tim.h> void delay_ms(uint32_t ms) { volatile uint32_t nCount; //переменная для счета RCC_ClocksTypeDef RCC_Clocks; //переменная для считывания текущей частоты RCC_GetClocksFreq (&RCC_Clocks); //считываем текущую тактовую частоту nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms; //пересчитываем мс в циклы for (; nCount!=0; nCount--); //гоняем пустые циклы } int main(void) { int x = 1023; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //включить тактирование GPIO_InitTypeDef PORT_SETUP; //структура настройки ножки PORT_SETUP.GPIO_Mode = GPIO_Mode_AF; //альтернативная функция ножки PORT_SETUP.GPIO_OType = GPIO_OType_PP; //ножка пуш-пул PORT_SETUP.GPIO_Pin = GPIO_Pin_12; //12 ножка PORT_SETUP.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOD, &PORT_SETUP); GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4); //использовать таймер4 для 12 ножки TIM_TimeBaseInitTypeDef TIM_SETUP; //структура настройки таймера TIM_SETUP.TIM_CounterMode = TIM_CounterMode_Up; //считаем вверх TIM_SETUP.TIM_Period = 1023; //период таймера 1023 отсчета TIM_SETUP.TIM_Prescaler = 0; //предделитель откл TIM_TimeBaseInit(TIM4, &TIM_SETUP); TIM_OCInitTypeDef PWM_SETUP; //структура настройки ШИМ PWM_SETUP.TIM_Pulse = 254; //начальное заполнение PWM_SETUP.TIM_OCMode = TIM_OCMode_PWM1; //режим1 center align PWM_SETUP.TIM_OutputState =TIM_OutputState_Enable; //подключаем к выходу PWM_SETUP.TIM_OCPolarity = TIM_OCPolarity_High; //положительная полярность TIM_OC1Init(TIM4, &PWM_SETUP); TIM_Cmd(TIM4, ENABLE); while(1) { while(x>0) //тушим светодиод { TIM4->CCR1=x; x--; delay_ms(1); } while(x<1023) //зажигаем светодиод { TIM4->CCR1=x; x++; delay_ms(1); } } } |
Выглядит несколько сложнее чем на AVR, но если вдуматься то все тоже самое. Результат
Проект кокоса
Можно пример как ШИМ подключить к ножек №13, если это возможно.
Вопрос снят.
Вот что мне у вас всегда нравиться так это то, что в коде всегда все подписано! это так упрощает нам ленивцам жизнь) вместо того чтобы открывать ref_manual читать переводить, подглядел у вас в коде, тяп-ляп переписал под свои задачи и готово) спасибо огромное!