Вводная информация. Энкодор ЕС11, от китайцев. МК Atmega32A. Среда разработки AtmelStudio7, язык С++.
Энкодер подключен к PD0,PD2
Изначально пробовал обрабатывать энкодер в общем коде программы. Код имел такой вид:
Спойлер
Код: Выделить всё
void port_ini(void)
{
DDRD =0b10001000;
//PORTD=0b00000100;
PORTD=0b00000111;
}
void EncoderScan(void)
{
next_state = PIND & 0x05; // Берем текущее значение
// И сравниваем со старым
// Смотря в какую сторону оно поменялось -- увеличиваем
// Или уменьшаем счетный регистр
switch(prev_state)
{
case 4:
{
if(next_state == 5) up_state++;
if(next_state == 0) down_state++;
break;
}
case 0:
{
if(next_state == 4) up_state++;
if(next_state == 1) down_state++;
break;
}
case 1:
{
if(next_state == 0) up_state++;
if(next_state == 5) down_state++;
break;
}
case 5:
{
if(next_state == 1) up_state++;
if(next_state == 4) down_state++;
break;
}
}
prev_state = next_state; // Записываем новое значение
// Предыдущего состояния
if (up_state >= 4) // 1 раз за 4 импульса изменяем состояние передачи
{
sw++;
infoPage++; // Передача +
up_state = 0;
Light_timer=Light_Time;
}
if (down_state >= 4)
{
sw--;
infoPage--;
// Передача -
down_state = 0;
Light_timer=Light_Time;
}
}
Так как основной код получился довольно таки объемным, решил использовать внешние прерывания. Код видоизменился и стал иметь следующий вид:
Спойлер
Код: Выделить всё
void port_ini(void)
{
DDRD =0b10001000;
PORTD=0b00000111;
}
void int_ini(void)
{
MCUCR |= (1 << ISC01); // Прерывание по заднему фронту INT0(по спаду импульса)
GIFR |= (1 << INTF0); // Очищаем флаг внешнего прерывания
GICR |= (1 << INT0); // Разрешаем внешние прерывания INT0
}
ISR(INT0_vect)
{
next_state = PIND & 0x05;
switch(prev_state)
{
case 4:
{
if(next_state == 5) up_state++;
if(next_state == 0) down_state++;
break;
}
case 0:
{
if(next_state == 4) up_state++;
if(next_state == 1) down_state++;
break;
}
case 1:
{
if(next_state == 0) up_state++;
if(next_state == 5) down_state++;
break;
}
case 5:
{
if(next_state == 1) up_state++;
if(next_state == 4) down_state++;
break;
}
}
prev_state = next_state; // Записываем новое значение
// Предыдущего состояния
if (up_state >= 4) // 1 раз за 4 импульса изменяем состояние передачи
{
sw++;
infoPage++; // Передача +
up_state = 0;
Light_timer=Light_Time;
}
if (down_state >= 4)
{
sw--;
infoPage--;
// Передача -
down_state = 0;
Light_timer=Light_Time;
}
}
int main(void)
{
int_ini();//инициализируем внешние прерывания
port_ini(); //Инициализируем порты
LCD_ini(); //Инициализируем дисплей
I2C_Init(); //Инициализируем шину TWI (I2C)
PWM0_ini();//инициализируем PWM0
PWM1_ini();//Инициализируем 16 битный счетчик
PWM2_ini();//инициализиируем PWM2
Пробовал добавлять конденсаторы между энкодером и землей - эффекта нет.
Пробовал прикрутить этот код (нашел тут же на сайте), так же не смог заставить работать.
Спойлер
Код: Выделить всё
// ISR(INT0_vect)
// {
//
// char EncCur = 0;
// if(!Pin_ENC_F1) EncCur = StateA; //опрос фазы 1 энкодера
// if(!Pin_ENC_F2) EncCur |= StateB; //опрос фазы 2 энкодера
// if(EncCur != EncPrev) //если состояние изменилось,
// {
// if(EncPrev == StateAB && //если предыдущее состояние StateAB
// EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
// {
// if(EncCur == StateB) //если текущее состояние StateB,
// {
// sw++;
// infoPage++; // Передача +
//
// Light_timer=Light_Time;
// }
// //шаг вверх
// else //иначе
// {
// sw--;
// infoPage--;
// // Передача -
//
// Light_timer=Light_Time;
// } //шаг вниз
// }
// EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
// EncPrev = EncCur; //сохранение предыдущего состояния
// }
//
// }

