Настройка таймера STM32 для работы с энкодером




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

Я покажу на примере Stm32f103c8. В этом микроконтроллере всего 4 таймера.
TIM1 - продвинутый, мы его оставим на всякий случай.
TIM2, TIM3, TIM4 - таймеры общего назначения. Для примера возьмем TIM2.

Мы будем использовать два входных канала этого таймера.
Выводы энкодера CLK и DT подключаем к GPIO A15 и GPIO B3. Сейчас неважно, какой сигнал, к какой ноге.
GND к GND контроллера, + к 3.3V платы контроллера.



Настраиваем пины для работы с таймером.

 GPIO_Alternate_Function_Enable(@_GPIO_MODULE_TIM2_CH1_PA15);
 GPIO_Alternate_Function_Enable(@_GPIO_MODULE_TIM2_CH2_PB3);
 GPIO_Set_Pin_Mode(@GPIOA_BASE, _GPIO_PIN_15, _GPIO_CFG_MODE_ALT_FUNCTION);
 GPIO_Set_Pin_Mode(@GPIOB_BASE, _GPIO_PIN_3,  _GPIO_CFG_MODE_ALT_FUNCTION);

Разрешаем тактирование второго таймера.

 RCC_APB1ENR.TIM2EN:= 1;

Перед началом настройки запрещаем работу таймера и отключаем захват на обоих каналах.

 TIM2_CR1.CEN             := 0;          {TIM2 disable}
 TIM2_CCER.CC1E           := 0;          {Capture 1 disable}
 TIM2_CCER.CC2E           := 0;          {Capture 2 disable}

Указываем, что мы работаем с передним фронтом на обоих каналах. Если нужно работать с задними фронтами - пишем в оба бита 1.

 TIM2_CCER.CC1P           := 0;
 TIM2_CCER.CC2P           := 0;

Каналы конфигурируем, как входы, первый канал с TI1, второй - TI2

 TIM2_CCMR1_Input.CC1S0   := 1;          {01: CC1 channel is configured as input, IC1 is mapped on TI1}
 TIM2_CCMR1_Input.CC1S1   := 0;          {01: CC1 channel is configured as input, IC1 is mapped on TI1}

 TIM2_CCMR1_Input.CC2S0   := 1;          {01: CC2 channel is configured as input, IC2 is mapped on TI2}
 TIM2_CCMR1_Input.CC2S0   := 0;          {01: CC2 channel is configured as input, IC2 is mapped on TI2}

В регистре TIM2_SMCR биты SMS 2:0 определяют режим работы таймера:
  1. 001 - режим энкодера 1 - счетчик считает вверх и вниз по выбранному фронту второго канала, направление определяет состояние первого канала. 
  2. 010 - режим энкодера 2 - счетчик считает вверх и вниз по выбранному фронту первого канала, направление определяет состояние второго канала. 
  3. 011 - режим энкодера 3 - счетчик считает вверх и вниз по каждому фронту сигнала на любом канале, направление определяет состояние другого канала. 
  4. 111 - режим прямого счета от внешнего такта, об этом чуть позже. 

 Сейчас мы выбираем режим енкодера 3.

 TIM2_SMCR.SMS0           := 1;          {001: Encoder mode 1 - Counter counts up/down on TI2FP1 edge depending on TI1FP2 level.}
 TIM2_SMCR.SMS1           := 1;          {010: Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level.}
 TIM2_SMCR.SMS2           := 0;          {011: Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input.}

Если все биты SMS 2:0 регистра TIM2_SMCR установлены, мы можем просто считать входящие импульсы с выбранного входа.
В регистре TIM2_SMCR биты TS 6:4 определяют вход внешнего такта:

  1. 101 - вход с первого канала. 
  2. 110 - вход со второго канала.

 TIM2_SMCR.TS0            := 0;          {Trigger selection (If SMS = %111) - external clock}
 TIM2_SMCR.TS1            := 1;          {101: Filtered Timer Input 1 (TI1FP1)}
 TIM2_SMCR.TS2            := 1;          {110: Filtered Timer Input 2 (TI2FP2)}

Этот режим работы может понадобиться для работы с инкрементальным энкодером.

Далее, включаем максимальную фильтрацию на обоих входах. Механические энкодеры без фильтрации нормально работать не будут.

 TIM2_CCMR1_Input.IC1F0   := 1;          {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC1F1   := 1;
 TIM2_CCMR1_Input.IC1F2   := 1;
 TIM2_CCMR1_Input.IC1F3   := 1;

 TIM2_CCMR1_Input.IC2F0   := 1;
 TIM2_CCMR1_Input.IC2F1   := 1;
 TIM2_CCMR1_Input.IC2F2   := 1;
 TIM2_CCMR1_Input.IC2F3   := 1;

По умолчанию, счетчик таймера будет сбрасываться в ноль при переходе через значение 65535.
Если нужно ограничить это значение - вписываем его в регистр TIM2_ARR.
Например, если нам нужно, чтобы счетчик переходил в ноль после числа 20, вписываем число 20 в этот регистр.

Мы почти готовы. Осталось включить таймер и захват.

 TIM2_CCER.CC1E           := 1;          {Capture enable}
 TIM2_CCER.CC2E           := 1;          {Capture enable}
 TIM2_CR1.CEN             := 1;          {TIM2 enable}

Текущее значение счетчика можно взять в регистре TIM2_CNT.

Полный листинг процедуры инициализации таймера.

Комментарии

Популярные сообщения из этого блога

PS4 Dualshock инверсия правого стика по оси X за два часа.

Настраиваем показания энкодера для применения в меню