Новичок
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
|
Доброго времени суток, Уважаемые! Такой вопрос. Собрал таймер на ATmega8 на кнопках все норм. все работает.
Тут на видео кнопочный вариант, для наглядности Теперь пытаюсь Подружить его с энкодером. Т.е. вместо кнопок поставить энкодер. И недопонимаю что делаю не так. Таймер включается, отображает все нули, и вообще никак не реагирует на повороты энкодера. Может кто подскажет в чем я опять "протупил" ? ИСХОДНИК (Atmel studio) Код:
/*Используется семисегментный индикатор с общим АНОДОМ. т.е. на смену разрядов подается "+", а на сементы индикатора "-" Эмиттеры транзисторов прицепить к "+" кллекторы к семисегментнику (к разрядам), базу через резистор к МК*/ #define F_CPU 1000000UL //Задаем частоту работы МК #include<util/delay.h> //Библиотека задержек #include <avr/interrupt.h> //Библиотека прерываний #include <avr/io.h> int NewState, OldState, upState, downState; int start_sec = 0; unsigned int R1=0, R2=0, R3=0, R4=0; //Переменные для разрядов семисегментника unsigned int R_count =1; //Для постоянного переключения разрядов на семисегментнике unsigned int cifri[10]={0b11000000, 0b11111001, 0b10100100, 0b10110000, 0b10011001, 0b10010010, 0b10000010, 0b11111000, 0b10000000, 0b10010000}; //Цыфры 0-9 void start_otscheta (void) //Тут будут размещены все настроки 1-го таймер/счетчика { TCCR1B &= ~(1<<CS12); //Устанавливаем бит в 0 (для настройки делителя частоты на 64) TCCR1B |= (1<<CS11)|(1<<CS10); //Устанавливаем биты в 1 (для настройки делителя частоты на 64) /*1000000/64 = 15625 т.е. на этой частоте будет работать МК. Далее для того чтобы получить ровно 12 сек. необходимо "убить" эти 15625 тактов. Это можно сделать настроив данный таймер/счетчик на прерывание при совпадении данного числа*/ TIMSK |= (1<<OCIE1A); //Настраивает прерывания при совпадении. /*Далее в регистре сравнения необходимо записать в двоичной форме число 15625. Данный регист 16-ти битный, поэтому он сдвоенный*/ OCR1AH = 0b00111101; //старший разряд OCR1AL = 0b00001001; //Младший разряд /*Когда произойдет совпадение, должно вызваться не только прерывание, но и сброс счетного регистра*/ TCNT1 = 0; //Обнуление счетного регистра TCCR1B |= (1<<WGM12); //Активация сброса при совпадении. } void Chislo_celikom(unsigned int vsego_sekund) //Создаем функцию, будет разделять общее кол-во секунд на мин. и сек. { R1 = vsego_sekund/60/10; //Десятки минут R2 = vsego_sekund/60%10; //Минуты (единицы) R3 = vsego_sekund%60/10; //десятки секунд R4 = vsego_sekund%60%10; //секунды (единицы) } ISR (TIMER0_OVF_vect) { if (R_count == 1){PORTB = ~0b00000001;PORTD = cifri[R1];} if (R_count == 2){PORTB = ~0b00000010;PORTD = cifri[R2];} if (R_count == 3){PORTB = ~0b0000100; PORTD = cifri[R3];} if (R_count == 4){PORTB = ~0b00001000; PORTD = cifri[R4];} R_count++; if (R_count>4){R_count=1;} NewState=PINC & 0b00000111; //Для энкодера if(NewState!=OldState) { switch(OldState) { case 2: { if(NewState == 3) upState++; if(NewState == 0) downState++; break; } case 0: { if(NewState == 2) upState++; if(NewState == 1) downState++; break; } case 1: { if(NewState == 0) upState++; if(NewState == 3) downState++; break; } case 3: { if(NewState == 1) upState++; if(NewState == 2) downState++; break; } } OldState=NewState; } } ISR (TIMER1_COMPA_vect) //Прерывания для первого таймера по сравнению. Чтобы отслеживать 1сек. { start_sec--; if (start_sec < 0) start_sec = 0; /*Теперь когда изначальное значение снизилось до 0, включать пищалку*/ if (start_sec == 0) { PORTC |= (1<<3); } else { PORTC &= ~(1<<3); } } int main(void) { //TCCR0 |= (1<<1); //TCCR0 &= ~((1<<0)|(1<<2)); //Активация нулевого таймера (делим на 8) TCCR0 |= (1<<CS01); TCNT0 = 0; //Обнуляем (на всякий случай) нулевой таймер sei(); //Разрешаем выполнение прерываний TIMSK |= (1<<0); //Устанавливаем 1 в нулевой бит, т.е. Прерывания для нулевого таймера (TOIE0) DDRB = 0b00001111; //Выводы на выход DDRD = 0b01111111; //Выводы на выход DDRC |= (1<<3); //тут будет выход на пищалку. PORTC &=~(1<<3); //по умолчанию сигнал на пищалку не подается этот порт в 0-ле DDRC = 0b00000000; //Выводы на вход (тут кнопки) PORTC = 0b00000111; //Подтягивающие резисторы к кнопкам Chislo_celikom(start_sec); while (1) { Chislo_celikom(start_sec); /* для энкодера*/ if (upState >=4) { start_sec++; upState = 0; if (start_sec>5999) { start_sec=0; } } if (downState >=4) { start_sec--; downState = 0; if (start_sec<0) { start_sec=5999; } } if (~PINC & (1<<2)) { if (start_sec == 0) { PORTC &= ~(1<<3); } start_otscheta(); _delay_ms(200); } } } |
||
Оценка
|
Специалист
|
Энкодер правильно подключили? Какой энкодер?
К порту C, правильно? Нет ошибки в строке: NewState=PINC & 0b00000111; //Для энкодера ? Может: NewState=PINC & 0b00000011; //Для энкодера
__________________
Уважаемые пассажиры, самолет ТУ-134 садится. У кого есть зарядка от ТУ-134, просьба пройти в кабину пилота. |
||
Оценка
|
Компактные и эффективные DC/DC-преобразователи DDR от MEAN WELL на DIN-рейку - в наличии и под заказ
MEAN WELL предлагает широкий ассортимент DC/DC-преобразователей DDR для монтажа на DIN-рейку. Доступны модели мощностью 15–480 Вт с разными комбинациями входного и выходного напряжения, которое можно настраивать в широком диапазоне. Преобразователи характеризуются компактностью, высокой эффективностью и усиленной изоляцией «вход-выход» 4000 В DC. Вся линейка, включая мощные модели, не имеет вентилятора и работает при температуре от -40 до 70/80/85 °C (в зависимости от серии) в условиях естественной конвекции.
|
Новичок
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
|
Цитата:
Подключил правильно, в той строке ошибки нет, энкодер с кнопкой один из выводом МК для нее в единицу установлен. Уже пробовал просто убирать и единичку оттуда и обработчик нажатия кнопки, все равно без изменений... |
||
Оценка
|
Эксперт
Регистрация: 08.11.2009
Сообщений: 2,310
Репутация: 640
|
как-то у вас опрос энкодера через опу выглядит может как-то так надо:
Код:
void encoder_read(void) {unsigned char tempPORTB; static unsigned char encoder_TEMP,Count; tempPORTB=PORTB; encoder_TEMP<<=2; encoder_TEMP|=(tempPORTB&((1<<1)|(1<<0))); encoder_TEMP&=0x0F; switch (encoder_TEMP) { // UP case 2: case 4: case 11: case 13: Count++; break; // DOWN case 1: case 7: case 8: case 14: Count--; break; default: break; } // switch encoder 8 state if (Count == 8) // Если был шаг энкодера влево { txt++; // <<-- нужное действие Count = 4; } else if (Count == 0) // Если был шаг энкодера вправо { txt--; // <<-- нужное действие Count = 4; } }//end void encoder_read(void) |
||
Оценка
|
Новичок
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
|
Так тоже не получается. Теперь на старте вместо нулей отображается 1. Энкодер точно рабочий, пробовал конструкцию if ... else писать для опроса при повороте "крутилки" вообще какие то непонятные цифры отображаться начинают и с большой скоростью прибывать или убывать... Вряд ли это только из за "дребезга".
|
||
Оценка
|
Новичок
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
|
Все разобрался!! Всем спасибо!! С помощью кусочка чужого кода, найденного в интернете, но все же понял в чем дело )))
Если кому то интересно: Код:
#define PORT_Enc PORTC #define PIN_Enc PINC #define DDR_Enc DDRC #define Pin1_Enc 0 #define Pin2_Enc 1 #define RIGHT_SPIN 0x01 #define LEFT_SPIN 0xff #define SetBit(port, bit) port|= (1<<bit) #define ClearBit(port, bit) port&= ~(1<<bit) #define b00000011 3 #define b11010010 210 #define b11100001 225 Код:
//функция опроса энкодера static unsigned char stateEnc; //хранит последовательность состояний энкодера unsigned char tmp; unsigned char currentState = 0; //проверяем состояние выводов микроконтроллера if ((PIN_Enc & (1<<Pin1_Enc))!= 0) {SetBit(currentState,0);} if ((PIN_Enc & (1<<Pin2_Enc))!= 0) {SetBit(currentState,1);} //если равно предыдущему, то выходим tmp = stateEnc; if (currentState == (tmp & b00000011)) return; //если не равно, то сдвигаем и сохраняем в озу tmp = (tmp<<2)|currentState; stateEnc = tmp; //сравниваем получившуюся последовательность if (tmp == b11100001) start_sec--; //минусуем секунду if (tmp == b11010010) start_sec++; //Плюсуем секунду return; |
||
Оценка
|
Обратная связь РадиоЛоцман Вверх |