С чего бы вот такой код в прерывании не работает (при обычном вызове работает)

vlkam
Offline
Зарегистрирован: 17.02.2013

 Собственно есть работающий код, решил его в прерывание засунуть и он почему то перестал работать, ловит максимум один имульс. Доходит до условия     if(PreamblePulseCount != 12){return;} только с одним импульсом

	int duration[12];
	byte PreamblePulseCount;

	int rs = digitalRead(HCS_RECIEVER_PIN);

	if(rs == 0){
		return;
	}

	// что то поймали, будем анализировать
	
	unsigned long TimeStartReading = micros();
	unsigned long PulseStart = TimeStartReading;
	unsigned long curpoz = TimeStartReading;
		
	int stat = 1;
	int tdur = 0;
	PreamblePulseCount = 0;	

	int i,j;

	// ловим преамбулу //////////////////////////////////////////////////////////////////////

	// Преамбула состоит из 12 импульсов, типичная длительность 9200 мкс 
	// Длительность преамбулы 23 базовых импульсов Те, типичный импульс Те 400 мкс
	while((curpoz - TimeStartReading) < 20000){
			
		rs = digitalRead(HCS_RECIEVER_PIN);
			
		if (stat != rs) { // состояние изменилось
			if(stat == 1 && rs == 0){ 
				// окончание импульса
				tdur = curpoz - PulseStart;
				if(tdur < 300 || tdur > 600){
					break;
				}
				duration[PreamblePulseCount] =  tdur;
				PreamblePulseCount ++;
				stat = 0;

				if(PreamblePulseCount == 12){
					break;
				}

			} else { 
				// начало импульса
				stat = 1;
				PulseStart = curpoz;
			}
		}
		curpoz = micros();
	}
	
	if(PreamblePulseCount != 12){
		return;
	}

 

leshak
Offline
Зарегистрирован: 29.09.2011

С того что, возможно, невнимательно читали attachInterrupt(interrupt, function, mode) | Аппаратная платформа Arduino

раздел "замечание по использованию".

Там упоминается millis(), но к micros() - это тоже относится (вообщем к любым функциям времени). ВОзможно еще что-то нарушили (код не целиком дали, поэтому этого не видно, как вы объявляли переменные и т.п.).

И вообще - идея делать while(как-то-длинное-условие) - внутри обработчика прерывание - это "фу, фу, фу..."

Ваша задача - "словили прерывание", сделать там "минимально необходимую работу" (прочитать время, состояния входов...) и как можно быстрее выйти из обработчика. Все "теждолое-вычислительное-ожидательное" - должно быть в loop(). Обработчик это "внештатная ситуация". Когда процессор "отвлекли от основных задач..." Поэтому нужно "не на долго отвлекать..."

vlkam
Offline
Зарегистрирован: 17.02.2013

leshak пишет:
возможно, невнимательно читали .... Там упоминается millis(), но к micros() - это тоже относится (вообщем к любым функциям времени).

Читал то как раз внимательно и поскольку micros() там не упоминается рассчитывал, что его применять можно. Тем более, что прошелся поиском и вроде народ micros() применяет..

Если все таки нельзя, то конечно понятно, почему не работает. Спасибо

leshak пишет:
вообще - идея делать while(как-то-длинное-условие) - внутри обработчика прерывание - это "фу, фу, фу..."

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

Вообще конечно буду переписывать

leshak
Offline
Зарегистрирован: 29.09.2011

vlkam пишет:

Читал то как раз внимательно и поскольку micros() там не упоминается рассчитывал, что его применять можно. Тем более, что прошелся поиском и вроде народ micros() применяет..

Ну все функции перечислить не возможно.... главное суть понять. Когда у вас сработал обработчик прерывания и вызвалась ваша функция "обработки прерываний" - в этот момент все остальные прерывания (внешние, прерывания таймера, прихода данных по Serial  и т.п.) - запрещены. не могут сработать.

Следовальное "часы стоят", "серил не слушаем", прерывание на другом пине - поймать не можем..... и т.п. 

Глючат и все функции которые зависят от этого delay (так как он использует внутри millis()) и т.д. и т.п.

Поэтому и важно - как можно раньше выйти из функции обработчика. Это как-бы "аврал...", а находится в этом режиме долго - череповато.

В ваш код - сильно не вникал. Но.... Вот вещи типа " if (stat != rs) { // состояние изменилось"  - можно попытатся убрать. Понастраивать точнеие на что именно будет срабатывать прерывание. на CHANGE, на RAISE и т.п.

Возможно и необходимость чтения пина отпадет (если мы знаем, что прерывание срабатывает при переходе с LOW на HIGH, то зачем читать пин? И так знаем что он HIGH)

Серию импульсов считать нужно?

Ну так просто заведите какой-то счетчик cnt++

И когда он будет cnt>12 - выполняйте что-вам-там нужно....

 

Вообщем - тупо "скопировать" логику с loop в прерывания - не выйдет. Нужно переписавать/передумывать алгоритм под "прерывестый поток исполнения", а не "непрерывный".

 

vlkam
Offline
Зарегистрирован: 17.02.2013

leshak пишет:
Вообщем - тупо "скопировать" логику с loop в прерывания - не выйдет. Нужно переписавать/передумывать алгоритм под "прерывестый поток исполнения", а не "непрерывный".

Это я уже понял :-)
Да, буду переписывать на логику прерываний, прерывание типа CHANGE и по нему ловить фронт/конец импульса