STM32. CMSIS. Урок#03: Таймеры общего назначения. Update interrupt, PWM mode.

preview_player
Показать описание
#stm32 #CMSIS #timers
Привет друзья! Вот уже 2 года, как я изучаю STM32.
Самое время, после опыта работы с библиотекой HAL, когда мы уже более менее ознакомились с периферией микроконтроллера, начать осваивать его на низкоуровневой библиотеке CMSIS.

На четвертом занятии мы поработаем с таймерами общего назначения, создадим прерывание по переполнению счетчика и выведем ШИМ сигнал на ножку микроконтроллера.

00:00 Введение
00:35 Про таймеры общего назначения
05:28 Работа с регистрами. Настройка таймера
17:30 Прерывание Update interrupt
17:57 Настройка ШИМ
26:45 Тесты ШИМ(один канал).
28:12 2 канальный ШИМ. Тесты с выбором полярности сигнала.

Мои заметки по CMSIS:
Рекомендации по теме
Комментарии
Автор

Комментарий в поддержку этого отличного канала.

ajdarseidzade
Автор

Спасибо, как раз с шимом хотел поиграть.

dobroliub
Автор

Если регистр не буферизирован, он моментально обновляется (для TIMxCR1 обновляются значения PSC, ARR).
Если буферизирован, то обновление новых значений только после события Update Event (после переполнения счетчика).

Если нужно на ходу обновить ARR, PSC при установленном бите ARPE(Auto-reload preload):
1) Меняем в программе значения ARR, PSC
2) Вызываем IRQ: TIMx->EGR |= TIM_EGR_UG
3) Сбрасываем флаг UIF: TIMx->SR &= ~TIM_SR_UIF

Gleb_Godlevski
Автор

И переписал код инициализации и работы таймера в своем проекте, все сделал на регистрах, прикольно, и у камушка stm32030f4 всего то 16кБ флеша, HAL жрет так память, будто ее там 2Гб, вообще странно, что она не старается экономить память там где ее мало, было бы супер.

svbHiTek
Автор

Ух...., запустил ШИМ на отладочной плате stm32f030f4, есть там светодиод пользовательский на РА4 ножке, подключен он а каналу 1 таймера 14

svbHiTek
Автор

Спасибо, а как сдвинуть по фазе один из сигналов, например на 90*

artvsuturin
Автор

мне одно интересно, не проще в самом начале сбросить одной строчкой, например CR1 = 0 ?
Хотя вроде после сброса МК, там и так всё по 0.

smart_electronics_il
Автор

Надо шим сделать в рамках счета 0-1000, к примеру 200-500. Аппаратно не сделать? Только в прерываниях ногой дрыгать?

hybridinnovate
Автор

А точно нужно включать тактирование ножки при использовании ШИМ?

ciklomat
Автор

Все время вижу глупую ошибку на просторах. На 8:39 пример.

Правильный вариант
TIM1->CR1 &= ~(TIM_CR1_xxx | TIM_CR1_xxx | ..).
Неправильный вариант в видео
TIM1->CR1 &= ~(TIM_CR1_ххх);
TIM1->CR1 &= ~(TIM_CR1_xxx);
...

То есть вместо того чтобы сделать запись все за один раз, ты дергаешь регистр на изменение каждого бита. А одна эта строчка у кортекса это 3 операции: считать, изменить, записать и ты их бессмысленно дублируешь по каждому биту. А регистры как бы volatile то есть не следует оптимизировать.

И ещё, когда тебе нужно сконфигурировать какие то регистры, как в случае инита таймера, когда тебе без разницы что там в них до этого было не нужно по маске сначала что то сбрасывать и потом через или ставить, то есть в 6 операций (чтение/изменение/запись 2 раза), когда можно просто в одну операцию записать нужное значение, естественно понимая что каждый бит значит (но обычно значение reset регистра 0 и все просто).
TIM1->CR1 = (TIM1_CR1_xxx |...);
Сорян, весь Видос не смотрел, на это место просто ткнул и все что увидел. Может ещё б чего сказал.
Вот простейший инит, не самый лучший, с просто константами делителей, но просто для понимания, на прерывание через определенное время, никаких & и | с регистрами таймера, они тут просто не нужны, т.к что было до не имеет значение и нам не нужно сохранять. Понятно что нужно все делать с умом, а не просто не напрягая серое вещество все везде лепить по одному шаблону.

RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;

TIM2->PSC = xxx - 1;
TIM2->ARR = xxx - 1;

// Load PSCR (это если нужно чтоб уже первый раз сработал именно после установленного промежутка, то есть с выставленными делителямя, нужно тут загрузить самостоятельно в теневой)
TIM2->CR1 = TIM_CR1_URS;
TIM2->EGR = TIM_EGR_UG;

TIM2->DIER = TIM_DIER_UIE; // UIE: Update interrupt enable
TIM2->CR1 = (TIM_CR1_ARPE | TIM_CR1_CEN); // CEN: Counter enable, ARPE: Auto-reload preload enable
NVIC_EnableIRQ(TIM2_IRQn);

dekus