Опубликовано 2015-04-04 22:51:49 автором Ruslan

Подключение энкодера к микроконтроллеру


В этом уроке мы научимся работать с инкрементальным энкодером на микроконтролле. В наш энкодер встроена еще и кнопка. С помощью одного лишь энкодера можно легко осуществлять управление практически любым девайсом! Например, представим себе листание деревовидного меню ( прокрутка - листания меню, нажатие - переход в подкатегорию меню).
Энкодер - это цифровой датчик угла поворота. У нашего инкрементального энкодера 5 контактов. Три (Общий, А и В) отвечают за вращение и 2 - это встроенная кнопка. Сначала разберемся, как подключить энкодер к микроконтроллеру и как с него считывать данные.
С Энкодера выходят два сигнала А и В, сдвинутых на 90 градусов по фазе. Выводы A и B должны быть подтянуты к плюс питанию резистором в 1 кОм для избежания ложных срабатываний, а центральный - на землю. Я, для надежности, подключил внешнюю подтяжку. Существуют два распространенных алгоритма опроса энкодера:
  • Опрос при помощи прерываний этот метод прост в использовании, но возможны ложные срабатывания когда энкодер раздолбается. Суть заключается в следующем. Настраиваем прерывание по восходящему фронту и подключаем его к каналу А, в обработчике прерывания проверяем канал В, и дальше проще некуда: если там высокий уровень — делаем '+1', если низкий '-1' нашему счетчику импульсов.
  • Опрос со сравнением предыдущего состояния энкодера и текущего этот метод немного сложнее предыдущего, но боле надежен. В процессе работы, микроконтроллер циклически опрашивает энкодер и сравнивает то, что он считал, с результатом предыдущего считывания. В зависимости от результата сравнения, программа делает выводы о направлении вращения.

Напишем простую программу которая будет опрашивать энкодер и выводить на дисплей переменную, которая будет меняться в зависимости от направления вращения энкодера

Пример кода

#include <mega8.h> 
#include <stdio.h> 
#include <delay.h> 
#include <alcd.h> 
unsigned char lcd[32],enc=0,NewEncState,PrevEncState,z=0; 
 
void MyscanEncoder() 
      {      
      unsigned char OUTB=PINB; 
      NewEncState = OUTB & 0b00011000;            // наш энкодер подключен к выводам 4 и 5 порта B  
      NewEncState = NewEncState>>3;               // делаем сдвиг на 3 для удобства  
if (NewEncState!=PrevEncState)                    //проверяем, изменилось ли состояние на выходе энкодера 
{    
    enc=(enc<<2) | NewEncState;                   //записываем состояние выводов в enc, предварительно сдвинув на 2, чтобы не затереть старые состояния 
    if (enc == 0b11100001) { enc=0; z++; }        //проверяем, совпадает ли последовательность состояний выводов энкодера с поворотом вперед 
    else if (enc == 0b11010010) { enc=0; z--; };  //проверяем, совпадает ли последовательность состояний выводов энкодера с поворотом назад 
    PrevEncState = NewEncState;	                  //новое состояние становится предыдущим 
} 
}  
 
// таймер, в котором будем опрашивать наш энкодер 
interrupt [TIM0_OVF] void timer0_ovf_isr(void) 
{ 
  MyscanEncoder();       // опрос энкодера 
} 
 

void main(void) 
{ 
// Input/Output Ports initialization 
// Port B initialization 
PORTB=0b00011000; 
DDRB=0x00; 
 
// Timer/Counter 0 initialization 
// Clock source: System Clock 
// Clock value: 500,000 kHz 
TCCR0=0x01; 
TCNT0=0x00; 
 
// Timer(s)/Counter(s) Interrupt(s) initialization 
TIMSK=0x01; 
 
// Alphanumeric LCD initialization 
lcd_init(16); 
 
// Global enable interrupts 
#asm("sei") 
 
while (1) 
      { 
      // формируем строку для вывода на дисплей   
      sprintf(lcd,"encoder= %i",z); 
         lcd_clear();      //чистим дисплей перед выводом 
         lcd_puts(lcd);    // выводим строку на дисплей 
         delay_ms(200);    // делаем задержку 
      } 
} 

   		

Комментарии - (1)

Добавить комментарий

Для отправки комментария вы должны авторизоваться.