Перестает работать loop при работе прерывания по таймеру.

Bagrin
Offline
Зарегистрирован: 10.05.2021

Пишу скетч под atmega328p, где используется прерывание 2 таймер счетчика. 

Все, что в функции прерывания работает отлично, но вообще не работает все что написано в процедуре loop.

Почему?

Догадываюсь, что нужно что то настроить в нулевом таймере... или нет?

 

b707
Offline
Зарегистрирован: 26.05.2017

код выкладывайте, без этого не о чем говорить

nik182
Offline
Зарегистрирован: 04.05.2015

Такая хрень случается, когда прерывание таймера слишком длинное и на остальное не остается времени.

Bagrin
Offline
Зарегистрирован: 10.05.2021

int x = 1;
unsigned long time_f;
void setup() {
  
  TCCR1B =  0b00000001;
  TCCR1A =  0b00100001;
  TCCR2B =  0b00000001;
  TCCR2A =  0b10100001;

  TIMSK2 |= (1<<0); 
  
  SREG |= (1<<7); 
  DDRD  |= (1<<3);
  PORTD &=~(1<<3);      
  DDRB  |= ((1<<2) | (1<<3));
  PORTB &=~((1<<2) | (1<<3)); 
}

ISR (TIMER2_OVF_vect){  
time_f = micros();
....
....
....
....
func1();
if((micros()-time_f) < 1 {
func2();
}
}

void loop(){
func3();
}

 

 

 

Bagrin
Offline
Зарегистрирован: 10.05.2021

Выполняется func1() и func2() . во первых не могу понять почему вызывается func2(), неужели вся функция прерывания выполняется меньше 1 мкс. У меня там длиннющий код из 25 команд.

Во вторых не выполняется func3();

nik182  

я правильно понял, что если функция прерывания будет выполнятся очень долго, то не будет вызываться loop(). Очень долго это 256*(время такта) ?

nik182
Offline
Зарегистрирован: 04.05.2015

Такт системы 4 мкс, строка 25 будет выполняться всегда. Программирование прерываний подразумевает выполнение внутри прерывания только временизависимого кода. Типа выставления ноги при управлении тиристором. Всё остальное следует делать в цикле луп, по флагу из прерывания. Мы так и не увидели прерывание полностью. С коммерческими тайнами в платный раздел. Там помогут.

sadman41
Offline
Зарегистрирован: 19.10.2016

На месте компилятора я строку 25 вообще бы отказался обрабатывать.

micros() в ISR "не ходит".

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

А с какой целью isr прописан внутри setup ???

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:
micros() в ISR "не ходит".

с чего бы это, с миллисом не спутаЛ?

b707
Offline
Зарегистрирован: 26.05.2017

Bagrin пишет:

во первых не могу понять почему вызывается func2(), неужели вся функция прерывания выполняется меньше 1 мкс.

Вы в условии знак "больше- меньше" не перепутали?

Строка 25 и будет выполнятся, если длина прерывания менее 1 мкс

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

sadman41 пишет:
micros() в ISR "не ходит".

с чего бы это, с миллисом не спутаЛ?

Полноценно не ходит.

ISR(TIMER0_OVF_vect) {
...
	timer0_fract = f;
	timer0_millis = m;                <<<<<<< (1)
	timer0_overflow_count++;   <<<<<<< (2)
}

unsigned long millis() {
...
	cli();
	m = timer0_millis;                <<<<<<< (1)
	SREG = oldSREG;

	return m;
}

unsigned long micros() {
	m = timer0_overflow_count;  <<<<<<<  (2)
...
	SREG = oldSREG;
	
	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

 

Bagrin
Offline
Зарегистрирован: 10.05.2021

nik182 пишет:
Такт системы 4 мкс, строка 25 будет выполняться всегда. Программирование прерываний подразумевает выполнение внутри прерывания только временизависимого кода. Типа выставления ноги при управлении тиристором. Всё остальное следует делать в цикле луп, по флагу из прерывания. Мы так и не увидели прерывание полностью. С коммерческими тайнами в платный раздел. Там помогут.

1. Спасибо за намек про 4 мкс, выставил предделитель 0-го таймера на 1. 

  TCCR0B |=  (1<<0);
  TCCR0B &= ~(1<<1);
  TCCR0B &= ~(1<<2); 

Теперь работает micros в прерывании и я измерил время выполнения функции прерывания = 3мкс.

ВСЕ заработало! Даже не сразу понял. Дело было в том что нулевой таймер работал слишком медленно.

Bagrin
Offline
Зарегистрирован: 10.05.2021

Komandir пишет:

А с какой целью isr прописан внутри setup ???

Извините, скобочку забыл

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Bagrin пишет:


int x = 1;
unsigned long time_f;
void setup() {
  
  TCCR1B =  0b00000001;
  TCCR1A =  0b00100001;
  TCCR2B =  0b00000001;
  TCCR2A =  0b10100001;

  TIMSK2 |= (1<<0); 
  
  SREG |= (1<<7); 
  DDRD  |= (1<<3);
  PORTD &=~(1<<3);      
  DDRB  |= ((1<<2) | (1<<3));
  PORTB &=~((1<<2) | (1<<3)); 
}

ISR (TIMER2_OVF_vect){  
time_f = micros();
....
....
....
....
func1();
if((micros()-time_f) < 1 {
func2();
}
}

void loop(){
func3();
}

А код-то где? Он секретный?

Тогда

b707 пишет:

не о чем говорить

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

  ТС, почитайте что нить о volatile, есть такой модификтор. Было бы не плохо, если бы работая с прерываниями вы понимали что такое атомарность. Ну а если вам лень, то для всех переменных объявленных глобально и используемых в прерываниях добавляйте этот модификатор. В вашем случае хуже не будет. Например:

volatile unsigned long time_f;

 

Bagrin
Offline
Зарегистрирован: 10.05.2021

brokly пишет:

  ТС, почитайте что нить о volatile, есть такой модификтор. Было бы не плохо, если бы работая с прерываниями вы понимали что такое атомарность. Ну а если вам лень, то для всех переменных объявленных глобально и используемых в прерываниях добавляйте этот модификатор. В вашем случае хуже не будет. Например:

volatile unsigned long time_f;

 

Спасибо за любой совет, мне не лень, обязательно почитаю.

Я первый раз на форуме, но чувствуется какая то агрессия среди завсегдатаев, чтоб не дай бог проект не оказался коммерческим и я не заработал не поделившись с остальными) 

Код не секретный, но я считаю нет смысла кидать километр кода , и достаточно кинуть кусок, где возникает суть вопроса. И, как оказалось, я был прав. Уважаемому nik182  этого оказалось достаточным и он помог, ткнув в правильном направление, за что ему и остальным огромное спасибо!) Всем добра!

Bagrin
Offline
Зарегистрирован: 10.05.2021

Тема закрыта

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Bagrin пишет:

агрессия среди завсегдатаев, чтоб не дай бог проект не оказался коммерческим и я не заработал не поделившись с остальными) 

Точно подмечено! Больше того, старожилы постоянно пытаются украсть код новичков, ведь в нем всегда много свежих идей и приемов программирования! Пруфы в #1 и #13! Вы очень мудро поступили, не дав полный код

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Bagrin пишет:

Код не секретный, но я считаю нет смысла кидать километр кода , и достаточно кинуть кусок, где возникает суть вопроса. 

Вы неправильно считаете.

Если Вы задаете вопрос, сопровождать его следует кодом, который компилируется. Вы можете сколько угодно выбрасывать фрагменты из своего первоначального кода, но тот остаток, что Вы помещаете на форуме, должен с одной стороны компилироваться, а с другой - иллюстрировать проблему.