Поставки продукции Megawin по официальным каналам - микроконтроллеры, мосты USB-UART

Таймер с энкодером на ATmega8

Новичок
 
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
0 2
0 0
 
24.05.2020 14:53 #1
Доброго времени суток, Уважаемые! Такой вопрос. Собрал таймер на 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);
      }
      
    }
}
Оценка
К конденсаторам источников питания высокой мощности предъявляются высокие требования по качеству и надежности. Пленочные – единственный тип конденсаторов, который может справиться с такой задачей. Компания Hongfa предлагает продукцию, которая подходит для применения практически во всех функциональных узлах типовых AC/DC- или DC/AC-преобразователей. Рассмотрим характеристики и применения плёночных конденсаторов Hongfa для различных решений.
Специалист
 
Аватар для Vadzz
 
Регистрация: 12.11.2008
Адрес: Тирасполь
Сообщений: 2,172
Записей в дневнике: 22
Репутация: 418
406 86
0 0
Отправить сообщение для Vadzz с помощью ICQ
 
24.05.2020 23:10 #2
Энкодер правильно подключили? Какой энкодер?
К порту C, правильно?
Нет ошибки в строке:
NewState=PINC & 0b00000111; //Для энкодера
?
Может: NewState=PINC & 0b00000011; //Для энкодера
__________________
Уважаемые пассажиры, самолет ТУ-134 садится. У кого есть зарядка от ТУ-134, просьба пройти в кабину пилота.
Оценка
Вслед за сериями на DIN-рейку DDRH-60/120/240 и на шасси RSDH-150/300 компания MEAN WELL выпустила новые маломощные DC/DC-преобразователи DDRH-15/30/45 со сверхшироким входным напряжением 150…1500 В, и монтажом не только на DIN-рейку, но и печатную плату или винтовым соединением. Все преобразователи семейства DDRH и RSDH работают при температурах -40…80°C и обладают высокой изоляцией 4000 В AC между входом и выходом, что обеспечивает надежную защиту. Они подходят для использования на высоте до 5000 м и сертифицированы по стандарту IEC62109-1 для фотоэлектрических систем. Преобразователи DDRH/RSDH есть в наличии и под заказ.
Новичок
 
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
0 2
0 0
 
25.05.2020 07:14 #3
Цитата:
Сообщение от Vadzz
Энкодер правильно подключили? Какой энкодер?
К порту C, правильно?
Нет ошибки в строке:
NewState=PINC & 0b00000111; //Для энкодера
?
Может: NewState=PINC & 0b00000011; //Для энкодера
Энкодер EC12D1564402 ALPS

Подключил правильно, в той строке ошибки нет, энкодер с кнопкой один из выводом МК для нее в единицу установлен. Уже пробовал просто убирать и единичку оттуда и обработчик нажатия кнопки, все равно без изменений...
Оценка
В последние годы растёт спрос на источники питания для промышленной автоматизации в связи с увеличением инфраструктурных проектов, требующих надёжного электропитания. Источники питания на DIN-рейку MEAN WELL обладают высокой эффективностью, надёжностью и безопасностью, обеспечивая стабильное выходное напряжение. Большой ассортимент в наличии позволяет выбрать подходящий ИП MW на DIN-рейку для решения любой задачи электропитания.
Эксперт
 
Аватар для DmitriyVDN
 
Регистрация: 08.11.2009
Сообщений: 2,310
Репутация: 640
620 131
34 9
 
25.05.2020 07:42 #4
как-то у вас опрос энкодера через опу выглядит может как-то так надо:
Код:
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
0 2
0 0
 
25.05.2020 09:15 #5
Цитата:
Сообщение от DmitriyVDN
как-то у вас опрос энкодера через опу выглядит может как-то так надо:
Так тоже не получается. Теперь на старте вместо нулей отображается 1. Энкодер точно рабочий, пробовал конструкцию if ... else писать для опроса при повороте "крутилки" вообще какие то непонятные цифры отображаться начинают и с большой скоростью прибывать или убывать... Вряд ли это только из за "дребезга".
Оценка
Эксперт
 
Аватар для DmitriyVDN
 
Регистрация: 08.11.2009
Сообщений: 2,310
Репутация: 640
620 131
34 9
 
25.05.2020 15:09 #6
вы в железе проверяете? 1.тогда на энкодер поставьте внешние подтяжки по 4.7к и проверьте правильность подключения самого энкодера
2. при передаче цифр в прерывание не выполняется атомарность доступа.
Оценка
Новичок
 
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
0 2
0 0
 
25.05.2020 16:41 #7
Все разобрался!! Всем спасибо!! С помощью кусочка чужого кода, найденного в интернете, но все же понял в чем дело )))


Если кому то интересно:

Код:
#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;
А в "железе" работает примерно так: https://www.youtube.com/watch?v=NWGPziD3kG8
Оценка
Новичок
 
Регистрация: 12.12.2010
Адрес: Санкт-Петербург
Сообщений: 11
Репутация: 10
0 3
0 0
 
29.05.2020 20:34 #8
Вообще о чём идёт речь ??? Где схема, где? где?
Оценка
Ответ
Похожие темы
Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

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

Быстрый переход
Электронные компоненты. Скидки, кэшбэк и бесплатная доставка от ТМ Электроникс
Часовой пояс GMT +3, время: 20:36.
Обратная связь РадиоЛоцман Вверх