Как и в МК других производителей в STM32 ШИМ генерируется таймерами, которых в STM32F030F4P6 содержится 5 штук не считая системного таймера, часов и сторожевых таймеров. TIM1 и TIM3 относятся к таймерам общего назначения и они многофункциональные - содержат по 4 канала захвата/сравнения и имеют множество других функций. Таймеры TIM14, TIM16 и TIM17 базовые и они попроще и имеют только 1 канал захвата/сравнения. Более подробно о таймерах и их возможностях можно узнать например из статей о таймерах общего назначения и базовых.

Цитаты из статей о возможностях таймеров

Базовые таймеры.

16-битный счётчик с автоперезагрузкой.
16-битный программируемый делитель частоты: с 1 по 65535.
Схема синхронизации для запуска АЦП/ЦАП.
Захват сигнала (input capture).
Сравнение вывода (output compare).
Генерация сигнала ШИМ (выровненного по границе или по центру).
Генерация одиночных импульсов.
Генерация прерывания и/или запроса DMA по переполнению счётчика.

Таймеры общего назначения.

16-битный счётчик с автоперезагрузкой.
16-битный программируемый делитель частоты: с 1 по 65535.
Схема синхронизации для запуска АЦП/ЦАП.
Захват сигнала (input capture).
Сравнение вывода (output compare).
Генерация сигнала ШИМ (выровненного по границе или по центру).
Генерация одиночных импульсов.
Генерация прерывания и/или запроса DMA по переполнению счётчика.
Схемы синхронизации для управления таймерами при помощи внешних сигналов и для соединения нескольких таймеров друг с другом.
Комплементарные выходы с программируемым dead-time.
Счётчик повторений.
Вход BRK для сброса выходов таймера или выставления их в известное состояние.
Поддерживают инкрементальные (квадратурные) энкодеры и датчики Холла.
Генерация прерывания или запроса DMA по следующим событиям:
* Обновление: переполнение счётчика.
* Событие-триггер: старт, остановка, инициализация счётчика или его обновление внутренним или внешним триггером.
* Захват сигнала.
* Сравнение (output compare).
* Включение BRK.

Вернемся к рассматриваемой теме - генерации ШИМ.
Схема тестового устройства.

http://s017.radikal.ru/i434/1607/b4/ef0e8ae536ce.gif

С выводом PB1 к которому подключен светодиод, соединены каналы TIM1, TIM3 и TIM14.

http://s020.radikal.ru/i704/1607/88/618e70aea161.png

Для генерации ШИМ будем использовать таймер TIM14 как наиболее простой из перечисленных.

Тестовый код.

Код:
#include "stm32f0xx_conf.h"

void GPIO_Conf(void) // Конфигурация портов ввода / вывода.
{
    GPIO_InitTypeDef s;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // Включаем тактирование порта PB.

    s.GPIO_Pin   = GPIO_Pin_1;       // Настройка вывода PB1.
    s.GPIO_Mode  = GPIO_Mode_AF;     // Вывод настроен на одну из альтернативных функций.
    s.GPIO_OType = GPIO_OType_PP;    // Двухтактный выход (т. е. не открытый сток).
    s.GPIO_PuPd  = GPIO_PuPd_NOPULL; // Подтягивающие резисторы отключены.
    s.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &s);            // Инициализация порта.

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_0); // PB1 это выход таймера TIM 14.
}


void Tim14_Conf(void) // Конфигурация таймера.
{
    TIM_TimeBaseInitTypeDef Tim;
    TIM_OCInitTypeDef Pwm;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); // Включаем тактирование таймера 14.

    Tim.TIM_ClockDivision = TIM_CKD_DIV1; // Выключаем предварительный делитель частоты таймера.
    Tim.TIM_CounterMode   = TIM_CounterMode_Up; // Значение в счетном регистре увеличивается.
    Tim.TIM_Period        = 65535; // Значение до которого досчитав таймер обнулится (максимум 65535).
    Tim.TIM_Prescaler     = 0; // На сколько нужно делить частоту (максимум 65535).
    Tim.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM14, &Tim); // Инициализация таймера.

    // Настройка ШИМ.
    TIM_OCStructInit(&Pwm);  // Загрузка в структуру настроек таймера по умолчанию.

    Pwm.TIM_OCMode = TIM_OCMode_PWM1; // Режим ШИМ 1.
    Pwm.TIM_OutputState = TIM_OutputState_Enable;
    Pwm.TIM_Pulse = 1000; //32768;
    TIM_OC1Init(TIM14, &Pwm);

    TIM_Cmd(TIM14, ENABLE); // Запуск таймера.
}


int main(void)
{
    GPIO_Conf();   // Конфигурация портов ввода / вывода.
    Tim14_Conf();  // Конфигурация таймера.

    while(1)
    {

    }
}

Программа довольно простая. В функции main() вызываются функции настройки порта и таймера, после чего МК зацикливается до тех пор пока питание не выключат.
В функции GPIO_Conf() производится настройка вывода PB1 к которому подключен светодиод. Сперва включается тактирование порта GPIOB, которое по умолчанию выключено. Затем вывод порта настраивается на использование альтернативной функции. Какой именно зависит от этой строки.

Код:
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_0); // PB1 это выход таймера TIM 14.

Может показаться непонятно как здесь указывается что вывод PB1 должен быть соединен именно с выходом TIM14. Ответ на это можно найти в даташите на МК STM32F030F4P6 в котором есть таблица альтернативных функций для портов.
Для порта GPIOB.

http://s020.radikal.ru/i708/1607/15/1de756d10e0a.png

Из таблицы следует что нулевая альтернативная функция PB1 это выход таймера TIM14. А если бы нам потребовалось генерировать ШИМ третьим каналом таймера TIM1 и выводить его на PB1, то нужно было бы настроить вывод порта на вторую альтернативную функцию.

Функция Tim14_Conf() настраивает таймер TIM14. В ней в первую очередь включается тактирование таймера, а затем настраиваются основные параметры таймера, такие как предварительное деление частоты, значение после которого таймер обнулится и т. д.
Затем производится настройка первого канала таймера, так чтобы он генерировал ШИМ. Чтобы не заполнять все поля структуры, вызывается функция TIM_OCStructInit(), которая записывает в структуру настройки по умолчанию. После чего нужно изменить лишь те поля которые отличаются от тех что по умолчанию. Необходимо выбрать решим ШИМ, разрешить работу выхода канала и задать длительность импульса. Последнее необязательно, ведь длительность можно изменить позже.
После всех настроек разрешается работа таймера функцией TIM_Cmd().

Если прошить эту программу в МК, то при подаче питания светодиод будет слабо светится. Почему слабо? Потому что длительность импульса равна примерно 1/65 длительности периода ШИМ (в поле TIM_Period значение 65535, а в поле TIM_Pulse значение 1000). Т. к. частота поступающая на счетчик таймера равна 48 МГц и предделители отключены, а таймер обнуляется каждые 65536 импульсов, то частота ШИМ составит 48000000 / 65536 = 732.42 Гц.
Проверим это логическим анализатором.

http://s019.radikal.ru/i643/1607/6f/a7ca6b3c7082.png

Длительность импульса 20 мкс, период ШИМ 1.36 мс и частота 732.22 Гц. Результат близок к расчетному. Небольшое отличие видимо из-за того что частота кварцевого резонатора не ровно 8 МГц, а немного меньше.

Но не всегда нужен 16-ти битный ШИМ. Обычно нужна частота побольше. Уменьшим значение поля TIM_Period, скажем до 4000.

http://s020.radikal.ru/i703/1607/71/4fba39928af7.png

Длительность импульса осталась прежней, а период и частота изменились. Светодиод начал светить намного ярче.

Теперь добавим в цикл код, изменяющий длительность импульса во время работы программы. Функция main() будет выглядеть таким образом.

Код:
int main(void)
{
    uint16_t x=0;
    volatile uint16_t i;

    GPIO_Conf();   // Конфигурация портов ввода / вывода.
    Tim14_Conf();  // Конфигурация таймера.

    while(1)
    {
        TIM_SetCompare1(TIM14, x); // Изменяем длительность импульса.
        x=x+100;

        for (i=0; i<30000; i++); // Небольшая задержка.
    }
}

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

Файлы http://pure-basic.narod.ru/forum_files/ … 14_PWM.zip