Как подключить энкодер к STM32.
В одной из прошлых статей про энкодер описывался принцип его работы и способы обработки данных приходящих с него. Описанные способы можно реализовать на простых микроконтроллерах типа Atmega, у более продвинутых, типа STM32, для работы с энкодером предназначен специальный интерфейс, который сам обрабатывает данные, приходящие с энкодера и на основе этих данных увеличивает или уменьшает значение счётного регистра, в зависимости от того в какую сторону было вращение.
Этот интерфейс реализуется с помощью двух каналов(TI1 и TI2) выбранного таймера, у stm32f103vet6 получилось запустить его(энкодер) на третьем и восьмом таймере, также была попытка запустить его на первом таймере, но она не увенчалась успехом. Почитав интернет, выяснил, что есть люди которые то же сталкивались с таким же вопросом, то есть им удавалось запустить энкодер на одном таймере и не удавалось на другом, хотя таймеры были идентичные, как например в моём случае, первый и восьмой таймер.
Сигналы с входов проходят через цифровой фильтр, затем поступают в детектор фронтов. Входной цифровой фильтр нужен для устранения дребезга контактов и по сути представляет собой, декрементирующий(считающий вниз) счётчик, физически дребезг, конечно, не пропадает, но за счёт применения "специального" алгоритма система его не “чувствует”. Детектор фронтов, в зависимости от того возрастающий или спадающий сигнал, устанавливает 1 на соответствующем выводе, TI1F_Rising – возрастающий и TI1F_Falling – спадающий. Далее, сигналы попадают в мультиплексор, определяющий по какому фронту производится захват, а затем в мультиплексор выбора входа.
Выше изображена картинка, отражающая алгоритм работы цифрового фильтра, предположим, что нам известно что сигнал нестабилен в течение 5 выборок, тогда после перехода в новое состояние, в течение 8 выборок(возьмём с запасом), микроконтроллер не должен реагировать на изменение состояния входа. Если через 8 выборок состояние сигнала подтверждается, он передаётся на выход TI1F. С логикой работы разобрались, давайте перейдём к настройке.
Для настройки входного фильтра предназначено битовое поле ICxF в регистре CCMR1, кроме количества выборок, в течение которых микроконтроллер не будет реагировать на входные сигналы, также можно настроить частоту выборок. По сути мы настраиваем время задержки с момента прихода фронта до "подтверждающей" выборки.
Fdts настраивается в регистре CKD, а CK_INT скорее всего TIMxCLK от RCC, N - количество выборок.
В регистре SMCR биты SMS определяют по фронту какого из входов будет вестись подсчёт, а увеличиваться значение счётчика будет или уменьшаться зависит от состояния другого входа, это можно увидеть на картинке ниже.
В регистре CCER — биты CСxP определяет по какому фронту появиться сигнал TIxFP1.
В регистре CCMR1 биты ССxS отвечают за настройку мультиплексора выбора входа.
Значение в регистре ARR определяет до какого значения может изменяться счётчик, когда значение счётчика превысит ARR, счётчик обнуляется.
Узнать направление вращения можно считав значение бита DIR в регистре CR1.
Теперь давайте с помощью энкодера будем по очереди зажигать и гасить светодиоды расположенные на плате.
В приведенном примере при каждом щелчке энкодера значение счетчика будет изменяться на 4.
Энкодер покупал тут.
Этот интерфейс реализуется с помощью двух каналов(TI1 и TI2) выбранного таймера, у stm32f103vet6 получилось запустить его(энкодер) на третьем и восьмом таймере, также была попытка запустить его на первом таймере, но она не увенчалась успехом. Почитав интернет, выяснил, что есть люди которые то же сталкивались с таким же вопросом, то есть им удавалось запустить энкодер на одном таймере и не удавалось на другом, хотя таймеры были идентичные, как например в моём случае, первый и восьмой таймер.
Сигналы с входов проходят через цифровой фильтр, затем поступают в детектор фронтов. Входной цифровой фильтр нужен для устранения дребезга контактов и по сути представляет собой, декрементирующий(считающий вниз) счётчик, физически дребезг, конечно, не пропадает, но за счёт применения "специального" алгоритма система его не “чувствует”. Детектор фронтов, в зависимости от того возрастающий или спадающий сигнал, устанавливает 1 на соответствующем выводе, TI1F_Rising – возрастающий и TI1F_Falling – спадающий. Далее, сигналы попадают в мультиплексор, определяющий по какому фронту производится захват, а затем в мультиплексор выбора входа.
Выше изображена картинка, отражающая алгоритм работы цифрового фильтра, предположим, что нам известно что сигнал нестабилен в течение 5 выборок, тогда после перехода в новое состояние, в течение 8 выборок(возьмём с запасом), микроконтроллер не должен реагировать на изменение состояния входа. Если через 8 выборок состояние сигнала подтверждается, он передаётся на выход TI1F. С логикой работы разобрались, давайте перейдём к настройке.
Для настройки входного фильтра предназначено битовое поле ICxF в регистре CCMR1, кроме количества выборок, в течение которых микроконтроллер не будет реагировать на входные сигналы, также можно настроить частоту выборок. По сути мы настраиваем время задержки с момента прихода фронта до "подтверждающей" выборки.
Fdts настраивается в регистре CKD, а CK_INT скорее всего TIMxCLK от RCC, N - количество выборок.
В регистре SMCR биты SMS определяют по фронту какого из входов будет вестись подсчёт, а увеличиваться значение счётчика будет или уменьшаться зависит от состояния другого входа, это можно увидеть на картинке ниже.
- SMS=‘001’ — счёт ведётся по фронтам TI2FP2
- SMS=‘010’ — счёт ведётся по фронтам TI1FP1
- SMS=‘011’ — счёт ведётся по каждому из фронтов
В регистре CCER — биты CСxP определяет по какому фронту появиться сигнал TIxFP1.
- 1 — по спадающему фронту
- 0 — по возрастающему
В регистре CCMR1 биты ССxS отвечают за настройку мультиплексора выбора входа.
Значение в регистре ARR определяет до какого значения может изменяться счётчик, когда значение счётчика превысит ARR, счётчик обнуляется.
Узнать направление вращения можно считав значение бита DIR в регистре CR1.
- 1 — значение счетчика уменьшается
- 0 — значение счетчика увеличивается
Теперь давайте с помощью энкодера будем по очереди зажигать и гасить светодиоды расположенные на плате.
#include "stm32f10x.h"
void init_tim8()
{
//разрешаем тактирование таймера №8
RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
//конфигурируем выводы к которым подключается энкодер как входы с подтяжкой к питанию
GPIOC->CRL &= ~(GPIO_CRL_CNF6_0 | GPIO_CRL_CNF7_0);
GPIOC->CRL |= GPIO_CRL_CNF6_1 | GPIO_CRL_CNF7_1;
GPIOC->ODR |= GPIO_ODR_ODR6 | GPIO_ODR_ODR7;
//настраиваем фильтр
TIM8->CCMR1 |= TIM_CCMR1_IC1F | TIM_CCMR1_IC2F;
//настраиваем мультиплексор
TIM8->CCMR1| = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
//сигнал TIxFP1 появиться по возрастающему фронту
TIM8->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC2P);
//счет по обоим фронтам
TIM8->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;
//максимальное значение счетчика 11
TIM8->ARR = 11;
//включаем счетчик
TIM8->CR1 |= TIM_CR1_CEN ;
//обнуляем счетный регистр
TIM8->CNT = 0;
}
int main(void)
{
//настраиваем выводы к которым подключен светодиод
RCC->APB2ENR |= RCC_APB2ENR_IOPEEN | RCC_APB2ENR_IOPCEN;
GPIOE->CRL = GPIO_CRL_CNF5_1 | GPIO_CRL_CNF6_1;
GPIOE->ODR |= GPIO_ODR_ODR5 | GPIO_ODR_ODR6;
init_tim8();
while(1)
{
//если значение счетчика равно 4 зажигаем первый светодиод
if(TIM8->CNT == 4)
{
GPIOE->BSRR = GPIO_BSRR_BR5;
}
else
{
GPIOE->BSRR = GPIO_BSRR_BS5;
}
//если значение счетчика равно 8 зажигаем второй светодиод
if(TIM8->CNT == 8)
{
GPIOE->BSRR = GPIO_BSRR_BR6;
}
else
{
GPIOE->BSRR = GPIO_BSRR_BS6;
}
}
В приведенном примере при каждом щелчке энкодера значение счетчика будет изменяться на 4.
Энкодер покупал тут.
Похожие статьи