Сколько всего можно запихать в прерывания?
- Войдите на сайт для отправки комментариев
Здравствуйте, уважаемые форумчане.
Есть программа. уже накопилось в ней куча всего. текст реально большой. и все в ней нужно.
Появилась задача выполнять определенные действия гораздо быстрее (через определенный промежуток времени), нежели они дождутся своей очереди в 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 милисекунд это в принципе нормальный код?
я так понимаю, что первая моя ошибка - это использование delay(1); в функции
Откуда Вы взяли, что прерывания будет выполняться 100мс?
Я вижу 10 -12мс (в10-ти кратном цикле delay по миллисекунде).
100мс это период вызова.
В приципе здесь все нормально
Откуда Вы взяли, что прерывания будет выполняться 100мс?
Я вижу 10 -12мс (в10-ти кратном цикле delay по секунде).
100мс это период вызова.
В приципе здесь все нормально
Да ниоткуда. просто боюсь, что все, что у меня в теле функции flash(), будет выполняться дольше, чем период вызова этой функции.
kentik, ну так измерьте, методика быстро гуглится если что.. В прерывания главное нельзя вставлять функции, использующие другие прерывания. А что у вас на аналоговом входе?
А что у вас на аналоговом входе?
У меня там показания с операционного усилителя.
есть библиотека cyberlib.h, там delay_ms можно использовать в прерываниях (проверено)
kentik, ну так измерьте, методика быстро гуглится если что.. В прерывания главное нельзя вставлять функции, использующие другие прерывания. А что у вас на аналоговом входе?
т.е. нельзя после запуска прерывания запустить другое прерывание?
attachinterrupt(0,flash,RISING); void flash(){attachinterrupt(1,flash1,FALLING);} void flash1(){...}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" уже не выводится.
Четыре диммера у меня с этой библой без проблем работали. Atmega328.
я ба не инициализировал прерывание (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); // прерывание вызывается при изменении значения на входе;