Радиолоцман Электроника en
расширенный поиск +
  
Ответ
 
Опции темы Поиск в этой теме Оценить тему
Старый 24.05.2020, 14:53 #1
geonov
Новичок
 
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
geonov Новичок
0 2
0 0
По умолчанию Таймер с энкодером на ATmega8

Доброго времени суток, Уважаемые! Такой вопрос. Собрал таймер на 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);
      }
      
    }
}
geonov вне форума  
Оценка 0
Старый 24.05.2020, 23:10 #2
Vadzz
Специалист
 
Аватар для Vadzz
 
Регистрация: 12.11.2008
Адрес: Тирасполь
Сообщений: 2,163
Записей в дневнике: 19
Репутация: 400
Vadzz Специалист Vadzz Специалист Vadzz Специалист Vadzz Специалист Vadzz Специалист
388 85
0 0
Отправить сообщение для Vadzz с помощью ICQ
По умолчанию

Энкодер правильно подключили? Какой энкодер?
К порту C, правильно?
Нет ошибки в строке:
NewState=PINC & 0b00000111; //Для энкодера
?
Может: NewState=PINC & 0b00000011; //Для энкодера
__________________
Уважаемые пассажиры, самолет ТУ-134 садится. У кого есть зарядка от ТУ-134, просьба пройти в кабину пилота.
Vadzz вне форума  
Оценка 0
Мало кто из инженеров-разработчиков знает про особенность электрохимической системы, которая проявляется у батареек большинства представленных на рынке брендов. Производители литиевых батареек знают об этой особенности, но не указывают её в даташите.
Старый 25.05.2020, 07:14 #3
geonov
Новичок
 
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
geonov Новичок
0 2
0 0
По умолчанию

Цитата:
Сообщение от Vadzz Посмотреть сообщение
Энкодер правильно подключили? Какой энкодер?
К порту C, правильно?
Нет ошибки в строке:
NewState=PINC & 0b00000111; //Для энкодера
?
Может: NewState=PINC & 0b00000011; //Для энкодера
Энкодер EC12D1564402 ALPS

Подключил правильно, в той строке ошибки нет, энкодер с кнопкой один из выводом МК для нее в единицу установлен. Уже пробовал просто убирать и единичку оттуда и обработчик нажатия кнопки, все равно без изменений...
geonov вне форума  
Оценка 0
При производстве драйверов силовых транзисторов компания Infineon использует различные технологии: JI, SOI, CT. Драйверы, выполненные с применением технологии SOI, имеют целый ряд преимуществ по сравнению с классическими JI-драйверами. В статье рассматриваются эти преимущества на примере новых семейств драйверов 650 В 2ED210x и 2ED218x.
Старый 25.05.2020, 07:42 #4
DmitriyVDN
Эксперт
 
Аватар для DmitriyVDN
 
Регистрация: 08.11.2009
Сообщений: 2,114
Репутация: 544
DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт
514 110
22 9
По умолчанию

как-то у вас опрос энкодера через опу выглядит может как-то так надо:
Код:
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)
DmitriyVDN вне форума  
Оценка 0
Старый 25.05.2020, 09:15 #5
geonov
Новичок
 
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
geonov Новичок
0 2
0 0
По умолчанию

Цитата:
Сообщение от DmitriyVDN Посмотреть сообщение
как-то у вас опрос энкодера через опу выглядит может как-то так надо:
Так тоже не получается. Теперь на старте вместо нулей отображается 1. Энкодер точно рабочий, пробовал конструкцию if ... else писать для опроса при повороте "крутилки" вообще какие то непонятные цифры отображаться начинают и с большой скоростью прибывать или убывать... Вряд ли это только из за "дребезга".
geonov вне форума  
Оценка 0
Старый 25.05.2020, 15:09 #6
DmitriyVDN
Эксперт
 
Аватар для DmitriyVDN
 
Регистрация: 08.11.2009
Сообщений: 2,114
Репутация: 544
DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт DmitriyVDN Эксперт
514 110
22 9
По умолчанию

вы в железе проверяете? 1.тогда на энкодер поставьте внешние подтяжки по 4.7к и проверьте правильность подключения самого энкодера
2. при передаче цифр в прерывание не выполняется атомарность доступа.
DmitriyVDN вне форума  
Оценка 0
Старый 25.05.2020, 16:41 #7
geonov
Новичок
 
Регистрация: 01.05.2020
Сообщений: 7
Репутация: 10
geonov Новичок
0 2
0 0
По умолчанию

Все разобрался!! Всем спасибо!! С помощью кусочка чужого кода, найденного в интернете, но все же понял в чем дело )))


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

Код:
#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
geonov вне форума  
Оценка 0
Старый 29.05.2020, 20:34 #8
SERGEY-314628
Новичок
 
Регистрация: 12.12.2010
Сообщений: 7
Репутация: 10
SERGEY-314628 Новичок
0 2
0 0
По умолчанию

Вообще о чём идёт речь ??? Где схема, где? где?
SERGEY-314628 вне форума  
Оценка 0
Ответ
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Оценка этой теме
Оценка этой теме:
Похожие темы
Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

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

Быстрый переход
Часовой пояс GMT +3, время: 21:25.
Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd. Перевод: zCarot
Вебинар Разбор новых уникальных модулей FMAC и CORDIC в микроконтроллерах общего назначения STM32G4 15.07.2020
Регуляторы VIPerPLUS — решения для источников питания на любой вкус (материалы вебинара)
Срезы портала ↓
Рейтинг@Mail.ru