STM32 STM32VL Discovery STM32F100RBT6 (урок 4) Basic timers, таймеры

0

Восстановленные материалы удаленного сайта www.doneathome.ru

По многочисленным просьбам пользователей попробую восстановить

STM32VL Discovery STM32F100RBT6 (урок 4) Basic timers, таймеры

Таймер – одна из самых полезных вещей в микроконтроллере и основная его задача – отсчитывание точных интервалов времени. На отладочной плате STM32VL Discovery установлен микроконтроллер STM32F100RBT6, который имеет следующие таймеры:
Basic timers (TIM6, TIM7) – самый простой таймер, который умеет только генерировать прерывания в заданный промежуток времени, но при этом очень легко настраивается и управляется.
General-purpose timers (TIM2-TIM4, TIM15-TIM17) – более продвинутый таймер, позволяющий генерировать ШИМ, считывать состояние ног, обрабатывать данные от энкодера и т.д.
The advanced-control timers (TIM1) – самый продвинутый таймер, может использоваться как трехфазный ШИМ генератор, например для управления трехфазными электродвигателями.

Устройство Базовых таймеров/счётчиков. Basic Timers

Набор разных сведений про базовые таймеры/счётчики. Basic Timers
1) Как называется обработчик для определенного прерывания
В этом файле смотрим прототипы обработчиков startup_stm32f10x_md_vl.c
2) Изменение пред делителя в любой момент
Менять можно когда угодно но оно поменяется после прерывания
3) Принудительный вызов прерывания
Можно программно вызвать принудительно вызвать (UDE) или (UIF)

Регистры (TIM6 & TIM7)

TIMx_CR1 [0x0000]

Описание: Регистр управления 1.
Биты:
Bit 7    ARPE:    Auto-reload preload enable
Описание: 
Бит управления буферизацией регистра TIMx_ARR (смена происходит моментально или после события прерывания)

Bit 3    OPM:    One-pulse mode
Описание: 
Ставится для включения режима одиночного счета счетчика.

Bit 2    URS:    Update request source
Описание: 
Бит выбирает возможные источники для прерывания и DMA (1 – только переполнение счетчика)

Bit 1    UDIS:    Update disable
Описание: 
Бит разрешает/запрещает  возможность генерирования прерывания или DMA.
Интересно что разрешение это ’0′, а запрет ’1′(для уверенности уточните в документации)

Bit 0    CEN:    Counter enable
Описание:
 Бит вкл/выкл работы таймера. (1 – счет запущен)

TIMx_CR2  [0x0000]

Описание: Регистр управления 2. Эти биты устанавливают значение выходного сигнала в режиме “Master – Slave”, когда один таймер управляет другими устройствами в составе микроконтроллера.
Биты:
Bits 6:4    MMS[2:0]:    Master mode selection
000 – формируется сигнал RESET (бит UG)
001 – формируется сигнал ENABLE (бит CEN)
010 – формируется сигнал UPDATE (таймер досчитал)

TIMx_DIER  [0x0000]

Описание: Здесь всего два значащих бита, которые разрешают запрос DMA и генерацию прерывания – UDE (DMA) и UIE (прерывание). “1” – можно, “0” – нельзя. (разрешается единицей).
Биты:
Bits 8    UDE:    Reserved, must be kept at reset value.
Описание: 
Этот бит ставится программно, разрешить UDE (DMA).

Bits 0    UIE:    Update interrupt enable
Описание: 
Этот бит ставится программно, разрешить UIE (прерывание).

TIMx_SR  [0x0000]

Описание: Это регистр статуса. Всего один значащий бит UIF – флаг прерывания. умолчанию. Устанавливается в единицу.
Биты:
Bits 8    UIF:    Update interrupt flag.
Описание: 
Этот бит ставится аппаратно, (UIF) – флаг прерывания.

TIMx_EGR  [0x0000]

Описание: Это регистр статуса. Всего один значащий бит UG. Его установка (программно) принудительно вызовет формирование события – прерывание или запрос DMA.(зависит от того что разрешено)
Биты:
Bits 8    UG:    Update generation.
Описание: 
Этот бит ставится программно, чтобы принудительно вызвать (UDE) или (UIF) .

TIMx_CNT  [0x0000]

Описание: Этот регистр содержит значение счета, так как это счетный регистр. Каждый такт частоты увеличивает значение этого счетчика на единицу. Необходимо предварительно включить таймер.

TIMx_PSC  [0x0000]

Описание: Этот регистр содержит биты для  определения результирующей частоты работы счетчика. Вот формула расчета результирующей частоты работы (частота называется CK_CNT) расчет fck/(PSC[15:0] + 1)

TIMx_ARR  [0x0000]

Описание: Этот регистр содержит биты, которые определяют до какого значения надо досчитывать счетчику. Это регистр автоперезагрузки (сравнения).

Практика

Порядок запуска таймера таков:
1. Подать тактирование на выбранный таймер. Через RCC. Все таймеры сидят на шине APB1, и, соответственно, включаются с помощью регистра RCC_APB1EN. 
2. Назначить предделитель, записав необходимое число в регистр TIMx_PSC (это необходима для формирования частоты счета, которая считается исходя из частоты шины APB1). Частота счёта будет определяться как Ftclk / (TIMx_PSC + 1). Например, если частота шины APB1  24 МГц, а TIMx_PSC равен 2399, то частота счёта (с какой скоростью будет увеличиваться значение счётчика) будет равна 24 / (2399 + 1) = 1 МГц.
3. Назначить максимальное значение счётчика, при коем он будет перезагружаться, записав его в TIMx_ARR. При наличии там нуля, таймер работать не будет.
4. Установить флаг разрешения счёта (CEN в TIMx_CR1).

Пример

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
 
 
void Init_Pin (void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); // это функция разрешения тактирования порта С
 
    GPIO_InitTypeDef Pinyshka; // создаём переменную (структуру) для ножки
 
    // заполняем поля структуры для определения режима ножки(ЗАМЕТИМ определение 2-ух ножек)
    Pinyshka.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_8;  // определяем ножки!!! порта
    Pinyshka.GPIO_Mode = GPIO_Mode_Out_PP; // определяем режим работы ножки
    Pinyshka.GPIO_Speed = GPIO_Speed_50MHz; // так как режим на выход то определяем скорость работы ножки
 
    // этой функцией мы определяем работу ножек (ссылка на заполненную структуру ножки) + (указываем порт необходимых нам ножек)
    GPIO_Init( GPIOC , &Pinyshka);
}
 
 
void Init_timer(void){
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // включаем тактирование таймера
   // Другие параметры структуры TIM_TimeBaseInitTypeDef не имеют смысла для базовых таймеров.
 
    TIM_TimeBaseInitTypeDef base_timer;
   // TIM_TimeBaseStructInit(&base_timer);
  /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */
    base_timer.TIM_Prescaler = 24000 - 1; // делитель 24000
    base_timer.TIM_Period = 1000; //период 1000 импульсов
    TIM_TimeBaseInit(TIM6, &base_timer);
 
    // Разрешаем прерывание по обновлению счётчика таймера TIM6.
    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM6, ENABLE);  // Включаем таймер
 
    // Разрешаем обработку прерывания по переполнению счётчика таймера TIM6.
    NVIC_EnableIRQ(TIM6_DAC_IRQn);// это же прерывание отвечает и за опустошение ЦАП.
}
 
void TIM6_DAC_IRQHandler(){
 
	static uint8_t Flag = 0; // Определяем чет/нечетн вход в обработчик
 
	// Проверяем от таймера ли прерывание
    if (TIM_GetITStatus(TIM6, TIM_IT_Update) == SET) {
      Flag = ~Flag; // инвертируем значение флага
 
      if(Flag) { //по флагу определяем ЛОГ уровни на светодиодах
  		GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);
  		GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_SET);
  	  }
      else {
  		GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET);
  		GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_RESET);
	  }
    /* Очищаем бит обрабатываемого прерывания */
      TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
    }
}
 
 
int main(void) {
 
	Init_Pin(); // инициализация ножек (светодиодных)
	Init_timer(); // инициализация таймера 6
 
    while (1); // безконечный цикл
    return 0;
}

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x