Страница 1 из 1

прерывание от таймера 0

Добавлено: Сб мар 16, 2019 15:05:55
wws63
Прошу специалистов помочь разобраться с проблемой.
В программке 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;
			  }
		
		  }
	}


Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 02:00:29
VALNER
У вас 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()

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 04:09:21
wws63
Да, я с направлением порта напутал. Привык, что в ПИКушках 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;
			  }
         }

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 06:31:14
bafomet911
А если так:
Спойлерif(i<8){...}
if(i>8&&i<15){...}
if(i>15&&i<26){...}
if(i>26){...}
Не устроит?

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 07:34:19
wws63
[uquote="bafomet911",url="/forum/viewtopic.php?p=3593428#p3593428"]А если так:
Не устроит?[/uquote]
Я приводил упрощенный пример.
В реальном проекте проверка идет от 8 до 26 каждое целое значение. Т.е 8, 9, 10...26
Наверное правильнее будет сделать мне сравнение с число
if (i>26) {}
if (i==26) {}
if (i==25) {}
.....
if(i==8) {}
if(i<8) {}

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 09:26:17
Ivanoff-iv
ну, если это последовательный ряд чисел, то я бы применил массив...

Код: Выделить всё

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: .......
};

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 09:52:06
ARV
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
}

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 11:31:34
wws63
[uquote="ARV",url="/forum/viewtopic.php?p=3593508#p3593508"]если сравнивате "цепочкой" по условию "больше" - начинайте с наибольшего.[/uquote]
А выход из процедуры при условии совпадения без goto ?

Код: Выделить всё

  if (i>26)  // больше 3100 об/мин
	       {
		    BLUE_PWM = 0;
		    RED_PWM  = 255;    // красный
		    GREEN_PWM = 0;
		    goto m; //----- убрать?
	       }

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 11:38:03
ARV
какой выход? цепочка if - else if срабатывает только в одном месте, все остальные проходят мимо. "выход" не требуется, вся цепочка - это как бы один оператор.

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 12:16:53
wws63
[uquote="ARV",url="/forum/viewtopic.php?p=3593594#p3593594"]вся цепочка - это как бы один оператор.[/uquote]
Спасибо, завтра посмотрю как в "железе" работает.

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 12:33:07
Ivanoff-iv
поправил прошлое сообщение (дописал код на кейсах)...
сейчас нет возможности проверить, но мне кажется, если массивы во флеш разместить то по ресурсоемкости метод "иф-елзе" будет самым громоздким... а может и нет, если оптимизатор правильно сработает... (может кто промерит объём кода и скорость выполнения)

Re: прерывание от таймера 0

Добавлено: Вс мар 17, 2019 14:39:01
wws63
[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3593653#p3593653"]поправил прошлое сообщение (дописал код на кейсах)...[/uquote]
Буду пробовать все варианты

Re: прерывание от таймера 0

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

Re: прерывание от таймера 0

Добавлено: Пн мар 18, 2019 16:20:15
Ivanoff-iv
питание мк стабльное?
блокировочные конденсаторы имеются?
ресет к плюсу притянут?
как разведены ключи лент?
схему давай!

Re: прерывание от таймера 0

Добавлено: Пн мар 18, 2019 16:55:37
wws63
[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3594637#p3594637"]питание мк стабльное?
блокировочные конденсаторы имеются?
ресет к плюсу притянут?
как разведены ключи лент?
схему давай![/uquote]
Причина найдена!

Re: прерывание от таймера 0

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