Например TDA7294

Форум РадиоКот :: Просмотр темы - прерывание от таймера 0
Форум РадиоКот
https://radiokot.ru/forum/

прерывание от таймера 0
https://radiokot.ru/forum/viewtopic.php?f=57&t=161596
Страница 1 из 1

Автор:  wws63 [ Сб мар 16, 2019 15:05:55 ]
Заголовок сообщения:  прерывание от таймера 0

Прошу специалистов помочь разобраться с проблемой.
В программке 3 ШИМа для управления RGB диодом. Скважность зависит от частоты входного сигнала на входе INT0.
ШИМ работает номрально, а для счета импульсов за период времени задействовал Таймер 0.
Но не считате, Где то ошибочка.
Код:
#include <avr/io.h>
#define F_CPU 8000000UL //8MHz
#include <util/delay.h>
#include <avr/interrupt.h>

volatile unsigned char Tic_Count = 0;
volatile unsigned char i = 0;
volatile unsigned char i_Count = 10;
#define BLUE_PB  1
#define BLUE_PWM    OCR1A
#define RED_PB   2
#define RED_PWM  OCR1B
#define GREEN_PB    3
#define GREEN_PWM   OCR2


ISR( INT0_vect )   // прерывание по внешнему сигналу
    {
   Tic_Count ++;
    }

ISR (TIMER0_OVF_vect)
    {
    TCNT0 = 60; // переполнение через 25мС
    i_Count--;
    if(i_Count == 0)
       {
       i_Count = 10; 
       i = Tic_Count;
       Tic_Count = 0x00;
       }
    }
int main(void)
{   //---------- настройка пинов МК
   DDRB |= (1<<BLUE_PB) | (1<<RED_PB) | (1<<GREEN_PB); // на выход RGB
   PORTB &= ~((1<<BLUE_PB) | (1<<RED_PB) | (1<<GREEN_PB));
   DDRD |= (1<<2); // PD2 на вход (INT0)
   PORTD |= (1 << 2); // Включение подтягивающего резистора
   MCUSR |= (1 << ISC00) | (1 << ISC01); // Передний фронт сигнала
   GICR  = (1 << INT0);                 // Включение входа прерывания
   sei(); /* Общее разрешение прерываний */
   //---------- Таймер 1---------------
   TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
   TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
   TCNT1 = 0x00;
   ICR1 = 0xFF;
   OCR1A = 0x00;
   OCR1B = 0x00;
    //---------- Таймер 2----------------------------
   TCCR2 |= (1 << COM21) | (1 << WGM21) | (1 << WGM20) | (1 << CS20);
   TCNT2 = 0x00;
   OCR2 = 0x00;
   //---------- Таймер 0--------------------------------
   TCCR0 = 0b00000101; // Т0 на внутр.такт, делитель 1024
   TCNT0 = 60; // переполнение через 25мС
   i_Count = 10;
   TIMSK |= (1 << TOIE0); /* Разрешить прерывание по                       
                                переполн.Т0*/
   sei();
   
   while(1)
   {
       //----------
       if (i>26) 
           {
          BLUE_PWM = 0;
          RED_PWM  = 255;   
          GREEN_PWM = 0;
         }
      
          //----------
       if (i>15) 
            {
          BLUE_PWM = 250;
          RED_PWM  = 250;   
          GREEN_PWM = 250;
          }
      
             
           if (i<8) 
                {
              BLUE_PWM = 0;
              RED_PWM  = 0;    // зеленый
              GREEN_PWM = 250;
           }
      
        }
   }


Автор:  VALNER [ Вс мар 17, 2019 02:00:29 ]
Заголовок сообщения:  Re: прерывание от таймера 0

У вас pin INT0 настроен на выход, а не на вход. Ну и в замен подтяжки вы просто держите на D2 высокий лог. уровень. Следовательно из за неправильной настройки порта не срабатывают прерывания на INT0.

Цитата:
DDRD |= (1<<2); // PD2 на вход (INT0) <--(это убрать)
PORTD |= (1 << 2); // Включение подтягивающего резистора


Надеюсь это единственная причина и это вам поможет, если вы сами это еще не нашли.

И да. Та часть что в бесконечном цикле тоже будет работать не правильно

Цитата:
while(1)
{
//----------
if (i>26)
{
BLUE_PWM = 0;
RED_PWM = 255;
GREEN_PWM = 0;
}

//----------
if (i>15)
{
BLUE_PWM = 250;
RED_PWM = 250;
GREEN_PWM = 250;
}


if (i<8)
{
BLUE_PWM = 0;
RED_PWM = 0; // зеленый
GREEN_PWM = 250;
}

}


Так как если і больше 26, то оно и больше 15, а по скольку у вас три независимых условия то оно всегда будет принимать значение того что выполняется последним. Их лучше расписать через else if()

Автор:  wws63 [ Вс мар 17, 2019 04:09:21 ]
Заголовок сообщения:  Re: прерывание от таймера 0

Да, я с направлением порта напутал. Привык, что в ПИКушках 1- вход.
А по поводу цикла программы, если else будет громоздко.
Можно ли обойтись таким нелюбимым всеми оператором goto ?
Код:
while(1)
   {
 //----------
m:
       if (i>26) 
           {
          BLUE_PWM = 0;
          RED_PWM  = 255;   
          GREEN_PWM = 0;
                     goto  m; 
         }
      
          //----------
       if (i>15) 
            {
          BLUE_PWM = 250;
          RED_PWM  = 250;   
          GREEN_PWM = 250;
                         goto m;
          }
      
             
           if (i<8) 
                {
              BLUE_PWM = 0;
              RED_PWM  = 0;    // зеленый
              GREEN_PWM = 250;
                         goto  m;
           }
         }

Автор:  bafomet911 [ Вс мар 17, 2019 06:31:14 ]
Заголовок сообщения:  Re: прерывание от таймера 0

А если так:
Спойлерif(i<8){...}
if(i>8&&i<15){...}
if(i>15&&i<26){...}
if(i>26){...}

Не устроит?

Автор:  wws63 [ Вс мар 17, 2019 07:34:19 ]
Заголовок сообщения:  Re: прерывание от таймера 0

А если так:
Не устроит?

Я приводил упрощенный пример.
В реальном проекте проверка идет от 8 до 26 каждое целое значение. Т.е 8, 9, 10...26
Наверное правильнее будет сделать мне сравнение с число
if (i>26) {}
if (i==26) {}
if (i==25) {}
.....
if(i==8) {}
if(i<8) {}

Автор:  Ivanoff-iv [ Вс мар 17, 2019 09:26:17 ]
Заголовок сообщения:  Re: прерывание от таймера 0

ну, если это последовательный ряд чисел, то я бы применил массив...
Код:
if (i>26) i=26;
if (i<=8) {i=0;} else {i-=8;};
Blue=BLUE_PWM[i];
Red=RED_PWM[i];
Green=GREEN_PWM[i];
или свитч кейс:
Код:
 if (i>26) i=26;
switch (i)
{
case 26: ..... break;
case 25: ..... break;
..............,..........
case 9: ...... break;
default: .......
};

Автор:  ARV [ Вс мар 17, 2019 09:52:06 ]
Заголовок сообщения:  Re: прерывание от таймера 0

wws63 писал(а):
если else будет громоздко
интересно, с чего вдруг?
Код:
if(cond_1){
  // первый выбор
} else if(cond_2){
  // второй выбор
} else if (cond_3){
  // третий выбор
} else {
  // если ничего не подошло
}


Добавлено after 3 minutes 36 seconds:
если сравнивате "цепочкой" по условию "больше" - начинайте с наибольшего. т.е. если сравниваем с числами 5, 10, 15 и 20, то надо писать в такой последователньости
Код:
if(x > 20){
  // x более 20
} else if(x > 15){
  // х более 15, но менее или равно 20
} else if(x > 10){
  // х более 10, но менее или равно 15
} else if(x > 5){
  // х более 5, но менее или равно 10
} else {
  // х менее или равно 5
}

Автор:  wws63 [ Вс мар 17, 2019 11:31:34 ]
Заголовок сообщения:  Re: прерывание от таймера 0

если сравнивате "цепочкой" по условию "больше" - начинайте с наибольшего.

А выход из процедуры при условии совпадения без goto ?
Код:
  if (i>26)  // больше 3100 об/мин
          {
          BLUE_PWM = 0;
          RED_PWM  = 255;    // красный
          GREEN_PWM = 0;
          goto m; //----- убрать?
          }

Автор:  ARV [ Вс мар 17, 2019 11:38:03 ]
Заголовок сообщения:  Re: прерывание от таймера 0

какой выход? цепочка if - else if срабатывает только в одном месте, все остальные проходят мимо. "выход" не требуется, вся цепочка - это как бы один оператор.

Автор:  wws63 [ Вс мар 17, 2019 12:16:53 ]
Заголовок сообщения:  Re: прерывание от таймера 0

вся цепочка - это как бы один оператор.

Спасибо, завтра посмотрю как в "железе" работает.

Автор:  Ivanoff-iv [ Вс мар 17, 2019 12:33:07 ]
Заголовок сообщения:  Re: прерывание от таймера 0

поправил прошлое сообщение (дописал код на кейсах)...
сейчас нет возможности проверить, но мне кажется, если массивы во флеш разместить то по ресурсоемкости метод "иф-елзе" будет самым громоздким... а может и нет, если оптимизатор правильно сработает... (может кто промерит объём кода и скорость выполнения)

Автор:  wws63 [ Вс мар 17, 2019 14:39:01 ]
Заголовок сообщения:  Re: прерывание от таймера 0

поправил прошлое сообщение (дописал код на кейсах)...

Буду пробовать все варианты

Автор:  wws63 [ Пн мар 18, 2019 16:05:26 ]
Заголовок сообщения:  Re: прерывание от таймера 0

Застрял на ровном месте. В Протеусе все работает на УРА, скважность с каждого канала ШИМ меняется в заданных параметрах, строго по частоте входного сигнала.
А в "железе" одни глюки. Светодиоды мигают хаотично, при этом изменение частоты входного сигнала не дает почти никаких изменений. Перепробовал все.
Снижал частоту генерации ШИМ (менее сотни Гц), думал может РЖБ - лента, изменял фронты сигнала на входе INT0, менял контроллер, игрался с тактовой частотой, менял пороги срабатывания ... Короче все , что можно. Разумеется, проверил монтаж на плате (сопли, обрывы). :dont_know:
В общем не знаю, в какую сторону копать :( Может есть какие то подводные камни с Атмегой 8?

Автор:  Ivanoff-iv [ Пн мар 18, 2019 16:20:15 ]
Заголовок сообщения:  Re: прерывание от таймера 0

питание мк стабльное?
блокировочные конденсаторы имеются?
ресет к плюсу притянут?
как разведены ключи лент?
схему давай!

Автор:  wws63 [ Пн мар 18, 2019 16:55:37 ]
Заголовок сообщения:  Re: прерывание от таймера 0

питание мк стабльное?
блокировочные конденсаторы имеются?
ресет к плюсу притянут?
как разведены ключи лент?
схему давай!

Причина найдена!

Автор:  wws63 [ Вт мар 19, 2019 16:43:15 ]
Заголовок сообщения:  Re: прерывание от таймера 0

Вместо регистра MCUCR было записано MCUSR.
Студия 6 (как впрочем и 4) на ноутбуке нормально компилировала в хекс, приносил проект на другой комп там прошивал и ступор.
Когда попытался внести изменения в программу и заново откомпилировать уже на компе, студия 6 начала ругаться на MCUSR.
Мистика! :dont_know:
Едем дальше :write:

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/