Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.71/58: Рейтинг темы: голосов - 58, средняя оценка - 4.71
pryomys
0 / 0 / 0
Регистрация: 05.06.2011
Сообщений: 11
1

обработка инкрементального энкодера на прерываниях (asm)

03.12.2012, 01:08. Просмотров 10889. Ответов 25
Метки нет (Все метки)

Приветствую сообщество.
Пытаюсь нарулить на ассемблере код обработки энкодера, оно вроде функционирует, но с большими глюками.

Вкратце: энкодер подключен к D1, D2. 4 светодиода подключены к PC0-PC3 (первые 2 подключены к -, вторые - к плюсу; так сделано на отладочной плате), поэтому в регистре перед выводом в порт инвертируются 2 последних бита с помощью. EOR.
Задача программы: при повороте вправо увеличиваем счетчик (если насчитываем 15, то ничего не делаем) и выводим в PortC. При движении влево уменьшаем счетчик (при достижении 0 ничего не делаем). Задержка по переполнению Таймера0 (с делителем 256 получается 16 мс при 4 МГц).
Дело не в дребезге, посмотрел осциллографом - фронты почти идеальные. Пробовал уменьшать/увеличивать величину задержки - не помогает.

При быстром вращении глючит (моргают ненужные светодиоды), при вращении назад ситуация такая же плюс вообще начинает инкременировать счетчик если быстро крутить.
Алгоритм с некоторыми изменениями взял из статьи про энкодер.

Зашли в обработчик INT0
Запретили локально INT0
Пощупали второй канал
+1 или -1 (если 1, то проверяем счетчик на равенство 0b00001111, если равно, то выходим из прерывания, если нет, то увеличиваем счетчик; если 0, то проверяем счетчик на 0b00000000, если равно, то выходим, если нет, то уменьшаем на 1)
Запускаем Т0 с предделителем 256
Вышли из обработчика

вошли в обработчик прерывания Т0.
останавливаем таймер
разрешаем INT0
выходим из прерывания

Прерывание запрещаем сразу после входа в процедуру обработки прерывания.
В аттаче проект студии.

[7.27 Кб]
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.12.2012, 01:08
Ответы с готовыми решениями:

Обработка энкодера
Имеется трёх импульсный энкодер (если это правильное название), т.е. датчик который имеет три линии...

Обработка строк [asm+pas]
Дан текст не более 255 символов. Составить словарь уникальных символов. Программа состоит из двух...

Непонятное поведение bacula при создании инкрементального бэкапа
Здравствуйте, я всего несколько дней как взялся настраивать bacula и появилась проблема описание...

USART на прерываниях
Добрый день. Я делаю терморегулятор на 18В20 и АтТини2313. Терморегулятор принимает через усарт...

Запутался в прерываниях
В общем стоит такая задача: Через мультиплексор на вход контроллера последовательно подаются 4...

25
swk
0 / 0 / 0
Регистрация: 22.10.2015
03.12.2012, 02:18 2
Цитата Сообщение от pryomys
Алгоритм с некоторыми изменениями взял из статьи про энкодер.
Почитайте там же комментарии. Там все варианты давно перетолкли.
0
Dimys_K
0 / 0 / 0
Регистрация: 06.11.2011
Сообщений: 191
03.12.2012, 08:35 3
Я сталкивался с подобынами глюками тоже. Причем первый раз пробовал работать с энкодером, который выдрал со старого моника. Программу написал с использованием внешнего прерывания по одной ноге. После прерывания опрашивал другую и делал вывод куда крутим. После этого я положил все это в долгий ящик. А тут приспичило энкодер в одно место поставить. Купил такой же в нигазине, запустил с этой программой и начались глюки. Что я только не делал с программой, ничего не выходило. По осциллографу все фронты были четкие, без дребезга.
Решил проблему отказавшись от внешнего прерывания. Измерил осциллографом минимальную длительность импульса при самом быстром вращении энкодера, которое можно осуществить рукой. Написал функцию опроса энкодера. В ней проверяю текущее состояние линий А и В и предыдущее. По этим данным делаю вывод куда крутим. Функцию вызываю не реже длительности измерянного импульса. Все очень даже не плохо работает.
0
Pojotit
0 / 0 / 0
Регистрация: 16.03.2012
Сообщений: 461
03.12.2012, 14:20 4
..маленький советик: обратите внимание на тип энкодера, есть как минимум два основных типа, первый - оба выходных контакта между щелчками висят в воздухе, второй - между щелчками один из выходов замкнут с общим и так они попеременно остаются замкнутыми через щелчёк. Если алгоритм этого обстоятельства не учитывает, то и будут наблюдаться всякого рода глюки, потому как, если код был написан для одного типа, совсем необязательно, что он будет нормально работать с другим типом энкодера
0
03.12.2012, 14:20
Yurkom
0 / 0 / 0
Регистрация: 23.05.2007
Сообщений: 792
03.12.2012, 19:04 5
Цитата Сообщение от pryomys
.....
вошли в обработчик прерывания Т0.
останавливаем таймер
разрешаем INT0
выходим из прерывания
.....
.....
вошли в обработчик прерывания Т0.
останавливаем таймер
сбрасываем флаг прерывания INT0 (записью единицы!)
разрешаем INT0
выходим из прерывания
.....
0
pryomys
0 / 0 / 0
Регистрация: 05.06.2011
Сообщений: 11
04.12.2012, 15:05 6
сбрасываем флаг прерывания INT0 (записью единицы!)
Он же сбрасывается автоматически при входе в обработчик прерывания. Хотя у Ревича встречал очистку регистра флагов записью единиц (с комментарием на всякий случай).

Попробовал сбросить флаги внешних прерываний в обработчике INT0 - не помогло.
Осциллограммы энкодера:





0
stt
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
04.12.2012, 19:30 7
Цитата Сообщение от pryomys
Пощупали второй канал
+1 или -1 (если 1, то проверяем счетчик на равенство 0b00001111, если равно, то выходим из прерывания, если нет, то увеличиваем счетчик; если 0, то проверяем счетчик на 0b00000000, если равно, то выходим, если нет, то уменьшаем на 1)
Мне кажется, именно тут тонкий момент:
Код
EXT_INT0:   push   temp
in      temp,   SREG
push   temp               ;сохраняем temp и SREG в стеке
clr      temp
out      GICR,   temp         ;запрещаем INT0

ТОНКИЙ МОМЕНТ

sbic   pinD,   1            ;если на проверяемом пине высокий уровень,
rjmp   move_right            ;идем по метке вправо, если низкий,
rjmp   move_left            ;то влево.
Попробуй сюда вставить задержку. Не факт, что не дребезжит пин Д1.
0
pryomys
0 / 0 / 0
Регистрация: 05.06.2011
Сообщений: 11
04.12.2012, 20:32 8
Попробуй сюда вставить задержку. Не факт, что не дребезжит пин Д1.
Не думаю что поможет. Мы же сразу запрещаем INT0 при входе в прерывание.
0
ShodS
0 / 0 / 0
Регистрация: 01.02.2010
Сообщений: 2,011
04.12.2012, 21:11 9
А на С совсем не вариант?..... Просто есть рабочий код от Л.И.
0
pryomys
0 / 0 / 0
Регистрация: 05.06.2011
Сообщений: 11
04.12.2012, 21:27 10
Спасибо, но Си не вариант.
0
Yurkom
0 / 0 / 0
Регистрация: 23.05.2007
Сообщений: 792
04.12.2012, 21:30 11
Цитата Сообщение от pryomys
Попробовал сбросить флаги внешних прерываний в обработчике INT0 - не помогло.
Да не в обработчике INT0 надо, а перед самым разрешением INT0, в твоем случае в обработчике T0.
0
pryomys
0 / 0 / 0
Регистрация: 05.06.2011
Сообщений: 11
04.12.2012, 22:28 12
Да не в обработчике INT0 надо, а перед самым разрешением INT0, в твоем случае в обработчике T0.
А в чем разница?
0
stt
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
04.12.2012, 23:50 13
Цитата Сообщение от pryomys
Не думаю что поможет. Мы же сразу запрещаем INT0 при входе в прерывание.
При чем тут INT0? Я говорю про анализируемый в прерывании пин. Но, конечно, если задержку воткнуть сложно, тады ой.
0
pryomys
0 / 0 / 0
Регистрация: 05.06.2011
Сообщений: 11
05.12.2012, 00:35 14
Подождите...
Ведь в момент срабатывания прерывания у нас на второй ноге энкодера уровни уже установились, фронтов сигнала нет. Дребезга соответственно тоже нет.
Или я опять что-то не понимаю.
0
Yurkom
0 / 0 / 0
Регистрация: 23.05.2007
Сообщений: 792
05.12.2012, 10:03 15
[QUOTE="pryomys"][QUOTE="Цитата:[/QUOTE]
Да не в обработчике INT0 надо, а перед самым разрешением INT0, в твоем случае в обработчике T0.
А в чем разница? В том, что несмотря на запрет прерывания, флаг всё равно встаёт аппаратно. Неважно, от дребезга, или при слишком быстром вращении. Потом, как только ты разрешишь INT0, оно тут же обработается, хотя импульса нет. Потому что флаг уже стоит!
0
dork
0 / 0 / 0
Регистрация: 25.03.2017
05.12.2012, 17:20 16
Цитата Сообщение от ShodS
А на С совсем не вариант?..... Просто есть рабочий код от Л.И.
ShodS, ссылочку не дадите?
буду благодарен...
0
pryomys
0 / 0 / 0
Регистрация: 05.06.2011
Сообщений: 11
05.12.2012, 22:13 17
В том, что несмотря на запрет прерывания, флаг всё равно встаёт аппаратно. Неважно, от дребезга, или при слишком быстром вращении. Потом, как только ты разрешишь INT0, оно тут же обработается, хотя импульса нет. Потому что флаг уже стоит!
Попробовал сбрасывать флаги прерываний в обработчике прерывания таймера... не помогает пока.
Код
TIM0_OVF:   push   temp
in      temp,   SREG
push   temp
clr      temp
out      TCCR0,   temp         ;останавливаем Таймер0
ldi      temp,   0b01000000
out      GICR,   temp         ;разрешаем INT0
ser      temp
out      GIFR,   temp         ;очищаем регистр флагов внешных прерываний
pop      temp
out      SREG,   temp
pop      temp
reti
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
06.12.2012, 01:53 18
Обычно, флаг сначала очищают , а потом разрешают прерывание
0
ShodS
0 / 0 / 0
Регистрация: 01.02.2010
Сообщений: 2,011
06.12.2012, 02:24 19
Цитата Сообщение от dork
Цитата Сообщение от ShodS
А на С совсем не вариант?..... Просто есть рабочий код от Л.И.
ShodS, ссылочку не дадите?
буду благодарен...
Код
//МОДУЛЬ*ПОДДЕРЖКИ*ЭНКОДЕРА*(От*Леанида*Ивиновича)
//Для*подавления*дребезга*используется*анализ*двух*последовательных
//состояний.*Это*позволяет*обойтись*без*временных*задержек.
//Функция*EncoderInit()*должна*вызываться*один*раз*в*начале*программы.
//Функция*EncoderExe()*должна*вызываться*в*основном*цикле.
//При*повороте*энкодера*на*шаг*вправо*или*влево*изменяется*значение*глобальной*переменной*EncoderValue.
//
//
//Глобалльные*переменные
sykned*char*EncoderValue*=*0;

//Константы
#define*EncoderDDR*DDRC************************/*порт*настройки*/
#define*EncoderPORT*PORTC********************/*порт*управления*/
#define*EncoderPIN*PINC************************/*порт*чтения*/
#define*EncoderF1*(1<<3)********************/*пины*чтения*енкодера*/
#define*EncoderF2*(1<<4)********************/*пины*чтения*енкодера*/
enum*{*State0,*StateA,*StateB,*StateAB*};*****//состояния*энкодера

//Переменные
static*char*EncPrev;**************************//предыдущее*состояние*энкодера
static*char*EncPrevPrev;**********************//пред-предыдущее*состояние*энкодера

//Инициализация*энкодера
void*EncoderInit(void)
{
EncoderDDR*&=*~(EncoderF1*|*EncoderF2);*//настройка*портов*на*ввод
EncoderPORT*|=*EncoderF1*|*EncoderF2;***//включение*подтягивающих*резисторов
EncPrev*=*State0;***********************//инициализация*предыдущего*состояния
EncPrevPrev*=*State0;*******************//инициализация*пред-предыдущего*состояния
}

//Обработка*энкодера
void*EncoderExe(void)
{
char*EncCur*=*0;

if(!*(EncoderPIN*&*EncoderF1))
EncCur**=*StateA;*//опрос*фазы*1*энкодера

if(!*(EncoderPIN*&*EncoderF2))
EncCur*|=*StateB;*//опрос*фазы*2*энкодера

if(EncCur*!=*EncPrev)*{********************//если*состояние*изменилось,
if(EncPrev*==*StateAB*&&*EncCur*!=*EncPrevPrev*){//если*предыдущее*состояние*StateAB*и*текущее*и*пред-предыдущее*не*равны,
if(EncCur*==*StateB)**************//если*текущее*состояние*StateB,
EncoderValue*++;************//шаг*вверх
else
EncoderValue*--;************//шаг*вниз
}
EncPrevPrev*=*EncPrev;**************//сохранение*пред-предыдущего*состояния
EncPrev*=*EncCur;*******************//сохранение*предыдущего*состояния
}
}
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
06.12.2012, 02:39 20
:))))
ShodS писал(а):

А на С совсем не вариант?.....
dork: Спасибо, но Си не вариант
0
06.12.2012, 02:39
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.12.2012, 02:39

Запутался в прерываниях
В общем стоит такая задача: Через мультиплексор на вход контроллера последовательно подаются 4...

Создание проекта с участием c++ и asm модулей. Ошибка asm модуля
Доброго времени суток! Подскажите, пожалуйста, как исправить данную ошибку (А2008)?

Delphi и ASM - не работает вызов функции Invoke через asm
В Delphi не работает вызов функции Invoke через asm. часть кода: asm invoke...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.