Энкодер / декодер в Xmega

    Вращающиеся энкодеры, также называемые пульсаторами, используются для создания дружественных человекe компьютерных интерфейсов. Есть много параметров, которые легче регулировать, поворачивая ручку, чем вводить числовые значения с клавиатуры. В радиоприемниках для регулировки громкости использовались потенциометры, и в настоящее время в эпоху цифровых технологий используются энкодеры. Устройство, в котором мы можем найти несколько или даже более дюжины энкодеров, - это осциллограф. Микроконтроллеры XMEGA позволяют очень просто использовать энкодеры благодаря системе событий и встроенному квадратурному декодеру.

    Энкодер имеет контакты, обозначенные буквами A и B и массой. Если энкодер может быть нажат, то есть еще две ножки. Штыри A и B должны быть подключены к источнику питания с помощью подтягивающих резисторов - к счастью, XMEGA оснащается такими, и нам не нужно добавлять отдельные. Внутри него есть два контакта, которые закорочены на землю в зависимости от положения ручки. Поворачивая ручку, мы получим формы сигналов, такие как на рисунке ниже - смещение на 90º в зависимости от направления вращения. Благодаря аппаратным декодерам, которые находятся в микроконтроллерах XMEGA, нам не нужно углубляться в детали и внимательно изучать эти формы сигналов. Декодер сделает все для нас, и положение ручки будет легко и быстро прочитано с использованием регистра CNT таймера.
    В начале функции main () нам нужно настроить контакты, которые будут использоваться энкодером. Мы устанавливаем их как входы и включаем внутренние подтягивающие резисторы. Поскольку контакты, используемые энкодером, расположены в одном порту, мы можем использовать регистр PORTCFG.MPCMASK для их настройки и определения того, какие контакты мы хотим настроить в нем. Затем, после ввода соответствующих значений в регистре PORTx.PINxCTRL , эти настройки будут скопированы в регистр управления каждого вывода, указанного в MPCMASK . Таким образом, мы можем быстро настроить контакты C1 и C0, которые мы подключаем к энкодеру.
PORTCFG.MPCMASK = 0b00000011 ;
PORTC.PIN0CTRL = PORT_ISC_LEVEL_gc | PORT_OPC_PULLUP_gc;
    Затем перейдите к настройке системы событий. В регистре EVSYS.CH0MUX мы указываем первый из двух контактов, используемых энкодером. Помните, что энкодер должен быть подключен к соседним контактам!
    Каждый канал системы событий имеет свой собственный регистр управления. Давайте посмотрим фрагмент документации для этого регистра на рисунке. Нам интересен бит QDEN , который запускает квадратурный декодер. Другие параметры, связанные с декодером, связаны с индексированными кодами. Полезной вещью, которую мы все еще можем установить в этом регистра, является цифровой фильтр. Цифровой фильтр распознает сигнал, если он остается на входе дольше, чем выбранное количество тактовых циклов. Установите фильтр на восемь циклов.

EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN0_gc; 
EVSYS.CH0CTRL = EVSYS_QDEN_bm | EVSYS_DIGFILT_8SAMPLES_gc;
    Квадратурный декодер является передатчиком события, а приемник должен быть таймером, который будет считать принятые импульсы. Для этого воспользуемся таймером C0. В регистре CTRLA , нам нужно определить источник сигнала синхронизации в нем. Это, конечно, канал 0 системы событий. В регистре CTRLD мы должны настроить таймер так, чтобы он мог правильно принимать импульсы из декодера. В частности, важно, чтобы таймер знал, когда нужно увеличить его значение, и когда его уменьшить, в зависимости от направления вращения энкодера.
TCC0.CTRLA = TC_CLKSEL_EVCH0_gc;
TCC0.CTRLD = TC_EVACT_QDEC_gc | TC_EVSEL_CH0_gc; 
    Теперь достаточно добавить простую процедуру, показывающую статус счетчика на ЖК-дисплее. Следует помнить, что один импульс энкодера увеличивает или уменьшает значение таймера на 4 - поэтому перед отображением значения регистра TCC0.CNT мы должны сначала делить его на 4.

#define F_CPU 2000000UL

#include <avr / io.h>
#include <util / delay.h>
#include "hd44780.h"

int  main ( void )  
{
PORTCFG.MPCMASK = 0b00000011 ; 
PORTC.PIN0CTRL = PORT_ISC_LEVEL_gc |  PORT_OPC_PULLUP_gc; 
EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN0_gc; 
EVSYS.CH0CTRL = EVSYS_QDEN_bm | EVSYS_DIGFILT_8SAMPLES_gc;   
TCC0.CTRLA = TC_CLKSEL_EVCH0_gc;
TCC0.CTRLD = TC_EVACT_QDEC_gc  |  TC_EVSEL_CH0_gc; 
LcdInit();
while ( 1 )  
{ 
LcdClear (); 
Lcd ( «CNT =» ); 
LcdDec (TCC0.CNT / 4 ); 
_delay_ms ( 100 ); 
} 
}
    Blogger Comment
    Facebook Comment

0 коммент.:

Отправить комментарий