Энкодер ужасно удобное устройство для управления, на мой взгляд гораздо удобнее обычных кнопок. Его можно сравнить с переменным резистором, но у энкодера больше преимуществ например:
- Может делать сколь угодно оборотов
- Быстро установить точное значение
У микроконтроллеров 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); } }
Видео пример работы:
На этом на верное все, свои вопросы можете оставлять в комментариях. Всего наилучшего вам.