Здравствуйте, уважаемые форумчане.
Есть программа. уже накопилось в ней куча всего. текст реально большой. и все в ней нужно.
Появилась задача выполнять определенные действия гораздо быстрее (через определенный промежуток времени), нежели они дождутся своей очереди в loop().
На помощь приходят прерывания. А так как таймер1 уже занят для внешнего прерывания и таймер 0 занят для всяких там delay(), которые я тоже использую, то остается на камне atmega328p только таймер2.
что бы с самого начала освоения таймеров голова не пухла от обьема информации, принято решение использовать библиотеку MsTimer2
http://playground.arduino.cc/Main/MsTimer2
Используя код из примера библиотеки, под свои нужды, получаю:
02 | for ( int i = 0; i < 10; i++) { |
03 | average=average+analogRead(A4); |
10 | if (average<(nullsensorI-corrector)){ |
11 | aa = (nullsensorI - average)/6; |
19 | MsTimer2:: set (100, flash); |
Но вот чувствую я, что плохо тут что-то. долго слишком в прерывание работать будет?
или для 100 милисекунд это в принципе нормальный код?
я так понимаю, что первая моя ошибка - это использование delay(1); в функции
Откуда Вы взяли, что прерывания будет выполняться 100мс?
Я вижу 10 -12мс (в10-ти кратном цикле delay по миллисекунде).
100мс это период вызова.
В приципе здесь все нормально
Откуда Вы взяли, что прерывания будет выполняться 100мс?
Я вижу 10 -12мс (в10-ти кратном цикле delay по секунде).
100мс это период вызова.
В приципе здесь все нормально
Да ниоткуда. просто боюсь, что все, что у меня в теле функции flash(), будет выполняться дольше, чем период вызова этой функции.
kentik, ну так измерьте, методика быстро гуглится если что.. В прерывания главное нельзя вставлять функции, использующие другие прерывания. А что у вас на аналоговом входе?
А что у вас на аналоговом входе?
У меня там показания с операционного усилителя.
есть библиотека cyberlib.h, там delay_ms можно использовать в прерываниях (проверено)
kentik, ну так измерьте, методика быстро гуглится если что.. В прерывания главное нельзя вставлять функции, использующие другие прерывания. А что у вас на аналоговом входе?
т.е. нельзя после запуска прерывания запустить другое прерывание?
1
attachinterrupt(0,flash,RISING);
2
void
flash(){attachinterrupt(1,flash1,FALLING);}
3
void
flash1(){...}
dmitriykisliy, в этих строчках вы не запускаете прерывание в полном слысле этого слова, вы его разрешаете. Но вот сработать одно во время работы другого - не сможет.
есть библиотека cyberlib.h, там delay_ms можно использовать в прерываниях (проверено)
с этой cyberlib.h косяк выскочил
01
void
setup
()
02
{
03
MCUSR = 0;
04
wdt_disable();
05
InitTimersSafe();
06
bool
success = SetPinFrequencySafe(enAB, frequency);
07
//TCCR2B = TCCR2B & 0b11111000 | 6;
08
pinMode(buttonStart, INPUT);
09
pinMode(revers, INPUT);
10
pinMode(enAB, OUTPUT);
11
pinMode(shift, OUTPUT);
12
digitalWrite(shift,LOW);
13
14
pinMode(4,OUTPUT);
//Настраиваем порты на выход
15
pinMode(2,INPUT);
//настраиваем порт на вход для отслеживания прохождения сигнала через ноль
16
17
GLCD.Init(0);
18
GLCD.ClearScreen(0);
19
20
D4_Low;
21
22
GLCD.ClearScreen(0);
23
GLCD.SelectFont(mini6x10);
24
GLCD.DrawBitmap(procent, 119,2);
25
GLCD.DrawBitmap(x1000, 37,2);
26
GLCD.DrawBitmap(bor, 0,3);
27
28
showvperednazad();
29
30
attachInterrupt(0, detect_up, LOW);
// настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
31
GLCD.GotoXY(0,0);
32
GLCD.print(
"1"
);
33
34
StartTimer1(halfcycle, 40);
//время для одного разряда ШИМ
35
GLCD.print(
"2"
);
36
StopTimer1();
//остановить таймер
37
38
GLCD.print(
"3"
);
39
40
41
42
//определяю базовую точку тока nullsensorI
43
nullsensorI=0;
44
for
(
int
i = 0; i < 10; i++) {
45
nullsensorI=nullsensorI+analogRead(A4);
46
delay(1);
47
}
48
nullsensorI=nullsensorI/10;
49
50
51
//для тестов
52
GLCD.GotoXY(0,10);
53
GLCD.print(nullsensorI);
54
//для теста
55
56
57
wdt_enable(WDTO_8S);
58
}
59
//********************обработчики прерываний*******************************
60
void
halfcycle()
//прерывания таймера
61
{
62
tic++;
//счетчик
63
if
(Dimmer1 < tic ) D4_High;
//управляем выходом
64
}
65
66
void
detect_up()
// обработка внешнего прерывания. Сработает по переднему фронту
67
{
68
tic=0;
//обнулить счетчик
69
ResumeTimer1();
//запустить таймер
70
attachInterrupt(0, detect_down, HIGH);
//перепрограммировать прерывание на другой обработчик
71
}
72
73
void
detect_down()
// обработка внешнего прерывания. Сработает по заднему фронту
74
{
75
StopTimer1();
//остановить таймер
76
D4_Low;
//логический ноль на выходы
77
tic=0;
//обнулить счетчик
78
attachInterrupt(0, detect_up, LOW);
//перепрограммировать прерывание на другой обработчик
79
}
80
//*************************************************************************
Все зависает мертво на строчке 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); // прерывание вызывается при изменении значения на входе;