Форум РадиоКот • Просмотр темы – Энкодер в Proteus
Сообщения без ответов | Активные темы
ПРЯМО СЕЙЧАС: |
Автор | Сообщение | ||
---|---|---|---|
|
Заголовок сообщения: Энкодер в Proteus Добавлено: Сб май 30, 2015 11:25:52 |
||
Карма: 7 Рейтинг сообщения: 0
|
Подскажите, коллеги. Есть ли в шпротеусе энкодер? Искал, не могу найти…. |
||
Вернуться наверх |
Профиль
|
||
Реклама | |
|
|
dr.doc
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Сб май 30, 2015 11:42:24 |
||
Карма: 20 Рейтинг сообщения: 0
|
Есть мотор-энкодер. На обмотку через кнопки подаете питание в разной полярности, он вращается, а энкодер выдает импульсы. |
||
Вернуться наверх | |||
Реклама | |
|
|
Dr. Alex
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Сб май 30, 2015 12:51:53 |
||
Карма: 7 Рейтинг сообщения: 0
|
Чего-же так всё запутанно))))) |
||
Вернуться наверх | |||
dr.doc
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Сб май 30, 2015 13:38:48 |
||
Карма: 20 Рейтинг сообщения: 0
|
Он же в проекте. |
||
Вернуться наверх | |||
Реклама | |
|
25.05.2023 Вебинар «Источники питания MORNSUN: новинки для промавтоматики и оптимальные решения для телекоммуникации»
Приглашаем на вебинар, посвященный новой продукции MORNSUN для промышленной автоматизации и телекоммуникационных приложений. Подробнее>> |
Dr. Alex
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Сб май 30, 2015 13:44:25 |
||
Карма: 7 Рейтинг сообщения: 0
|
Ты бы ещё HEX приложил…. |
||
Вернуться наверх | |||
Реклама | |
|
|
dr.doc
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Сб май 30, 2015 14:24:53 |
||
Карма: 20 Рейтинг сообщения: 0
|
Пожалуйста. |
||
Вернуться наверх | |||
Dr. Alex
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Сб май 30, 2015 14:30:52 |
||
Карма: 7 Рейтинг сообщения: 0
|
Спасибо, познавательно. . Пробую в своём проекте |
||
Вернуться наверх | |||
dm211
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Вт июн 02, 2015 11:17:29 |
Нашел транзистор. Понюхал.
Карма: 5 Рейтинг сообщения: 0
|
Есть специальная библиотека энкодера. |
Вернуться наверх | |
imerlin
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Вт апр 09, 2019 14:23:01 |
Зарегистрирован: Вт июл 16, 2013 11:18:59 Рейтинг сообщения: 0
|
Hi All! |
Вернуться наверх | |
СКАЗОЧНИК
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Вт апр 09, 2019 14:47:40 |
||
Карма: 133 Рейтинг сообщения: 0
|
|||
Вернуться наверх | |||
imerlin
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Вт апр 09, 2019 15:24:33 |
Зарегистрирован: Вт июл 16, 2013 11:18:59 Рейтинг сообщения: 0
|
Извините. Добавлено after 5 minutes 52 seconds: Да, забыл про “чем измеряете” – осциллом протеусовским вестимо. Добавлено after 12 minutes 14 seconds: Не то что бы очень нужно было, мне хватает тех выводов, которые сдвинутые меандры генерирует, но просто интересно, что за странный такой вывод… |
Вернуться наверх | |
СКАЗОЧНИК
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Вт апр 09, 2019 15:36:50 |
||
Карма: 133 Рейтинг сообщения: 0
|
Хм… Ну, здесь извиняйте. Протеуса не установлен, посмотреть не могу. Думал, вы про нормальный железный энкодер говорите. ))) |
||
Вернуться наверх | |||
Ivanoff-iv
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Пт май 17, 2019 06:58:01 |
||
Карма: 44 Рейтинг сообщения: 0
|
да, это индикатор 0 позиции (импульс 1 раз за оборот не зависимо от настроек энкодера) |
||
Вернуться наверх | |||
Alti
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Пн июн 24, 2019 09:07:07 |
||
Зарегистрирован: Чт окт 06, 2011 21:49:44 Рейтинг сообщения: 0
|
Модель энкодера с дребезгом. На базе ATMEGA8
|
||
Вернуться наверх | |||
АлександрЛ
|
Заголовок сообщения: Re: Энкодер в Proteus Добавлено: Пн июн 24, 2019 18:20:41 |
||
Карма: 182 Рейтинг сообщения: 2
|
что делает средний вывод в энкодере? По наблюдениям время от времени выдает импульсы, но как то нерегулярно, по наблюдениям я закон их чередования вывести не смог… “крутнул” энкодер ООООчень медленно вот такой схемой: |
||
Вернуться наверх | |||
Кто сейчас на форуме |
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12 |
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения |
Бывает, что нужно собрать схему в протеусе, которую можно было по человечески читать. Один путь решения проблемы это создание моделей и привязка к графическому символу. Но это не короткий и не быстрый путь, плюс я не настолько серьезно отношусь к нему (просто мне нравится что много домашних проектов можно отлаживать прямо в нем).
Попробуем например создать модель энкодера, которого к сожалению нету в штатной библиотеке протеуса. Для начала нарисуем графический символ, обозначающий наш энкодер. Я набросал такой вид:
Не забываем, что нужно добавлять правильные пины на символ, они находятся в пункте “Пины устройства”.
Далее нужно сохранить устройство в библиотеке, для этого выделяем все устройство, нажимаем правой кнопкой мыши и “Создать устройство”. Дальше по пунктам интуитивно все заполняем. Ничего сложного.
Энкодер я строю по принципу, о котором писал в прошлой статье (речь идет о двух сигналах смещенных друг относительно друга на определенную фазу). Сначала создадим схему эмулятор:
Вкратце о схеме, три источника прямоугольных импульсов, p90 смещен относительно p0 на 90 градусов, второй на 270. На два выхода с помощью реле комутируется либо p0 и p90, либо p0 и p180. Пины Up и Down предназначены для подключения кнопки, пины A и C – выходы энкодера.
Частота источников 50 Гц. Я подумал что врядли может быть больше импульсов за оборот ручки.
Далее создаем нашу схему, вставляем наш энкодер, тыкаем свойства и ставим галочку “Присоеденить иерархический модуль”. Потом, нажимаем на модели правой кнопкой и переходим на дочерний лист. Там и вставляем схему с реле. Вот в принципе все и готово.
Дальше можно в схему добавлять мк и тестировать на симуляторе.
Отслеживание всех состояний энкодера
Методист по олимпиадной робототехнике Университета Иннополис Алексей Овсянников продолжает серию уроков. Читайте, как легко и просто отслеживать все возможные состояния (фазы) энкодера.
Продолжаю публиковать материалы для слушателей курсов повышения квалификации по робототехнике. В одной из прошлых статей я рассказал про обработку сигналов энкодера в Arduino. Сегодня я хотел бы продолжить эту тему и рассказать, как легко и просто можно отследить все возможные состояния (фазы).
В прошлой статье я привел код для Arduino, позволяющий с помощью прерываний отслеживать только один выход энкодера, а сигнал на втором проверялся уже внутри обработчика и указывал на направление вращения. В результате мы улавливали 11-12 тиков на один оборот диска энкодера. Сегодня разовьем программу и научимся «отлавливать» все возможные состояния, что позволит в 4 раза увеличить точность (улавливать 44-48 состояний на один оборот диска).
Вспомним сигналы, возникающие на двух выходах энкодера:
С каждого энкодера приходит два сигнала. Для полного отслеживания сигналов потребуется их подключать к пинам, поддерживающим прерывания. У общеизвестной «народно любимой» платы Arduino UNO всего лишь два таких пина (2 и 3), то есть к ней получится подключить всего один мотор для полного отслеживания или два мотора, как было описано в прошлой статье. Узнать подробнее о прерываниях можно на официальном сайте. Для экспериментов хватит и UNO, но я сразу переключился на Arduino MKR Zero, которая имеет 9 пинов с прерываниями (до 4 моторов). Код итоговой программы от выбранной платы почти не меняется, только указываются другие пины.
Про подключение подробно не буду рассказывать, для мотора Pololu 75:1 MP 12V выглядит как на фото:
Зеленый провод — «земля» энкодера — соединяем с GND платы
Синий провод — питание энкодера — соединяем с Vcc платы (работает и от 3.3В, и от 5В)
Желтый провод — выход А энкодера — на пин платы с прерыванием
Белый провод — выход B энкодера — на другой пин платы с прерыванием
На красный и черный провода подается питание мотора, я же оставлю их пустыми и буду крутить мотор рукой.
Итак, я подключил выходы А и В энкодера к пинам 6 и 7 Arduino MKR Zero (у Arduino UNO это будут пины 2 и 3). В программе я могу настроить прерывание на переход сигнала из 0 в 1 (передний фронт, RISING), из 1 в 0 (задний фронт, FALLING) или на любое подобное изменение (CHANGE). Для полноты картины придется ловить оба фронта.
В процедурах intAsub и intBsub будет происходить обработка прерываний. Первым делом, в каждой из них считываю и запоминаю текущий сигнал:
и
Внимательно изучим сигналы, приходящие по линиям А и В. При вращении мотора вперед:
При вращении мотора назад:
Зелеными стрелками я обозначил передний фронты, красными — задние. На любой из линий передний фронт возникает при изменении сигнала с 0 на 1, при этом на другой линии еще с прошлого шага стабильно держится какой-то сигнал. Задний фронт возникает при изменении сигнала с 1 на 0, на другой линии опять же с прошлого шага держится какой-то сигнал.
Если следить за прерываниями линии А, то получаем:
Передний фронт А при вращении вперед — на линии В сигнала нет,
Задний фронт А при вращении вперед — на линии В есть сигнал,
Передний фронт А при вращении назад — на линии В есть сигнал,
Задний фронт А при вращении назад — на линии В нет сигнала.
Внимательно смотрим на эти четыре варианта и замечаем, что при движении вперед сигналы sigA (считанный в самом начале прерывания) и sigB (считанный ранее в другом прерывании) отличаются, а при движении назад совпадают. Если не уловили, то остановитесь на этом моменте и еще раз внимательно изучите сигналы. Например, мотор крутится вперед и возникло прерывание на заднем фронте; мы считываем этот сигнал командой digitalRead и видим 0. А на линии В с последнего прерывания той линии хранится значение 1.
Таким образом обработчик прерывания для линии А принимает вид:
Переменная sigB обновляется и актуализируется в другом прерывании.
Если следить за прерываниями линии В, то получаем:
Передний фронт B при вращении вперед — на линии А сигнал есть,
Задний фронт В при вращении вперед — на линии А сигнала нет,
Передний фронт В при вращении назад — на линии А сигнала нет,
Задний фронт В при вращении назад — на линии А сигнал есть.
Внимательно смотрим на эти четыре варианта и замечаем, что при движении вперед сигналы sigA (считанный в самом начале прерывания) и sigB (считанный ранее в другом прерывании) совпадают, а при движении назад отличаются. Обработчик прерываний для линии В:
Вот и все! Не надо никаких сложных алгоритмов, запоминания текущей фазы и сравнивания с предыдущими, не надо хранить сигналы в 8 переменных и выстраивать трехэтажную логику.
Если к контроллеру надо подключить несколько моторов, то придется создавать такие процедуры для каждого пина. На три мотора получится 6 процедур, на 4 мотора 8 процедур и т.д.
Реализовать подобный алгоритм можно на любом контроллере, имеющем достаточно внешних прерываний. Некоторые контроллеры, например STM32, имеют даже аппаратную поддержку подобных энкодеров. Но об этом можно поговорить позже, пока что остановимся на доступной и понятной линейке Arduino, которую просто надо научиться эффективно использовать.
Кстати, итоговый код программы:
Надеюсь, что рассмотренный материал пригодится кому-нибудь при подготовке к олимпиаде Innopolis Open in Robotics. Более подробно о подготовке к олимпиаде мы будем рассказывать на тематических КПК, да и подробнее познакомиться с подобными приемами можно на курсах Arduino.
Теги: arduino, headline, Алексей Овсянников, робототехника, Университет Иннополис
Инкрементальный энкодер представляет собой механическое устройство (датчик) преобразующее угол поворота вала (ручки) в электрические сигналы. Энкодер имеет три вывода, или пять в зависимости от наличия встроенной кнопки. Здесь я рассматриваю наиболее распространенные энкодеры, которые встраивают в бытовую аппаратуру, например, для регулировки громкости, навигации в меню и т.д. В отличие от переменного резистора, положение ручки энкодера меняется дискретно, “щелчками”, при этом происходит несколько коммутаций, последовательность которых зависит от направления вращения. На один полный оборот ручки может приходиться различное количество дискретных положений (12, 20, 24), в зависимости от модели энкодера.
На рисунке ниже представлена функциональная схема поясняющие принцип действия энкодера.
Как видно из временных диаграмм, при повороте на одно дискретное положение (на один “щелчок”), на выводах A и B формируются отрицательные импульсы (полярность импульсов зависит от схемы подключения), сдвинутые по фазе между собой. Сдвиг фаз зависит от направления вращения. Из временной диаграммы можно выделить четыре состояния, которые составляют период одного дискретного изменения (“щелчка”), длительность периода варьируется примерно от 2 мс до 4 мс.
На следующем рисунке представлена схема подключения энкодера к микроконтроллеру:
Выводы A и B энкодера необходимо подтянуть к линии питания +5В с помощью резисторов, также необходимо установить конденсаторы C1 и C2 которые уменьшают влияние дребезга контактов.
Состояние энкодера можно определить используя прерывания по изменению сигнала на выводах микроконтроллера или путем периодического опроса через равные промежутки времени, сравнивая текущее состояние с предыдущим сохраненным значением. Сначала рассмотрим вариант периодического опроса.
Ниже представлен код программы, в которой реализован периодический опрос состояния выводов энкодера. Опрос состояний выводов А и B энкодера выполняется в подпрограмме обработки прерываний, которая периодически вызывается по переполнению таймера TMR0 (см. Таймеры. Организация временной задержки). В моем варианте таймер переполняется примерно через 1 мс, то есть энкодер опрашивается каждую миллисекунду.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
#include <p16f628a .INC> LIST p=16F628A __CONFIG H’3F18′ ;конфигурация микроконтроллера flag equ 20h ;перечисление регистров общего назначения flag1 equ 21h ;присвоение названий адресам регистров shet equ 22h ; shet1 equ 23h ; W_TEMP equ 7Eh ; STATUS_TEMP equ 7Fh ; #DEFINE enc1 PORTB,4 ;присвоение названий линиям ввода-вывода #DEFINE enc2 PORTB,5 ;микроконтроллера ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0000h ;начать выполнение программы с адреса 0000h goto Start ;переход на метку Start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Подпрограмма обработки прерываний org 0004h ;начать выполнение подпрограммы с адреса 0004h movwf W_TEMP ;сохранение значений ключевых регистров swapf STATUS,W ; clrf STATUS ; movwf STATUS_TEMP ; btfsc enc1 ;опрос состояний выводов энкодера и сохранение bsf flag,0 ;полученных значений в регистр flag btfss enc1 ;сохранение значения вывода enc1 в 0-й бит bcf flag,0 ;сохранение значения вывода enc2 в 1-й бит btfsc enc2 ; bsf flag,1 ; btfss enc2 ; bcf flag,1 ; btfss flag,2 ;проверка предыдущего состояния выводов goto vih ;энкодера (2-й и 3-й биты регистра flag) btfss flag,3 ;если оба значения не равны 1 переходим goto vih ;на метку vih, для выхода из обработчика btfss flag1,0 ;проверка флага (0-й бит регистра flag1) goto i2 ;инкремента/декремента регистра shet incf shet1,F ;если флаг не установлен-переходим (метка i2) movlw .3 ;на проверку факта поворота ручки энкодера xorwf shet1,W ;при установленном флаге инкрементируем btfss STATUS,Z ;регистр shet1, проверяем на равенство goto vih ;числу 3, если не равно-переходим на метку bcf flag1,0 ;vih, для выхода из обработчика clrf shet1 ;если shet1 равен 3-очищаем регистр и ;сбрасываем флаг инкремента/декремента ;регистра shet i2 btfsc flag,0 ;определение направления вращения ручки goto i1 ;энкодера, если enc1=1 переходим на метку i1 btfss flag,1 ;если enc1=0 и enc2=1 произошел поворот goto vih ;в положительную сторону (условно) ;соответственно далее по ходу кода производим ;инкремент регистра shet ;состояние enc1=0 и enc2=0 игнорируется- ;переходом на метку выхода vih incf shet,F ;инкемент регистра shet, максимальное значение movlw .0 ;ограничивается на уровне 255 xorwf shet,W ; btfss STATUS,Z ; goto vih1 ; movlw .255 ; movwf shet ; goto vih1 ;переход на метку vih1 i1 btfsc flag,1 ;определение направления вращения ручки goto vih ;энкодера, если enc1=1 и enc2=0 произошел ;поворот в отрицательную сторону (условно) ;соответственно далее по ходу кода производим ;декремент регистра shet ;состояние enc1=1 и enc2=1 игнорируется- ;переходом на метку выхода vih decf shet,F ;декремент регистра shet, минимальное значение movlw .255 ;ограничивается на уровне 0 xorwf shet,W ; btfss STATUS,Z ; goto vih1 ; clrf shet ; vih1 bsf flag1,0 ;установка флага инкремента/декремента регистра shet bsf flag1,1 ;установка флага регистрации поворота энкодера ;для дальнейшего опроса в основной программе vih rlf flag,F ;сдвиг содержимого регистра flag rlf flag,F ;влево на 2 бита bcf INTCON,T0IF ;сброс флага прерывания по переполнению TMR0 movlw .15 ;запись числа 15 в регистр таймера TMR0 movwf TMR0 ;равнозначно временной задержке примерно 1мс swapf STATUS_TEMP,W ;восстановление содержимого ключевых регистров movwf STATUS ; swapf W_TEMP,F ; swapf W_TEMP,W ; ; retfie ;выход из подпрограммы прерывания ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Основная программа Start movlw b’00000000′ ;запись нулей в выходные защелки порта B movwf PORTB movlw b’00000111′ ;выключение компараторов movwf CMCON bsf STATUS,RP0 ;настройка линий вводавывода порта B movlw b’00110111′ movwf TRISB ;запись двоичного числа 11010001 в регистр movlw b’11010001′ ;OPTION_REG, тем самым устанавливаем внутренний movwf OPTION_REG ;источник тактового сигнала для TMR0 bcf STATUS,RP0 ;включаем предделитель перед TMR0 ;устанавливаем коэффициент предделителя 1:4 clrf shet ;очистка дополнительных регистров clrf shet1 ; clrf flag1 ; clrf TMR0 ;очистка регистра таймера TMR0 bcf INTCON,T0IF ;сброс флага прерывания по переполнению TMR0 bsf INTCON,T0IE ;разрешение прерываний по переполнению TMR0 bsf INTCON,GIE ;глобальное разрешение прерываний a1 btfss flag1,1 ;опрос флага регистрации поворота энкодера goto a1 ;флаг регистрации равен нулю: переход на метку a1 bcf flag1,1 ;флаг равен единице: сброс флага регистрации movf shet,W ;вывод содержимого регистра shet на цифровое call vivod ;табло goto a1 …………….. ;подпрограммы вывода содержимого …………….. ;регистра shet на семисегментные индикаторы …………….. ; end ;конец всей программы ;</p16f628a> |
Внутри обработчика прерываний сначала сохраняется текущее состояние выводов энкодера, для этого используется дополнительный регистр flag, содержимое которого всегда перед выходом из обработчика сдвигается влево на два бита, таким образом сохраняется предыдущее состояние выводов энкодера. После сохранения текущего состояния в 0-й и 1-й бит регистра flag, осуществляется проверка предыдущего состояния, то есть анализируются 2-й и 3-й биты. Алгоритм следующий: если предыдущее состояние обоих выводов соответствовало логической единице, проверяем текущее сохраненное значение (биты 0,1 регистра flag), если значение битов равно 0 и 1, произошел поворот в одну сторону, если значение равно 1 и 0, произошел поворот в противоположную сторону. После определения факта поворота происходит инкремент или декремент регистра shet, содержимое которого (число от 0 до 255) в основной программе выводится на семисегментные индикаторы. Инкремент производится до числа 255 и ограничивается на этом значении, даже при дальнейшем повороте ручки энкодера, то же самое и при декременте до 0.
Если предыдущее состояние обоих выводов не соответствует 1, просто выходим из обработчика, также смещая содержимое регистра flag влево. Это необходимо чтобы пропустить все остальные возможные состояния выводов энкодера, то есть для определения направления вращения используется половина периода одного дискретного изменения (два состояния из четырех возможных).
При использовании такого алгоритма выявились некоторые недостатки, сам факт поворота ручки определялся стабильно, но из-за наличия дребезга контактов в конце периода одного дискретного изменения (после “щелчка”), происходило повторное определение факта поворота, причем в обратную сторону. То есть после инкремента регистра shet происходил декремент и наоборот. Чтобы избежать этого, после инкремента/декремента регистра shet, я дополнительно добавил условие для многократной проверки состояния выводов энкодера на соответствие высокому логическому уровню. После инкремента/декремента shet, перед выходом из обработчика прерывания устанавливается флаг (0-й бит) в дополнительном регистре flag1. При последующих входах в обработчик, после проверки предыдущего состояния и соответствия выводов энкодера высокому логическому уровню, по установленному флагу в регистре flag1 происходит инкремент регистра shet1. Если его содержимое не равно числу 3 происходит выход из обработчика. Таким образом, после факта поворота, следующее определение состояния энкодера будет выполняться, при условии трехкратной фиксации высоких логических уровней на выводах энкодера, после чего регистр shet1 обнуляется и сбрасывается флаг регистра flag1.
После изменения значения регистра shet в обработчике прерываний, дополнительно устанавливается флаг регистрации поворота энкодера flag1,1, который опрашивается в основной программе, если флаг установлен вызывается подпрограмма vivod, для вывода содержимого регистра shet на семисегментные индикаторы.
Теперь рассмотрим программу опроса энкодера основанную на прерываниях по изменению уровня на входах микроконтроллера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
#include <P16F628A.INC> LIST p=16F628A __CONFIG H’3F18′ ;конфигурация микроконтроллера flag equ 20h ;перечисление регистров общего назначения flag1 equ 21h ;присвоение названий адресам регистров shet equ 22h ; ; W_TEMP equ 7Eh ; STATUS_TEMP equ 7Fh ; #DEFINE enc1 PORTB,4 ;присвоение названий линиям ввода-вывода #DEFINE enc2 PORTB,5 ;микроконтроллера ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0000h ;начать выполнение программы с адреса 0000h goto Start ;переход на метку Start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Подпрограмма обработки прерываний org 0004h ;начать выполнение подпрограммы с адреса 0004h movwf W_TEMP ;сохранение значений ключевых регистров swapf STATUS,W ; clrf STATUS ; movwf STATUS_TEMP ; btfsc enc1 ;опрос состояний выводов энкодера и сохранение bsf flag,0 ;полученных значений в регистр flag btfss enc1 ;сохранение значения вывода enc1 в 0-й бит bcf flag,0 ;сохранение значения вывода enc2 в 1-й бит btfsc enc2 ; bsf flag,1 ; btfss enc2 ; bcf flag,1 ; btfss flag,0 ;Проверка текущих сохраненных значений состояния goto i3 ;выводов энкодера btfss flag,1 ;если enc1=1 и enc2=1 сбрасываем флаг готовности, goto i3 ;иначе переходим на метку i3 bcf flag1,1 ; i3 btfsc flag1,1 ;проверка флага готовности, если флаг установлен goto vih ;переходим на метку vih btfsc flag,0 ;флаг готовности сброшен:Проверка текущих сохраненных goto vih ;значений состояния выводов энкодера btfsc flag,1 ;если enc1=0 и enc2=0 переходим на метку i2, goto vih ;иначе переходим на метку vih i2 btfsc flag,2 ;проверка предыдущих состояний выводов энкодера goto i1 ;если enc1=1 переходим на метку i1, btfss flag,3 ;если enc1=0 и enc2=1 произошел поворот goto vih ;в положительную сторону (условно) ;соответственно далее по ходу кода производим ;инкремент регистра shet ;состояние enc1=0 и enc2=0 игнорируется- ;переходом на метку выхода vih incf shet,F ;инкемент регистра shet, максимальное значение movlw .0 ;ограничивается на уровне 255 xorwf shet,W ; btfss STATUS,Z ; goto vih1 ; movlw .255 ; movwf shet ; bsf flag1,1 ;произошел инкремент регистра shet (поворот энкодера) ;устанавливаем флаг готовности goto vih1 ;переход на метку vih1 i1 btfsc flag,3 ;проверка предыдущих состояний выводов энкодера goto vih ;если enc1=1 и enc2=0 произошел ;поворот в отрицательную сторону (условно) ;соответственно далее по ходу кода производим ;декремент регистра shet ;состояние enc1=1 и enc2=1 игнорируется- ;переходом на метку выхода vih decf shet,F ;декремент регистра shet, минимальное значение movlw .255 ;ограничивается на уровне 0 xorwf shet,W ; btfsc STATUS,Z ; clrf shet ; bsf flag1,1 ;произошел инкремент регистра shet (поворот энкодера) ;устанавливаем флаг готовности vih1 bsf flag1,0 ;установка флага регистрации поворота энкодера ;для дальнейшего опроса в основной программе vih rlf flag,F ;сдвиг содержимого регистра flag rlf flag,F ;влево на 2 бита exxit movf PORTB,W ;чтение порта B, для устранения несоответствия bcf INTCON,RBIF ;сброс флага прерываний по изменению уровня на RB4-RB7 swapf STATUS_TEMP,W ;восстановление содержимого ключевых регистров movwf STATUS ; swapf W_TEMP,F ; swapf W_TEMP,W ; ; retfie ;выход из подпрограммы прерывания ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Основная программа Start movlw b’00000000′ ;запись нулей в выходные защелки порта B movwf PORTB ; movlw b’00000111′ ;выключение компараторов movwf CMCON ; bsf STATUS,RP0 ;настройка линий вводавывода порта B movlw b’00110111′ ; movwf TRISB ; bcf STATUS,RP0 ; clrf flag1 ;очистка дополнительных регистров clrf shet ; movf PORTB,W ;чтение порта B, для устранения несоответствия bsf INTCON,RBIE ;разрешение прерываний по изменению уровня на RB4-RB7 bsf INTCON,GIE ;глобальное разрешение прерываний a1 btfss flag1,0 ;опрос флага регистрации поворота энкодера goto a1 ;флаг регистрации равен нулю: переход на метку a1 bcf flag1,0 ;флаг равен единице: сброс флага регистрации movf shet,W ;вывод содержимого регистра shet на цифровое call vivod ;табло goto a1 …………….. ;подпрограммы вывода содержимого …………….. ;регистра shet на семисегментные индикаторы …………….. ; end ;конец всей программы ; |
Выводы энкодера подключены к линиям RB4, RB5, в микроконтроллере включены прерывания по изменению уровня на входах RB4-RB7. Линии RB6, RB7 настроены на выход, чтобы не вызывать ложных прерываний, так как в данном микроконтроллере нельзя разрешать прерывания по отдельности на каждую линию. В обработчике прерываний происходит сохранение текущих состояний выводов энкодера в 0-й и 1-й биты регистра flag, далее идет проверка сохраненных значений, если биты 0 и 1 равны нулю, происходит переход на метку i2, где проверяется предыдущее состояние выводов энкодера записанных в биты 2 и 3 регистра flag. Если значение битов равно 0 и 1 произошел поворот в одну сторону, если 1 и 0 в другую сторону, состояние 0-0 и 1-1 игнорируется, в этом случае происходит выход из обработчика прерываний. После определения факта поворота происходит изменение значения счетчика shet, а также установка флага регистрации поворота энкодера flag1,0. Этот флаг опрашивается в основной программе, и если равен единице вызывается подпрограмма vivod, для вывода содержимого регистра shet на семисегментные индикаторы.
Для лучшей стабильности реализовано игнорирование состояний выводов энкодера после определения факта поворота. То есть после изменения значения регистра shet, устанавливается флаг готовности flag1,1. Состояние выводов игнорируется до момента, когда оба вывода не установятся в единицу, то есть по окончанию периода одного дискретного изменения. Как только значение обоих выводов будут равны единице, флаг готовности будет сброшен, и разрешен дальнейший анализ состояний выводов энкодера. Важное значение имеет наличие конденсаторов на выводах энкодера, которые уменьшают дребезг контактов, улучшая работоспособность данной программы.
Вышеприведенные программы тестировались на микроконтроллере PIC16F628A, тактовый генератор внутренний на 4 МГц, энкодер на 20 дискретных положений. Для отображения содержимого регистра shet, использовано цифровое табло из семисегментных индикаторов на драйвере MC14489AP. Результат представлен на видеоролике ниже.