Энкодер ужасно удобное устройство для управления, на мой взгляд гораздо удобнее обычных кнопок. Его можно сравнить с переменным резистором, но у энкодера больше преимуществ например:
- Может делать сколь угодно оборотов
- Быстро установить точное значение
У микроконтроллеров ST реализована аппаратная обработка сигналов энкодера, входит она в состав некоторых таймеров.
Энкодеры по конструкции бывают разных типов:
- Механические (контакты)
- Оптические (светодиод, фотоприемник, перфорированный диск)
- Электромагнитные (можно сделать из шагового двигателя)
Я подключил вот такой:

Это механический энкодер с Aliexpress в виде модуля для ардуино. Этот энкодер еще в придачу, кнопкой.
Назначение выводов:
- GND (Общая шина)
- + (Плюс питания)
- SW (Тактовая кнопка)
- DT (Сигнал направления вращения)
- CLK (Сигнал тактовый)
В datasheet написано, что все таймеры общего назначения могут обрабатывать сигналы квадратурных (инкрементальных) энкодеров. Выводы (CLK) и (DT) подключаются к входам таймера (TIMx_CH1) и (TIMx_CH2). Я свой энкодер подключил к TIM3 заработало без проблем.
Код инициализации таймера:
void Encoder_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef encod;
encod.GPIO_Mode = GPIO_Mode_IPD;
encod.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
encod.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_StructInit(&encod);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIMER_InitStructure;
TIM_TimeBaseStructInit(&TIMER_InitStructure);
TIMER_InitStructure.TIM_Period = 180;
//TIMER_InitStructure.TIM_CounterMode = TIM_CounterMode_Down|TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIMER_InitStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_Cmd(TIM3, ENABLE);
}
Получение значения через функцию:
#include "main.h"
char lcd_buff[50];
uint16_t Y,X;
int main(void)
{
cconf_init();
delay_init();
I2C_Configuration();
LCD_init();
LCD_com(0x0C);
Encoder_init();
Timer_init();
while(1)
{
X = TIM_GetCounter(TIM3);
sprintf(lcd_buff,"%04u",X);
LCD_puts(lcd_buff);
LCD_gotoxy(0,0);
}
}
Использование прерывания:
#include "main.h"
char lcd_buff[50];
uint16_t Y,X;
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) != RESET)
{
X = X+1;
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
int main(void)
{
cconf_init();
delay_init();
I2C_Configuration();
LCD_init();
LCD_com(0x0C);
Encoder_init();
Timer_init();
Interrupt_init();
while(1)
{
sprintf(lcd_buff,"%04u",X);
LCD_puts(lcd_buff);
LCD_gotoxy(0,0);
}
}
Видео пример работы:
На этом на верное все, свои вопросы можете оставлять в комментариях. Всего наилучшего вам.
