MPLAB® Code Configurator and Encoder

Просмотров: 1365


Еще раз про энкодер…

Для некоторых приложений очень удобно и экономически выгодно, для настройки и управления использовать энкодер. Такие энкодеры имеют строенную тактовую кнопку которую можно применить для выбора режимов работы устройства. В настоящей статье пойдет речь об энкодерах формирующих код “Грея”. Их формируемая последовательность несколько отличается от классической.

Принцип обработки данных с такого энкодера прост. Вся работа происходит по прерываниях формируемых с портов микроконтроллера к которому он подключен. Мы должны иметь данные с текущего прерывания и с предыдущего. Обрабатывать данные когда состояния контактов R и L при этом вращение в “право” (условно) когда предыдущие флаги имеют высокий уровень, вращение “влево” когда предыдущее прерывание в право низкий, а влево высокий.

Подключение энкодера:

 Подключение выполним к портам которые имеют свойства формировать прерывание по изменению состояния. Их можно выбрать из таблицы описания ног микроконтроллера. Для PIC16F1509 выглядит так:

В колонке Interrupt где стоит символ IOC напротив вывода можно использовать для работы с энкодером, дополнительно необходимо обратить внимание на колонку Pull-up. На понадобятся включение подтягивающих резисторов, для формирования на входах высокого уровня сигнала, когда контакты энкодера находятся в неактивном состоянии.

Создадим проект с использованием MPLAB® Code Configurator.

Работу начнем стандартно после окончания работы мастера мы должны получить пустой проект:

Запустим MPLAB® Code Configurator:

Нас интересуют конфигурация выводов, выберем

В менеджере пинов отметим порты RD4/RB5/RB6 что будем использовать как входы:

В окне Модуль пинов настроим свойства, обратите внимание на включение подтягивающих резисторов WPU, а также тип прерывания, новые микроконтроллеры  позволяют выбирать положительное или отрицательное событие или любое, но старые серии различают просто прерывание по входу и тип необходимо определять дополнительно. Но с целью универсальности применим тип “любой”, чтобы проект можно было использовать на любом микроконтроллере.

Выполним генерацию:

Наш проект получит следующие файлы:

Откроем файл pin_manager.c МСС выполнил полностью настройку портов и прерываний

    /**
    IOCx registers
    */
    // interrupt on change for group IOCBF - flag
    IOCBFbits.IOCBF4 = 0;
    IOCBFbits.IOCBF5 = 0;
    IOCBFbits.IOCBF6 = 0;
    // interrupt on change for group IOCBN - negative
    IOCBNbits.IOCBN4 = 1;
    IOCBNbits.IOCBN5 = 1;
    IOCBNbits.IOCBN6 = 1;
    // interrupt on change for group IOCBP - positive
    IOCBPbits.IOCBP4 = 1;
    IOCBPbits.IOCBP5 = 1;
    IOCBPbits.IOCBP6 = 1;

    // register default IOC callback functions at runtime; use these methods to register a custom function
    IOCBF4_SetInterruptHandler(IOCBF4_DefaultInterruptHandler);
    IOCBF5_SetInterruptHandler(IOCBF5_DefaultInterruptHandler);
    IOCBF6_SetInterruptHandler(IOCBF6_DefaultInterruptHandler);
   
    // Enable IOCI interrupt 
    INTCONbits.IOCIE = 1;

Он так-же предлагает обработку этих прерываний, по каждому выводу отдельно, но у нас эти функции использовать нет необходимости. Саму обработку прерываний мы можем как обычно видеть в файле interrupt_manager.c

void interrupt INTERRUPT_InterruptManager (void)
{
    // interrupt handler
    if(INTCONbits.IOCIE == 1 && INTCONbits.IOCIF == 1)
    {
        PIN_MANAGER_IOC();
    }
    else
    {
        //Unhandled Interrupt
    }
}

Для удобства опишем порты подключения энкодера в файле pin_manager.c:

#include "../mcc_generated_files/mcc.h" // значение тактовой
//#define FCY _XTAL_FREQ/2                // для макросов задержки



//------------------------------------------------------------------------------
// для функции энкодера
bool DIRLp, DIRRp, FMINUS, FPLUS, FBUTTON, FBUTTON1;     // флаги направления вращения 

/*таймер определения двойного нажатия кнопки энкодкра*/
int timeeREPEAT;                            // таймер повторного нажатия
int click_counter;                          // счетчик нажатий кнопки

/*описание выводов энкодера*/
#define DIRR    PORTBbits.RB5  // 
#define DIRL    PORTBbits.RB6  //
#define BUTTON  PORTBbits.RB4  //

#define CONBUT 50              //константа задержки последовательности нажатия кнопки

//------------------------------------------------------------------------------

Для обработки энкодера изменим функцию PIN_MANAGER_IOC, добавим строки:

//------------------------------------------------------------------------------
bool SDIRR, SDIRL, SENB;  // описание флагов

    __delay_us(200);
    SDIRR=DIRR;  // сосчитать положение энкодера
    SDIRL=DIRL;

    // для вращения сравниваем настоящее состотояние с предыдущим
    // (код Грея)
    if(!SDIRR && !SDIRL && DIRRp && DIRLp)
    {
        FPLUS=1;     // признак вращения вправо
    }
    else if(!SDIRR && !SDIRL && !DIRRp && DIRLp)
    {
        FMINUS=1;     // признак вращения влево
    }
    else if(!BUTTON)// обработка нажатия кнопки
    {
        __delay_ms(10); // подавление дребезга
        SENB=BUTTON;
        if(!BUTTON && !timeeREPEAT)
        {
            FBUTTON1=1;        // признак нажатия кнопки энкодера
            timeeREPEAT=CONBUT;     // инициализация таймера
            click_counter=0;//
        }
        else if(!SENB && timeeREPEAT)
        {
            click_counter++; // подсчитываем количество нажатий
            timeeREPEAT=CONBUT;      // инициализация таймера
        }
    }

    DIRRp=SDIRR;     // запомнить предыдущее состояние
    DIRLp=SDIRL;

    // Clear the flag
    INTCONbits.IOCIF=0;

При возникновении прерываний, запомним состояние входов (__delay_us(200); необходим для предварительного фильтрации звона механики). Далее выполняем логическую определения направления вращения энкодера:

    if(!SDIRR && !SDIRL && DIRRp && DIRLp)
    {
        FPLUS=1;     // признак вращения вправо
    }
    else if(!SDIRR && !SDIRL && !DIRRp && DIRLp)
    {
        FMINUS=1;     // признак вращения влево
    }

Для энкодера с “обычным” кодированием, вариант определения направления:

    // для вращения сравниваем настоящее состотояние с предыдущим
//    if(!SDIRR && !SDIRL && DIRRp && DIRLp)     // (код Грея)
    if(SDIRR && SDIRL && !DIRRp && DIRLp)       // (обычный режим)
    {
        FPLUS=1;        // признак вращения вправо
    }
//    else if(!SDIRR && !SDIRL && !DIRRp && DIRLp)     // (код Грея)
    else if(!SDIRR && !SDIRL && !DIRRp && DIRLp)    // (обычный режим)
    {
        FMINUS=1;       // признак вращения влево
    }

По окончанию прерываний необходимо запомнить текущее состояние флагов:

    DIRRp=SDIRR;     // запомнить предыдущее состояние
    DIRLp=SDIRL;

На этом было бы все если бы все ограничивалось энкодерами без тактовой кнопки. Для управления тактовой кнопкой добавим не только функцию контроля нажатия кнопки, но и счетчик нажатий, это может быть удобно для организации много уровненных функций. Для контроля обработки нажатий кнопки нам потребуется ввести дополнительную задержку в 10 мС для подавления дребезга. Для подсчета нажатий необходимо будет воспользоваться таймером, для определения времени в котором определяется функция нажатия кнопки.

Логика работы проста, нажимается кнопка, инициализация таймера, пока идет отсчет времени, если следующее нажатие происходит до окончания работы таймера, то выполняется подсчет нажатий, если таймер “отработал” формируется флаг нажатия кнопки и пользователь может определить количество выполненных нажатий.

Перейдем в МСС. Для настройки функций таймера надо определиться с системным генератором (что мы не сделали в начале):

Выберем внутренний генератор, тактовая 16 мГц. Настроим таймер 0 для формирования временных интервалов:

Настроим таймер на период 10 мС, для этого выберем делитель 1:256, синхронизацию от системного генератора FOSC/4, зададим в окне периода таймера 10 mc, реально получим 9.984 mc. Установим опцию активировать прерывание от таймера. Выполним генерацию кода:

В функцию INTERRUPT_InterruptManager (файл interrupt_manager.c) будет добавлен блок для таймера:

void interrupt INTERRUPT_InterruptManager (void)
{
    // interrupt handler
    if(INTCONbits.TMR0IE == 1 && INTCONbits.TMR0IF == 1)
    {
        TMR0_ISR();
    }
    else if(INTCONbits.IOCIE == 1 && INTCONbits.IOCIF == 1)
    {
        PIN_MANAGER_IOC();
    }
    else
    {
        //Unhandled Interrupt
    }
}

В функцию TMR0_ISR(); добавим обработку нашего таймера:

void TMR0_ISR(void)
{

    // Clear the TMR0 interrupt flag
    INTCONbits.TMR0IF = 0;

    TMR0 = timer0ReloadVal;

    if(TMR0_InterruptHandler)
    {
        TMR0_InterruptHandler();
    }

    // add your TMR0 interrupt custom code
    //--------------------------------------------------------------------------
    if(timeeREPEAT)timeeREPEAT--;   // обработка таймера
    else if(FBUTTON1)
    {
        FBUTTON1=0;
        FBUTTON=1; // установить флаг нажатие кнопки
    }
    //--------------------------------------------------------------------------
}

Не забудьте, что-бы переменные из файла pin_manager.c были доступны в файле tmr0.c их надо описать как внешние. В файле pin_manager.h добавьте строки:

#include "stdbool.h"        // для определения булевых функций

//------------------------------------------------------------------------------
// для функции энкодера
extern bool FMINUS, FPLUS, FBUTTON, FBUTTON1;     // флаги направления вращения 

/*таймер определения двойного нажатия кнопки энкодкра*/
extern int timeeREPEAT;                            // таймер повторного нажатия
extern int click_counter;                          // счетчик нажатий кнопки
//------------------------------------------------------------------------------

И подключите его к файлу tmr0.c добавив в заголовок:

#include "pin_manager.h"

Имея в своём распоряжении флаги вращение в право FPLUS, вращение влево FMINUS. нажатие кнопки FBUTTON, а также счетчик нажатий click_counter, можно строить разнообразные системы управления на энкодере.

Пример функции получения данных с энкодера может такой:

//------------------------------------------------------------------------------
void Encoder (void) // обработка параметра энкодером
{
    // контроль вращения энкодера
    if(FPLUS)
    {
        FPLUS=0;    // сбросить флаг
        if(value<30000) value++;    // увеличить параметр
    }
    else if(FMINUS)
    {
        FMINUS=0;   //сбросить флаг
        if(value>-30000)value--;    // уменьшить параметр
    }
    else if(FBUTTON) // функции кнопки
    {
        if(!click_counter)          // для 1 клика
        {

            value=0;                // установить парметрв ноль

        }
        else if(click_counter==1)   // для двойного клика
        {
            value=10;               //.................
        }
        else if(click_counter==2)   // для тройного
        {
            value=10;
        }
//        else if(click_counter==3) // 4 клика
//        {
//
//        }
//        else if(click_counter==4) value=40;
//        else if(click_counter==5) value=50;
        FBUTTON=0;
    }
}
//------------------------------------------------------------------------------

Проект для тестирования

Значок

MPLAB® Code Configurator and Encoder 317.13 KB 115 downloads

Пример создания кода для управления функциями...



Это может быть интересно


  • Часы-кухонный таймерЧасы-кухонный таймер
    Просмотров: 3798 Каждая кухня должна иметь кухонный таймер, который позволяет напоминать хозяйке когда проходить определенный промежуток времени. Например, печем пирог, варим яйца… , чтобы не смотреть постоянно на часы, установим таймер и …
  • VU Meter Tower ARTVU Meter Tower ART
    Просмотров: 1553 Стерео индикатор уровня аудио сигнала. Компактность и удобство проектирования устройств на светодиодах WS2812B, а также легкость реализации алгоритма родило идею созданию своей конструкции. В этом проекте я предоставлю …
  • Униполярный шаговый двигательУниполярный шаговый двигатель
    Просмотров: 2089     В приводах различных устройств часто применяются шаговые двигатели, Шаговый двигатели различают двух типов униполярные – когда обмотки коммутируются током текущим только в одну сторону, например при …
  • Сумеречное релеСумеречное реле
    Просмотров: 1372 Реле управления освещением, датчик день-ночь – одним словом фотореле для управления освещением или формирования сигнала для системы умный дом о понижении или повышении освещенности относительно заданного уровня. Реле выполнено по классической схеме, конденсаторный блок питания, от сети переменного тока …
  • Акриловый корпус для платы ch-4000Акриловый корпус для платы ch-4000
    Просмотров: 617 Плата ch-4000 подходит для монтажа в корпуса на дин рейку, но для домашней автоматики необходимо что-то другое, поэтому был разработан корпус из акрила который позволит создавать настольные и настенные устройства. Корпус …
  • Audio-bluetooth modules BK8000L (noname)Audio-bluetooth modules BK8000L (noname)
    Просмотров: 607 Еще один вариант, так сказать недоразумения Audio-bluetooth modules BK8000L (noname). Его отличительной маркировкой служат два отверстия в плате и надпись R2. Отличают его от модулей на чипе BK8000L, …
  • Дифференциальный терморегуляторДифференциальный терморегулятор
    Просмотров: 3921 Дифференциальный терморегулятор ch-3020 Назначение. Ch-c3020 представляет собой дифференциальный терморегулятор. Основное назначение солнечные системы горячего водоснабжения, а также вентиляционные системы управление притоком свежего воздуха. Контроллер позволяет работать пяти режимах. …
  • I2C MODULE – PIC18F25K42 Device ID Revision = A001I2C MODULE – PIC18F25K42 Device ID Revision = A001
    Просмотров: 1016 I2C MODULE Обход ошибок в версии I2C MODULE – PIC18F25K42 Device ID Revision = A001 В Серии K42 применен совершенно новый модуль шины I2C, который позволяет поддерживать все …
  • Цифровой спидометр для автомобиляЦифровой спидометр для автомобиля
    Просмотров: 10105  Универсальность печатной платы ch-c0030pcb позволяет создавать на её основе разнообразные устройства. Одним из таких устройств является электронный спидометр для автомобиля, в котором можно задать два компаратора скорости, например,  для …
  • Система отопления на солнечных коллекторах от Дмитрия (rv3dpi)Система отопления на солнечных коллекторах от Дмитрия (rv3dpi)
    Просмотров: 3103 Солнечные коллекторы для отопления в Европе используют в более 50% от общего количества установленных гелиосистем. Однако следует понимать, что гелиосистемы предназначены лишь для поддержки отопления и экономии затрат на основную …



Поделись этим!

Catcatcat

catcatcat

Development of embedded systems based on Microchip microcontrollers.

Продолжайте читать

НазадДалее