и прерывания то работают, там в программе по ним ещё и импульсы считываются с датчика скорости. Но до того момента пока контроллер не заснёт.
Вот код:
#include <mega8.h> #include <delay.h>
char i = 1; // функция beeper char x; // функция beeper char beep1,beep2; // звуковая индикация функции beeper char z1,z2,z3,z4,z5,z6; // защита системы char mig1,mig2,mig3; // защита системы мигаем светодиодом char crash = 0; // флаг аварии, отказа БС char go = 0; // если 1, то едем, всё в норме, если 0 - стоим (день). // Если 2 значит ночь. char PWM = 0; // процент ШИМа int t,t1,t2,t3; // время (таймер 0) int V = 0; // количество импульсов (6 импульсов на метр) int Kimp = 0; // количество импульсов в секунду (скорость)
// External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { V++; // считываем скорость (количество импульсов датчика) MCUCR=0x0F; }
while (1) { //************************************* ЗАЩИТА СИСТЕМЫ ************************************ //*******************************************************************************************
*/ if (mig2 == 2) // если КЗ на линии БС {OCR2 = 0x00; crash = 1;} // то вырубаем линию else { // зажигание скорость свет if ((PIND.3 == 1)&&(Kimp >= 6)&&(PINB.4 == 0)) go = 1; // есть движение, всё в норме else { if ((PIND.3 == 0)||(Kimp < 6)) // если нет движения, значит стоим, go = 0; // либо выключенно зажигание - свет выключаем }
// зажигание свет if ((PIND.3 == 1)&&(PINB.4 == 1))// если включаем зажигание и наружное освещение go = 2; // значит наступила ночь - включаем свет на // полную мощность
if (go == 1) // если есть движение и всё в норме включаем свет { // соответственно скорости if ((OCR2 < PWM)&&(t3 == 0)) {OCR2++; t3 = 73;} // включаем ближний свет
if ((OCR2 > PWM)&&(t3 == 0)) {OCR2--; t3 = 73;} // плавно снижаем мощность
if (Kimp <= 33) // скорость до 20 км/ч {PWM = 0x59;} // ШИМ 35%
if ((Kimp > 33)&&(Kimp <= 50)) // скорость до 30 км/ч {PWM = 0x66;} // ШИМ 40%
if ((Kimp > 50)&&(Kimp <= 66)) // скорость до 40 км/ч {PWM = 0x73;} // ШИМ 45%
if ((Kimp > 66)&&(Kimp <= 83)) // скорость до 50 км/ч {PWM = 0x80;} // ШИМ 50%
if ((Kimp > 83)&&(Kimp <= 100)) // скорость до 60 км/ч {PWM = 0x8C;} // ШИМ 55%
if ((Kimp > 100)&&(Kimp <= 116)) // скорость до 70 км/ч {PWM = 0x99;} // ШИМ 60%
if ((Kimp > 116)&&(Kimp <= 133)) // скорость до 80 км/ч {PWM = 0xA6;} // ШИМ 65%
if ((Kimp > 133)&&(Kimp <= 150)) // скорость до 90 км/ч {PWM = 0xB3;} // ШИМ 70%
if ((Kimp > 150)&&(Kimp <= 166)) // скорость до 100 км/ч {PWM = 0xC0;} // ШИМ 75%
if (Kimp > 166) // скорость более 100 км/ч {PWM = 0xCC;} // ШИМ 80% }
if ((go == 2)&&(OCR2 < 0xFF)&&(t3 == 0)) { OCR2++; t3 = 73; // плавно включаем ближний на полную мощность } // за 3 сек.
if ((go == 0)&&(OCR2 > 0x00)&&(t3 == 0)) { OCR2--; t3 = 73; // плавно выключаем свет } }
//*************************************** ДАЛЬНИЙ СВЕТ ************************************* //******************************************************************************************** if (mig3 == 2) // если КЗ на линии ДС {OCR1B = 0x00;} // то вырубаем линию else { if ((PIND.3 == 1)&&(PINC.1 == 1)&&(OCR1B < 0xFF)&&(t1 == 0)) { // если включаем дальний с задержкой 0,5 сек. OCR1B++; t1 = 12; }
if ((PIND.3 == 1)&&(PINC.1 == 0)&&((PINB.4 == 0))&&(OCR1B > 0)) { // если выключаем дальний при выключенном нар.освещ. OCR1B = 0x00; }
if (((PIND.3 == 0)||(PINC.1 == 0))&&((go == 0)||(go == 2))&&(OCR1B > 0)&&(t1 == 0)) { // если выключаем дальний при включенном нар.освещ. OCR1B--; t1 = 73; // с задержкой 3 сек. } }
//**************************************** ПРОТИВОТУМАННЫЙ СВЕТ ************************** //******************************************************************************************
if (mig1 == 2) // если КЗ на линии ПТС {OCR1A = 0x00;} // то вырубаем линию else { if ((PINC.0 == 1)&&(PIND.3 == 1)&&(PINB.4 == 1)&&(t2 == 0)) { // если включено нар.освещ., противотуманный свет if (OCR1A < 0xFF) // и зажигание, то плавно его (3 сек.) зажигаем { OCR1A++; t2 = 73; } } else // если нет { if (crash == 1) // если КЗ на линии БС { OCR1A = 0x00FF; // то врубаем ПТС } else { if ((OCR1A > 0x00)&&(t2 == 0)) { OCR1A--; t2 = 73; // то также плавно гасим } } } }
//****************************** ЗВУКОВАЯ ИНДИКАЦИЯ РЕЖИМОВ РАБОТЫ ************************ //******************************************************************************************
if ((mig1 == 0)&&(mig2 == 0)&&(mig3 == 0)) { if ((go == 0)&&(beep2 == 1)) // если выключен режим ДХО { // подаём два коротких сигнала (бипа) i = 4; beep2 = 0; } beeper(); // если система в норме if ((go == 1)&&(beep2 == 0)) // и включен режим ДХО { // подаём один короткий сигнал (бип) i = 2; beep2 = 1; } beeper(); } else // если имеется неисправность { if (beep1 == 0) { // подаём 6 коротких сигналов (бипов) i = 12; // если i равен 2, то один бип, i=4 - два бипа и т.д. beep1 = 1; } beeper(); }
// зажигание габариты if ((PIND.3 == 0)&&(PINB.5 == 1)) {} // надо сделать чтобы пикало каждые 5 сек.
Пробуй в реале. Вроде бы косяков нет. Может Протеус балуется. Внешний инт должен асинхронно будить с любым тактовым генератором. Не пойдет - тогда будем ум морщить.
Добавлено (03.03.2017, 10:45) --------------------------------------------- msmmmm, попробовал, в реале тоже работать не хочет, значит в чём то накосячил
Добавлено (03.03.2017, 13:41) --------------------------------------------- msmmmm, попробовал отработать эту проблему, сделал минимально возможную программу и вот что получилось: работает только если внешнее прерывание настроено на срабатывание по низкому уровню, остальные три режима не функционируют (изначально у меня стоял режим "по переднему фронту").
while (1) { if (PIND.3 == 1) { PORTC.2 = 1; // зажигаем светодиод индикации нормальной работы системы } else { PORTC.2 = 0; MCUCR=0xA0; #asm("SLEEP") MCUCR=0x00;
}
} }
Добавлено (03.03.2017, 13:47) --------------------------------------------- проблема в том, что при включении зажигания будет подаваться плюс на вход МК, и если использовать INT0 Mode: Low level, то придётся сигнал инвертировать, а плата уже готова и на это не рассчитана
Тёмыч, собирался еще утром написать, но только сейчас до компа добрался - работа. В режиме Power-down МК отключен почти полностью, в т.ч. и его тактовый генератор, а прерывания по изменению уровня синхронизируются именно с ним. В даташите указано, что выход из режима Power-down возможен только прерывания по низкому уровню, но это не совсем так, по крайней мере из моего опыта. Просыпается МК и по остальным типам прерываний int, но само прерывание не обрабатывается. Происходит это потому, что выход из глубокого сна длителен и подобен сбросу, только программный счетчик не изменяется. Изменился уровень, пошла команда на включение МК, завелся генератор, выдержалось время стабилизации генератора и лишь затем такты пошли на АЛУ. Все это время даже флаг не может измениться - отсутствует тактовая частота. После просыпания МК не видит, что было прерывание (прерывание реагирует на изменения уровня, а оно уже произошло) и не обрабатывает его, а выполняет дальше программу. А вот при прерывании по низкому уровню все происходит точно так же, но проснувшийся МК реагирует просто на низкий уровень на входе и все работает по даташиту. Выход из ситуации: 1. Использовать Idle. Кушать будет больше. 2. Попробовать использовать прерывание без прерывания . Написать программу так, чтобы проснувшийся МК продолжал работу без перехода в прерывание. Учесть длительность просыпания из режима Power-down.
Просыпается МК и по остальным типам прерываний int, но само прерывание не обрабатывается. Происходит это потому, что выход из глубокого сна длителен и подобен сбросу, только программный счетчик не изменяется. Изменился уровень, пошла команда на включение МК, завелся генератор, выдержалось время стабилизации генератора и лишь затем такты пошли на АЛУ. Все это время даже флаг не может измениться - отсутствует тактовая частота. После просыпания МК не видит, что было прерывание (прерывание реагирует на изменения уровня, а оно уже произошло) и не обрабатывает его, а выполняет дальше программу. А вот при прерывании по низкому уровню все происходит точно так же, но проснувшийся МК реагирует просто на низкий уровень на входе и все работает по даташиту.
это понял.
Цитатаmsmmmm ()
2. Попробовать использовать прерывание без прерывания . Написать программу так, чтобы проснувшийся МК продолжал работу без перехода в прерывание. Учесть длительность просыпания из режима Power-down.
msmmmm, каким образом это осуществить? если можно по подробней про это, и желательно с примером, а то мозгов пока на это не хватает...
Для начала определи стоит ли на твоем контроллере этим заниматься (я уже не помню над которым издевался), а именно: все оставь как было, а после команды слип установи какой-нибудь маркер (зажигание светодиода и вход в бесконечный цикл, выдача в СОМ какой-то информации и т.д.) и посмотри: просыпается контроллер от синхронного прерывания или нет. По даташиту - нет. Но вот нашел еще любителя нестандартных применений: Re: Atmega 8. Выход из режима power-down. Пн мар 31, 2014 12:32:38 Попробовал выводить контроллер из спящего режима по любому логическому изменению на INT1 - и все в порядке, выходит и работает. Шанс есть - это на меге8.
А чем Idle не угодил? Потребление смешное, а питание ключом зажигания снимается полностью.