Столкнулся со следующей проблемой.
Есть МК AtMega128 на нем настроены ряд прерываний:
- 2 по таймерам
- внешнее по нарастающему фронту на INT2
На вход INT2 подан сигнал с детектора ноля сетевого напряжения. В обработчике внешнего прерывания управляю временем открытия клапана на основе пропуска полупериодов (клапан на 220 В).
В основном цикле программы выполняю считывание температуры с датчиков DS18B20. Использую библиотеку для датчиков температуры http://chipenable.ru/index.php/componen ... 18b20.html
алгоритм опроса прост - считываю текущее значение температуры, запускаю новое преобразование на всех датчиках, через 1 секунду повторяем. Время отсчитывает таймер и кладет указатель на функцию опроса датчиков в кольцевой буфер, откуда в основном цикле производиться ее вызов, такой себе мини диспетчер задач. Библиотека по опросу датчиков работает на основе задержек и в момент формирования таймслотов глобально запрещает все прерывания, а затем разрешает их.
Собственно проблема в том, что при опросе датчиков (или просто глобальном запрете, а затем разрешении прерываний) происходят ложные срабатывания по внешнему прерыванию. Т.е. в данный момент, для проверки, я в обработчике INT2 просто инвертирую выход. Подключив осциллограф одним каналом на выход детектора, а второй на выход МК, который я инвертирую наблюдаю следующее:
- в случает отсутствий манипуляций с запретом/ разрешение глобально прерываний, фронты четко совпадают и смена состояния выхода четко соответствует переднему фронту сигнала с детектора
- в случае опроса датчика возникает дополнительные вызовы обработчика прерывания в следствии чего за один период выхода с детектора получаю 5 и более дополнительных смен состояний выхода Мк.
Вопрос из-за чего может возникать повторно прерывание и как этот эффект побороть, потому как в следствии этого я не корректно считаю периоды, а следовательно клапан фактически открыт меньше.
Инициализация прерывания
Код: Выделить всё
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: On
// INT2 Mode: Rising Edge
// INT3: Off
// INT4: Off
// INT5: Off
// INT6: Off
// INT7: Off
EICRA=0x30;
EICRB=0x00;
EIMSK=0x04;
EIFR=0x04;Код: Выделить всё
#define __save_interrupt() SREG
#define __restore_interrupt(var) SREG = (var)
#define __disable_interrupt() #asm("cli")
#define __enable_interrupt() #asm("sei")
#define __delay_cycles(var) delay_us((unsigned int)(var)/(_MCU_CLOCK_FREQUENCY_/1000000))
void OWI_WriteBit1(unsigned char pins)
{
unsigned char intState;
// Disable interrupts.
intState = __save_interrupt();
__disable_interrupt();
// Drive bus low and delay.
OWI_PULL_BUS_LOW(pins);
__delay_cycles(OWI_DELAY_A_STD_MODE);
// Release bus and delay.
OWI_RELEASE_BUS(pins);
__delay_cycles(OWI_DELAY_B_STD_MODE);
// Restore interrupts.
__restore_interrupt(intState);
}


