Прерывания+Serial будет ли конфликт?

gatsby163
Offline
Зарегистрирован: 10.03.2014

Доброго времени суток! Планирую собрать счетчик импульсов, импульсы буду считать с помощью прерываний, но, так же планирую получать колличество подсчиьанных импульсов с помощью серийного порта. Функцией прерывания пользуюсь впервые, читал что работа uart это тоже своего рода прерывания, поэтому возник вопрос как в данном случае будет работать код? Будет ли конфликт если во время получения импульсов я запрошу колличество полученых?


volatile boolean actionState = LOW;
long Impulse = 0;
long i = 0;

void setup() {
  Serial.begin(9600); 
  attachInterrupt(0, ImpulseCounter, RISING); 
}
 
void loop() {
   i = Impulse;
   if (Serial.available() > 0) {
  String param = Serial.readString();
    if(param=="1")
    Serial.println(i);
    }
}
 
void ImpulseCounter() {
  actionState != actionState;
  Impulse++;
  }

 

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

Этот - будет плохо работать. Иногда. Потому что Impulse не volatile, а строка 11 не завернута в ATOMIC_BLOCK ( cli() / sei() )

gatsby163
Offline
Зарегистрирован: 10.03.2014

Можно подробнее про ATOMIC_BLOCK? впервые слышу, пока на русском не нашел ничего толкового.

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

Третья ссылка в дружественном гугле: http://microsin.net/programming/avr/avr-gcc-atomically-and-non-atomically-executed-code-blocks.html

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

Прерывание может случиться в любой момент - между любыми двумя командами основной программы. Если мы говорим о наиболее распространенных моделях Ардуино (кстати, Вы не написали, с какой работаете), то они 8-разрядные. Следовательно, для копирования переменной Impulse в переменную i нужно несколько команд. Если прерывание вклинится в эту цепочку, результат работы окажется непредсказуемым. Поэтому на время выполнения i = Impulse нужно запретить прерывания.

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

gatsby163 пишет:

поэтому возник вопрос как в данном случае будет работать код? 

Поэтому возник ответ: 1) запустите 2) посмотрите как работает 3) расскажите нам.

gatsby163
Offline
Зарегистрирован: 10.03.2014

Там не про Arduino  речь идет. Библиотеку util/atomic.h для ардуино не могу найти а так примрно понял для чего она. спасибо за направление завтра проодолжу

gatsby163
Offline
Зарегистрирован: 10.03.2014

У меня стандартная UNO, запретить прерывания каким образом можно? Макросом util/atomic.h?) пока так и не понял как его с ARDUINO IDE подружить

gatsby163
Offline
Зарегистрирован: 10.03.2014

Пока к сожалению нету генератора импульсов под рукой, завтра протестирую

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

gatsby163 пишет:

Там не про Arduino  речь идет.

Ардуино это тот же AVR.

gatsby163 пишет:

Библиотеку util/atomic.h для ардуино не могу найти

Ничего искать не надо, всё уже есть. Нужно лишь подключить библиотеку через #include:

#include <util/atomic.h>

 

gatsby163
Offline
Зарегистрирован: 10.03.2014

Подскажите пожалуйста так правильно будет?

#include <util/atomic.h>
#define ATOMIC_BLOCK();

volatile boolean actionState = LOW;
volatile long Impulse = 0;
long i = 0;

void setup() {
  Serial.begin(9600); 
  attachInterrupt(0, ImpulseCounter, RISING); 
}
 
void loop() {
   ATOMIC_BLOCK() {
   cli();
   i = Impulse;
   sei();
  }
   if (Serial.available() > 0) {
  String param = Serial.readString();
    if(param=="1")
    Serial.println(i);
    }
}
 
void ImpulseCounter() {
  actionState != actionState;
  Impulse++;
  }

Impulse теперь volatile, вот с ATOMIC_BLOCK не понятно. правильно ли я его тут объявил или нужно с параметрами ATOMIC_RESTORESTATE или ATOMIC_FORCEON использовать? Компилятор вроде не ругается)

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

Вторую строку убираем. cli/sei этот макрос как раз и делает. Так что выбирайте что-то одно:

ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { i = Impulse; }