Технический форум
Вернуться   Технический форум > Электроника, самоделки и техника > Форум по электронике > Микропроцессоры


Ответ
 
Опции темы Опции просмотра
Старый 01.06.2016, 10:15   #1 (permalink)
Сергей Демагого
Member
 
Регистрация: 26.03.2016
Сообщений: 16
Сказал(а) спасибо: 0
Поблагодарили 1 раз в 1 сообщении
Репутация: 60
По умолчанию Проблема с опросом энкодера на внешних прерываниях

Такая тема уже была кажется, но с такой проблемой вроде никто не сталкивался. Задание следующее:Отобразить номер своего варианта на ЖКИ индикатор с возможностью
изменения значения энкодером в большую (до 999) или меньшую сторону.
Опрос энкодера реализовать на внешних прерываниях.
Вот код:
KOD_2.txt
Алгоритм стандартный, но при повороте ручки энкодера влево-вправо он либо в обе стороны прибавляет, либо в обе стороны отнимает. В чем может быть дело?
Сергей Демагого вне форума   Ответить с цитированием

Старый 01.06.2016, 10:15
Helpmaster
Member
 
Аватар для Helpmaster
 
Регистрация: 08.03.2016
Сообщений: 0

В похожих обсуждениях зачастую можно найти полезные ответы

Странность с опросом
подключение внешних разъемов
Подключение энкодера
Помогите с макросом для энкодера
О внешних ссылках

Старый 01.06.2016, 16:31   #2 (permalink)
nml
Member
 
Аватар для nml
 
Регистрация: 15.08.2013
Адрес: Minsk
Сообщений: 145
Сказал(а) спасибо: 1
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 713
По умолчанию

Скажите, а зачем там вообще таймер?
Вы разрешили прерывание по спаду INT0, объявили обработчик - что еще надо? Флаг прерывания сам сбросится при входе в обработчик.

Или же у вас дребезг контактов?

Но тогда лучше вообще все по таймеру, а внешнее прерывание запретить.
Читать по таймеру, сравнивать с предыдущим.
nml вне форума   Ответить с цитированием
Старый 03.06.2016, 15:19   #3 (permalink)
Сергей Демагого
Member
 
Регистрация: 26.03.2016
Сообщений: 16
Сказал(а) спасибо: 0
Поблагодарили 1 раз в 1 сообщении
Репутация: 60
По умолчанию

Недавно боролся с похожей проблемой. Поборол. Суть в следующем.При инициализации:1. Привязываем прерывание к срезу импульса на выходе А энкодера.Обработчик прерываний:1. Запрещает прерывания.2. Взводит глобальный флаг.Основной код программы:1. Если взведен флаг, выполняем последующий код, иначе - пропускаем.2. Задержка 3 мс для завершения возможного переходного процесса.3. Читаем выход А энкодера. Если высокий - прерывание ложное, сбрасываем глобальный флаг, разрешаем прерывания, пропуск последующего кода.4. Читаем выход В энкодера - если высокий, добавляем нужную величину, низкий - убавляем и т.д., вобщем стандартный вариант. Перед завершением обработки сбрасываем глобальный флаг и разрешаем прерывания

Выше предложенный алгоритм заработал, однако программа работает не оптимально: иногда при повороте энкодера возникает осечка, либо прибавляет/отнимает 2, вместо 1.
Пробовал перебрать частоту тиков таймера, ничего не помогает.
Код:
#include "hd44780.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define ENC_PORT PORTD
#define ENC_PIN PIND
#define A_PIN 2
#define B_PIN 1
#define Comapare_Mask (1<<A_PIN)|(1<<B_PIN)
volatile uint8_t flag=0;
void timer0_on()
{
TCNT0=0x00; //записываем 0 в счетный регистр
TCCR0|=(1<<CS02)|(0<<CS01)|(1<<CS00);//устанавливаем частоту тиков
TIMSK|=(0<<OCIE0)|(1<<TOIE0);//устанавливаем прерывания по переполнению
}
void timer0_off()
{
TCCR0|=(0<<CS02)|(0<<CS01)|(0<<CS00);
}
int main(void)
{ int count=14;
lcd_init();
lcd_clear();
lcd_out4(count,2);
MCUCR |= (1<<ISC01)|(0<<ISC00);//прерывание по спаду
GICR = (1<<INT0); //разрешение прерываний
ENC_PORT |= Comapare_Mask;//опрос энкодера
sei();
while(1)
{
  if (flag==1)
  {
   timer0_on();
   if ((ENC_PIN&(1<<A_PIN)) >>A_PIN==1) //считываем вывод А
   {
        flag = 0;//если уровень высокий сбрасываем флаг
   }
   else
   {
        if ((ENC_PIN&(1<<B_PIN)) >>B_PIN==1)
        {
         count--;
         if (count<0) count=9999;
        }
        else
        {
         count++;
         if (count>9999)
          count=0;
        }
        flag = 0;
   }
  }
  lcd_out4(count,2);
};
}
ISR (INT0_vect)
{
GICR = (0<<INT0); //запрещаем прерывания
flag = 1;//взводим глобальный флаг
}
ISR (TIMER0_OVF_vect)
{
timer0_off();
GICR = (1<<INT0);
}
Сергей Демагого вне форума   Ответить с цитированием
Старый 03.06.2016, 15:54   #4 (permalink)
wss60
Member
 
Аватар для wss60
 
Регистрация: 09.08.2015
Адрес: Minsk
Сообщений: 245
Сказал(а) спасибо: 12
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 3649
По умолчанию

Пример на внешнем прерывании.
wss60 вне форума   Ответить с цитированием
Ads

Яндекс

Member
 
Регистрация: 31.10.2006
Сообщений: 40200
Записей в дневнике: 0
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 55070
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.




Часовой пояс GMT +4, время: 19:10.

Powered by vBulletin® Version 6.2.5.
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.