Сколько всего можно запихать в прерывания?

kentik
Offline
Зарегистрирован: 28.03.2013

Здравствуйте, уважаемые форумчане.

Есть программа. уже накопилось в ней куча всего. текст реально большой. и все в ней нужно.

Появилась задача выполнять определенные действия гораздо быстрее (через определенный промежуток времени), нежели они дождутся своей очереди в loop().
На помощь приходят прерывания. А так как таймер1 уже занят для внешнего прерывания и таймер 0 занят для всяких там delay(), которые я тоже использую, то остается на камне atmega328p только таймер2.

что бы с самого начала освоения таймеров голова не пухла от обьема информации, принято решение использовать библиотеку MsTimer2
http://playground.arduino.cc/Main/MsTimer2

Используя код из примера библиотеки, под свои нужды, получаю:

void flash() {
                for(int i = 0; i < 10; i++) {
                   average=average+analogRead(A4);
                   delay(1);
                }
  average=average/10; 
  corrector=a/2+15;  
  
             if ((a<109)&&(a>47)){
                     if(average<(nullsensorI-corrector)){
                         aa = (nullsensorI - average)/6; 
                    if (aa>90) aa=90;
                       }
              }
   pwmWrite(enAB,a+aa);
}

void setup() {
  MsTimer2::set(100, flash); // 100ms period
  MsTimer2::start();
}

void loop() {
}

Но вот чувствую я, что плохо тут что-то. долго слишком в прерывание работать будет?
или для 100 милисекунд это в принципе нормальный код?
 

kentik
Offline
Зарегистрирован: 28.03.2013

я так понимаю, что первая моя ошибка - это использование delay(1); в функции 

X-Dron
Offline
Зарегистрирован: 24.01.2015

Откуда Вы взяли, что прерывания будет выполняться 100мс?
Я вижу 10 -12мс (в10-ти кратном цикле delay по миллисекунде).
100мс это период вызова.
В приципе здесь все нормально

 

kentik
Offline
Зарегистрирован: 28.03.2013

X-Dron пишет:

Откуда Вы взяли, что прерывания будет выполняться 100мс?
Я вижу 10 -12мс (в10-ти кратном цикле delay по секунде).
100мс это период вызова.
В приципе здесь все нормально


 

Да ниоткуда. просто боюсь, что все, что у меня в теле функции flash(), будет выполняться дольше, чем период вызова этой функции.

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kentik, ну так измерьте, методика быстро гуглится если что..    В прерывания  главное нельзя вставлять функции, использующие другие прерывания. А что у вас на аналоговом входе?

kentik
Offline
Зарегистрирован: 28.03.2013

dimax пишет:

А что у вас на аналоговом входе?


У меня там показания с операционного усилителя.

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

есть библиотека cyberlib.h, там delay_ms можно использовать в прерываниях (проверено)

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

dimax пишет:

kentik, ну так измерьте, методика быстро гуглится если что..    В прерывания  главное нельзя вставлять функции, использующие другие прерывания. А что у вас на аналоговом входе?

т.е. нельзя после запуска прерывания запустить другое прерывание?



attachinterrupt(0,flash,RISING);
void flash(){attachinterrupt(1,flash1,FALLING);}
void flash1(){...}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

dmitriykisliy, в этих строчках вы не запускаете прерывание в полном слысле этого слова, вы его разрешаете. Но вот сработать одно во время работы другого - не сможет.

kentik
Offline
Зарегистрирован: 28.03.2013

dmitriykisliy пишет:

есть библиотека cyberlib.h, там delay_ms можно использовать в прерываниях (проверено)

с этой cyberlib.h косяк выскочил 

 

void setup() 
{ 
  MCUSR = 0;
  wdt_disable();
   InitTimersSafe(); 
   bool success = SetPinFrequencySafe(enAB, frequency);
  //TCCR2B = TCCR2B & 0b11111000 | 6;
  pinMode(buttonStart, INPUT); 
  pinMode(revers, INPUT); 
  pinMode(enAB, OUTPUT);
  pinMode(shift, OUTPUT);
  digitalWrite(shift,LOW);
  
  pinMode(4,OUTPUT);//Настраиваем порты на выход
  pinMode(2,INPUT);//настраиваем порт на вход для отслеживания прохождения сигнала через ноль 
  
     GLCD.Init(0);
     GLCD.ClearScreen(0);
     
 D4_Low;  
 
     GLCD.ClearScreen(0);
     GLCD.SelectFont(mini6x10);
     GLCD.DrawBitmap(procent, 119,2);
     GLCD.DrawBitmap(x1000, 37,2);
     GLCD.DrawBitmap(bor, 0,3);

showvperednazad(); 

  attachInterrupt(0, detect_up, LOW);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
  GLCD.GotoXY(0,0);
    GLCD.print("1");

  StartTimer1(halfcycle, 40); //время для одного разряда ШИМ
  GLCD.print("2");
  StopTimer1(); //остановить таймер 
 
    GLCD.print("3");
      


//определяю базовую точку тока nullsensorI
    nullsensorI=0;
     for(int i = 0; i < 10; i++) {
        nullsensorI=nullsensorI+analogRead(A4);
        delay(1);
      }
    nullsensorI=nullsensorI/10;

 
//для тестов 
    GLCD.GotoXY(0,10);
    GLCD.print(nullsensorI);
//для теста


wdt_enable(WDTO_8S);
}
//********************обработчики прерываний*******************************
void halfcycle()  //прерывания таймера
{ 
  tic++;  //счетчик  
  if(Dimmer1 < tic ) D4_High; //управляем выходом
}

void  detect_up()  // обработка внешнего прерывания. Сработает по переднему фронту
{  
 tic=0;             //обнулить счетчик
 ResumeTimer1();   //запустить таймер
 attachInterrupt(0, detect_down, HIGH);  //перепрограммировать прерывание на другой обработчик
}  

void  detect_down()  // обработка внешнего прерывания. Сработает по заднему фронту
{   
 StopTimer1(); //остановить таймер
 D4_Low;//логический ноль на выходы
 tic=0;       //обнулить счетчик
 attachInterrupt(0, detect_up, LOW); //перепрограммировать прерывание на другой обработчик
} 
//*************************************************************************

Все зависает мертво на строчке attachInterrupt(0, detect_up, LOW);

 вот на экранчике цифирька "1" уже не выводится.
 

bwn
Offline
Зарегистрирован: 25.08.2014

Четыре диммера у меня с этой библой без проблем работали. Atmega328.

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

я ба не инициализировал прерывание (70 строка) , а запрещал или разрешал (вместо 70 строки) и через регистры. код есть готовый, но на компе(завтра выкину) или пример arduino.ru/forum/proekty/fuoz-na-arduino-nano-s-328-chipom

8, 9 строки кода

EIMSK &= ~ (1 << INT0); // Запретить прерывание 0

ну и 

 

//EICRA &= ~((1<<ISC00)|(1<<ISC01)); //прерывание вызавается при сигнале LOW
//EICRA |= (1<<ISC01); // FALLING – вызов прерывания при изменении уровня напряжения с высокого (HIGH) на низкое (LOW)
//EICRA |=(1<<ISC00)|(1<<ISC01) // RISING – вызов прерывания при изменении уровня напряжения с низкого (LOW) на высокое(HIGH)
// EICRA |= (1<<ISC00); // прерывание вызывается при изменении значения на входе;