Arduino Сделать прерывание по FALLING и RISING на одном пине

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Сообщения: 36
Зарегистрирован: Вт ноя 11, 2014 22:38:33

Сообщение xintrea »

Здравствуйте!

Имеется Arduino UNO. Нужно сделать два аппаратных прерывания на пине D2. Один обработчик должен обрабатывать FALLING на этом пине, второй обработчик должен обрабатывать RISING на этом же пине.

Возможно ли такое сделать? Судя по документации, определить можно только одно прерывание на одном пине, если определить второе, оно отменит первое.

Может быть, есть способы как-то обойти эту проблему?
Реклама
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

всё можно сделать в одном обработчике.
сначала, например, настраиваешь на RISING.
когда зайдет в обработчик, меняешь настройку на FALLING.
после захода по FALLING, опять меняешь настройку на RISING.
и так до бесконечности ...
только нужно иметь флаг, по которому видишь текущую настройку.
и по состоянию флага выполняешь то или другое "тело" обработчика.
и окончании обработки инвертируешь сам флаг и настройку обработчика.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
Собутыльник Кота
Сообщения: 2804
Зарегистрирован: Вс фев 02, 2020 09:12:37

Сообщение 1en2 »

поставленная задача не имеет логики, поэтому процессору это не объяснить......настроить заранее на высокий уровень, а первым придёт низкий и пропустишь....если прерывания идут непредсказуемо, то как их обрабатывать, всё равно кто-то кого-то будет ждать...поэтому "никто никуда не спешит", дождутся очереди и обработаются.....т.е., если есть возможность, то обходиться без прерываний...))))
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

1en2 писал(а):поставленная задача не имеет логики, поэтому процессору это не объяснить......настроить заранее на высокий уровень, а первым придёт низкий и пропустишь....
поставленная задача имеет логику, так как какой-то уровень будет на пине, либо высокий либо низкий, одновременно два уровня не придут.
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

[uquote="1en2",url="/forum/viewtopic.php?p=4131553#p4131553"]поставленная задача не имеет логики, поэтому процессору это не объяснить......настроить заранее на высокий уровень, а первым придёт низкий и пропустишь....если прерывания идут непредсказуемо, то как их обрабатывать, всё равно кто-то кого-то будет ждать...поэтому "никто никуда не спешит", дождутся очереди и обработаются.....т.е., если есть возможность, то обходиться без прерываний...))))[/uquote]
Перед тем как настроить прерывание, читается эта нога и в соответствии со считанным уровнем, выставляется реакция на нужный фронт. Два спада или нарастания подряд невозможны априори. Потому, после реакции на один фронт, перенастраиваешься на противоположный и так до бесконечности. Но если все равно страшно, можно дополнительно читать ногу в прерывании для убедительности.
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15671
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

КОТИЩИ!!!
Хотя бы в исходный референс (хоть оффлайн, хоть онлайн) адурино - IDE заглянуть надо!
"...
Parameters

interrupt: the number of the interrupt (int)
pin: the pin number (Arduino Due, Zero only)
ISR: the ISR to call when the interrupt occurs; this function must take no parameters and return nothing. This function is sometimes referred to as an interrupt service routine.
mode:
defines when the interrupt should be triggered. Four contstants are predefined as valid values:
LOW to trigger the interrupt whenever the pin is low,
CHANGE to trigger the interrupt whenever the pin changes value
RISING to trigger when the pin goes from low to high,
FALLING for when the pin goes from high to low.
The Due board allows also:
HIGH to trigger the interrupt whenever the pin is high.
(Arduino Due, Zero only)
Returns

none
..."

:tea:
Реклама
Первый раз сказал Мяу!
Сообщения: 36
Зарегистрирован: Вт ноя 11, 2014 22:38:33

Сообщение xintrea »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4131552#p4131552"]всё можно сделать в одном обработчике.
сначала, например, настраиваешь на RISING.
когда зайдет в обработчик, меняешь настройку на FALLING.
после захода по FALLING, опять меняешь настройку на RISING.
и так до бесконечности ...
только нужно иметь флаг, по которому видишь текущую настройку.
и по состоянию флага выполняешь то или другое "тело" обработчика.
и окончании обработки инвертируешь сам флаг и настройку обработчика.[/uquote]

Я не написал, что время между фронтами "спада" и "подъема" где-то 500нс.

Arduino UNO в дефолте работает вроде как на 8МГц.

Вопрос в том, если настроить прерывание на CHANGE, хватит ли времени в прерывании еще и вызывать чтение значения с пина, чтобы понимать какое состояние - FALLING или RISING? Или хватит ли времени переконфигурировать прерывание внутри прерывания?
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="xintrea",url="/forum/viewtopic.php?p=4131628#p4131628"]Вопрос в том, если настроить прерывание на CHANGE, хватит ли времени в прерывании еще и вызывать чтение значения с пина?[/uquote]
Самому не понятно, что 500ns при 8MHz тактовой - это всего 4 такта, а учитывая, что речь про ардуино и 40 тактов для элементарного действия может не хватить.
Друг Кота
Аватара пользователя
Сообщения: 15671
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

UNO по заводским настройкам в виде кварцевого резонатора 16 МГц.
https://store.arduino.cc/products/arduino-uno-rev3/
Это если не клон какой-нить.
Ознакомьтесь хош с матчастью для начала...
Или поиграйтесь с симулятором (https://www.sites.google.com/site/unoardusim/) ....
Второе - по всей видимости недопонимание как алгоритм построить под имеющуюся задачу.
Ведь нам то все равно какой перепад прерывание вызвал - а уж затем по факту поимки перепада (после выхода из прерывания) проводим анализ события.
Ежли счет импульсов имелся ввиду - на то уже другое действо применять надо.
8)
Встал на лапы
Сообщения: 80
Зарегистрирован: Вс фев 21, 2021 13:01:40
Откуда: Прокопьевск

Сообщение Михаил_avr »

Спойлер

Код: Выделить всё

void int_ini(void)
{
//включим прерывания INT0 по нисходящему фронту
EICRA |= (1 << ISC00);
//разрешим внешнее прерывание INT0
EIMSK |= (1 << INT0);
}
//----------









ISR(INT0_vect)

{

if (digitalRead(2)==1)
{
//передний фронт



}
else
{
//задний фронт 



}
}
Вот там где написано передний и задний фронт можешь вызвать функции ,которые хотел (это и есть Falling и Rising) только надо ещё функцию инициализации вместо стандартной вызвать.
Первый раз сказал Мяу!
Сообщения: 36
Зарегистрирован: Вт ноя 11, 2014 22:38:33

Сообщение xintrea »

[uquote="BOB51",url="/forum/viewtopic.php?p=4131688#p4131688"]UNO по заводским настройкам в виде кварцевого резонатора 16 МГц.
https://store.arduino.cc/products/arduino-uno-rev3/
Это если не клон какой-нить.[/uquote]

Это фирменная Ардуина УНО, 10 лет назад купленная. Это не R3, но и не v.1. А что-то такое промежуточное. На официальном сайте информация только про R3, на других сайтах черт ногу сломит. Пока что я так и не смог понять что у меня за модель, и где для нее документацию искать.
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Ардуино УНО, Ардуино НАНО, 10 лет назад, какой МК установлен?
Собутыльник Кота
Сообщения: 2804
Зарегистрирован: Вс фев 02, 2020 09:12:37

Сообщение 1en2 »

ATMega328
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Ну раз Атмега328, есть 3 варианта построения:
1 вариант, тогда когда не знаем что на входе, да не важно
Спойлер

Код: Выделить всё

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Any change
EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (1<<ISC00);
EIMSK=(0<<INT1) | (1<<INT0);
EIFR=(0<<INTF1) | (1<<INTF0);
PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);

sei();


// External Interrupt 0 service routine
ISR(INT0_vect)
{
// Place your code here

	if((PIND & (1<<PIND2)) == 0)
	{
		// низкий уровень
	} 
	else
	{
		// высокий уровень
	}

}
2 вариант, определяем что есть на входе
Спойлер

Код: Выделить всё

	if((PIND & (1<<PIND2)) == 0)
	{	// низкий уровень
		EICRA=(0<<ISC11) | (0<<ISC10) | (1<<ISC01) | (1<<ISC00);
	} 
	else
	{	// высокий уровень
		EICRA=(0<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00);
	}
		
	EIMSK=(0<<INT1) | (1<<INT0);
	EIFR=(0<<INTF1) | (1<<INTF0);
	PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);

sei();

		
// External Interrupt 0 service routine  
ISR(INT0_vect)
{	
	if ((EICRA & (1<<ISC00)) == 0)	
	{
		EICRA |= (1 << ISC00);
	} 
	else 							
	{
		EICRA &= ~(1 << ISC00);          
	}
}
3 вариант, когда не знаем что на входе, да не важно
Спойлер

Код: Выделить всё

// External Interrupt(s) initialization
// Interrupt on any change on pins PCINT16-23: On INT18
EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(1<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);
PCMSK2=(0<<PCINT23) | (0<<PCINT22) | (0<<PCINT21) | (0<<PCINT20) | (0<<PCINT19) | (1<<PCINT18) | (0<<PCINT17) | (0<<PCINT16);
PCIFR=(1<<PCIF2) | (0<<PCIF1) | (0<<PCIF0);

sei();


// Pin change 16-23 interrupt service routine
ISR(PCINT2_vect)
{
	if((PIND & (1<<PIND2)) == 0)
	{
		// низкий уровень
	} 
	else
	{
		// высокий уровень
	}
}
Друг Кота
Аватара пользователя
Сообщения: 15671
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Если "фирменная" - то там должна быть еще одна АВРка(AtMega16U/8U) для мостаUSB-TTL у которой свой кварц.
У "клонов" в роли моста выступает СН340.
Но в любом случае те уны работают на "стандартной" частоте в 16МГц (если работать в рамках стандартных платформ ардуиноIDE).
(http://arduino.ru/Hardware/ArduinoBoardUno , http://doc.arduino.ua/ru/hardware/Uno)
8)
Касательно прерываний - там в принципе достаточно только контрольный флаг поставить, который затем в основном цикле приведет к переходу на обработчик события. Это же не под ассемблером условный возврат из прерывания с подстановкой адреса перехода через стек строить - в Си подобные фокусы с "вольным обращением" со стеком весьма непрактичны.
Опять же для измерения интервала другие алгоритмы используются.
В том числе "штатный референсовский" pulseIn() возвращающий длину сигнала в микросекундах (причем на любом цифровом входе).
:roll:
Ответить

Вернуться в «AVR»