Продолжим осваивать периферию STM32. На этот раз научимся плавно включать и выключать светодиод.
Про ШИМ было сказано уже достаточно в статье «Как работает ШИМ». Поэтому здесь лишь представлена реализация и краткое описание. Стоит отметить, что у семейства STM32F407xx среди фич указано «Up to 17 timers: each up to 4 pwm…» в общем проблем с количеством таймеров и каналов ШИМ не должно быть.
Задача — плавное изменение яркости светодиода, т.е. получить регулируемое напряжение. Поэтому нам нужен таймер, который будет делать отсчеты. На основе этих отсчетов мы формируем сигнал с определенной частотой(периодом). Регулируя заполнение импульса(скважность), мы изменяем напряжение.
В качестве примера будем использовать ножку PD12, потому что на ней светодиод. При этом помним, что на любую произвольную ножку нельзя назначить ШИМ канал, только на те у которых есть в качестве альтернативной функции можно использовать таймер. У PD12 используется TIM4.

TIM4 имеет 16 битный счетчик, которой умеет считать как вверх, так и вниз. Можно использовать 16 битный предделитель. Кроме того имеется 2 режима Edge- and Center-aligned, выравнивание по центру и фронту, фишка специфичная помогает снизить помехи, для управления светодиодом разницы нет какой использовать.
В качестве прошивки — плавно зажигаем, затем плавно тушим светодиод. Для этого придется настроить ножку на альтернативный режим, включить таймер и настроить ШИМ
#include
#include
#include
#include
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 читать переводить, подглядел у вас в коде, тяп-ляп переписал под свои задачи и готово) спасибо огромное!