Страница 1 из 1
Atmega8. Обработчик для валкодера на C
Добавлено: Сб май 12, 2007 17:15:18
sansan88
В общем я делаю блок управления для УМЗЧ. Регулировка громкости будеи происходить при помощи валкодера (или как он там правильно называется, когда крутишь в одну сторону, контакты замыкаются в одном порядке, если в другую, то наоборот).
Вот собственно обработчик:
Код: Выделить всё
while (1)
{
if (PIND.7==0) {
if (enc_dec==1) {
enc_count--;
enc_dec=0;
enc_inc=0;
printf("%c\r",enc_count);
}
else {
enc_inc=1;
};
};
if (PIND.6==0) {
if (enc_inc==1) {
enc_count++;
enc_dec=0;
enc_inc=0;
printf("%c\r",enc_count);
}
else {
enc_dec=1;
};
};
};
Это пока главный цикл программы.
Тут для примера сделал вывод состояния переменной-счетчика enc_count.
Изначально переменные enc_dec, enc_inc установлены в 0.
Выводы PD6 и PD7 програмно подтянуты к + питания.
Проблема такая, при повороте движка на одно деление происходит многократное выполнение кода и соответственно число в счетчике уменьшается (увеличивается) не на 1, как требуется, а на много больше.
Как решить эту проблему, мож кто сталкивался, подскажите пожалуйста.
Добавлено: Сб май 12, 2007 17:33:54
tych
Можно оставить схему как у вас и две ножки МК подсоединить диодами к INT0 настроеному как вход с подтяжкой и прервание по спаду. А в прерывании инализировать направление.
Добавлено: Сб май 12, 2007 17:42:07
ARV
Тебе необходимо добавить в свой код цикл ожидания момента, когда состояние твоих входных портов изменится - и только после этого продолжать основной цикл. В этом случае при одном и том же состоянии счетчик увеличится только на 1.
Добавлено: Сб май 12, 2007 17:44:03
sansan88
Попробую, но хотелось бы не использовать прерывание.
Добавлено: Сб май 12, 2007 17:47:44
tych
Если не использовать прерывание то твоя прога может вечно крутится в опросе ( поллинге ) валкодера и ничего больше делать не сможет.
Добавлено: Сб май 12, 2007 17:49:43
sansan88
ARV писал(а):Тебе необходимо добавить в свой код цикл ожидания момента, когда состояние твоих входных портов изменится - и только после этого продолжать основной цикл. В этом случае при одном и том же состоянии счетчик увеличится только на 1.
У меня еще будет процедура вывода информации на ЖКИ от Nokia 3310, только вот не знаю куда ее засунуть, в главный цикл или в таймер. Задержки - это первое что мне пришло в голову, но тогда если состояние долго не изменится (например я не до конца провернул ручку и произошло замыкание только первого контакта) то программа подвиснет до его изменения и ничего кроме прерываний обрабатывать не будет. Кстати, на прерывание еще повешу IR приемник для декодирования сигналов с пульта.
Добавлено: Сб май 12, 2007 17:54:49
sansan88
tych писал(а):Если не использовать прерывание то твоя прога может вечно крутится в опросе ( поллинге ) валкодера и ничего больше делать не сможет.
Тот код который я привел - есть главный цикл функции main. так что после обработчика валкодера в него можно впринципе вставить еще чего-то. ЛАдно, попробую сделать с прерыванием, похоже это единственный приемлемый вариант.
Добавлено: Сб май 12, 2007 17:56:39
ARV
Вообще-то, tych прав: делай в основном цикле вывод всего, чего надо, управление всем чем надо, а остальное (всю входящую информацию) делай по прерываниям - валкодер, IR-приемник, таймер...
а при ожидании можно извратиться и тоже че-то делать, но это муторно, имхо...
Добавлено: Сб май 12, 2007 18:01:17
sansan88
Значит так и сделаю. с задержками чет нет желания заморачиваться. Ладно, разработки данного давайса приостановлены до понедельника, отдыхаю. Потом отпишусь че получилось.
Добавлено: Сб май 12, 2007 18:05:17
tych
Можно сделать прерывание по переполнению таймера_0 в 2 раза чаще чем максимальное число тиков валкодера разумно допустить.
И в этом прервании 1 раз опрашивать что там на ногах его и сравнить что было в прошлый раз. Далее делать в этом прерывании все остальное.
Добавлено: Чт июн 04, 2009 21:03:00
VenomXP
Автор пропал куда-то. Очень интересно увидет код этой штуки. Имеется такая штука, только она из мышки, современной (умерла бедная совсем). Он такой маленький имеет 3 вывода. Фото позже будет. Я уверен что в нем нет оптопары, по простой причине что она просто туда не поместиться.
Добавлено: Пт июн 05, 2009 11:15:00
VenomXP
Привожу пример кода обработки валкодера:
Код: Выделить всё
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if ((PIND.7 == PIND.6)) vol++;
if ((PIND.7 != PIND.6)) vol--;
}
Принцип простой. Любой из выводов валкодера цепляем на внешнее прерывание, допустим PD7(все зависит от контроллера), а другой вывод на любую ножку контроллера сконфигурированную как вход, допустим PD6. Дальше из кода все понятно.
Мне бы хотелось выяснить как допустим можно сделать так: если быстро крутить его то значение инкремента увеличивалось на 10 единиц, а если медленно то на 1?
Добавлено: Пт июн 05, 2009 14:06:50
ARV
VenomXP писал(а):Мне бы хотелось выяснить как допустим можно сделать так: если быстро крутить его то значение инкремента увеличивалось на 10 единиц, а если медленно то на 1?
я делал такой вариант и даже где-то выкладывал код... но меня раскритиковали - сказали, что неудобно... и я забросил это

Добавлено: Пт июн 05, 2009 14:22:24
VenomXP
Я думаю принцип следующий. Запускаем таймер пусть он считает вообще не останавливаясь до максимума. Вводим переменную которая бы считала чколько времени прошло: count++; Далее когда приходит внешнее прерывание делаем так:
Код: Выделить всё
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (count > 50) //если прошло больше 50 мс с последнего обнуления
{
if ((PIND.7 == PIND.6)) vol++;
if ((PIND.7 != PIND.6)) vol--;
count = 0; //обнуляем счетчик
}
else
{
if ((PIND.7 == PIND.6)) vol = vol +10;
if ((PIND.7 != PIND.6)) vol = vol - 10;
count = 0;
}
}
Ну или примерно так.
Добавлено: Вс июн 07, 2009 17:03:27
dt_andrew
вот мой код
работает четко уже не в одном проекте
предварительные определения
//*****************************************************************************
#define ENCODER_PIN_A PD3
#define ENCODER_PIN_B PD1
#define ENCODER_PIN_PORT PIND
#define ENCODER_LEFT KBD_LEFT // код клавиши лево
#define ENCODER_RIGHT KBD_RIGHT // код клавиши право
#define ENC_TIMER_CNT 5
volatile char encoder_status;
const char enc_mask_plus = 0b00011110;
const char enc_mask_minus = 0b00101101;
//*****************************************************************************
осовная программа
таймер 2 настроен на 500мкс
переменной enc_timer_cnt можно регулировать чувствительность
//*****************************************************************************
ISR(SIG_OVERFLOW2)
{
TCNT2 = TIMER2_CNT; OCR2 = TIMER2_OCR;
enc_timer_cnt++;
if (enc_timer_cnt == ENC_TIMER_CNT)
{
if (enc.flip == -1) encoder_scan();
enc_timer_cnt = 0;
}
}
//*****************************************************************************
обработчик валкодера
и процедура инициализации
//*****************************************************************************
void encoder_scan(void)
{
unsigned char enc_A, enc_B, bit_0, bit_1;
if (enc.flip == -1)
{
if (bit_is_clear(ENCODER_PIN_PORT, ENCODER_PIN_A)) enc_A = 0; else enc_A = 1;
if (bit_is_clear(ENCODER_PIN_PORT, ENCODER_PIN_B)) enc_B = 0; else enc_B = 1;
if (bit_is_clear(encoder_status, 0)) bit_0 = 0; else bit_0 = 1;
if (bit_is_clear(encoder_status, 1)) bit_1 = 0; else bit_1 = 1;
if ((enc_A != bit_0) || (enc_B != bit_1))
{
encoder_status = encoder_status << 2;
if (enc_A == 0) encoder_status &= ~(_BV(0)); else encoder_status |= _BV(0);
if (enc_B == 0) encoder_status &= ~(_BV(1)); else encoder_status |= _BV(1);
if (encoder_status == enc_mask_minus)
{
enc.code = ENCODER_LEFT;
enc.flip = 1;
}
if (encoder_status == enc_mask_plus)
{
enc.code = ENCODER_RIGHT;
enc.flip = 1;
}
}
}
}
//*****************************************************************************
void encoder_init(void)
{
enc.code = ENCODER_NOKEY;
enc.flip = -1;
}
//*****************************************************************************
код не оптимальный и можно сделать красивее
но у меня работает хорошо и этим все сказано - переделывать лень и нет времени
в основном цикле
if (enc.flip == 1)
{
kbd_key = enc.code;
beep();
enc.flip = -1;
return 1;
// в зависимости от кода клавиши полученной от валкодера
// принимаем решение что делать
}