Перейти к содержанию

Спящий режим МК AVR


Рекомендуемые сообщения

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

Подскажите пожалуйста, каким образом реализовать такой алгоритм работы МК:

Питание постоянно включено, однако контролер спит в режиме POWER_DOWN (максимальное энергосбережение).

Затем по нажатию кнопки контроллер просыпался бы и работал условно в "Первом режиме", после следующего нажатия переходил во "второй режим", затем в третий и после 4-го нажатия вновь засыпал в режим POWER_DOWN.

(По такому принципу работают множетсво фонариков)

Ещё следует учесть, что среда разработки Atmel Studio, язык C, МК- AtMega8.

Спасибо всем откликнувшимся!

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Непонятен вопрос, что значит "каким образом" ?
Что конкретно не получается ? Кнопку опросить или проц в слип загнать ? Поподробнее...
 

Ссылка на комментарий
Поделиться на другие сайты

28 минут назад, Alex сказал:

Поподробнее...

Не понятен механизм отправки в сон изначально. Как это сделать правильнее.

Как я себе это представляю: при инициализации МК сразу вводить в сон (понятно что предварительно проинициализировав режим сна) 

asm sleep;  //в спящий режим

Затем в прерывании отслеживать нажатие кнопки, а затем прогонять через SWITCH, чтобы выбирать режим. И при четвертом нажатии на кнопку опять отправлять в сон? В общем не понятен сам механизм... Типа того:

 

ISR(INT0_vect) //обработка прерывания, низкий уровень на INT0
{
    MODE++;
	IF (MODE>4) MODE = 1;
	void Change_Mode();
}

void Change_Mode() //функция смены режимов
{
	SWITCH (MODE)
	{
		case 1:
		{
		 Делаем что-то;
		}

		case 2:
		{
		 Делаем что-то;
		}

		case 3:
		{
		 Делаем что-то
		}

		case 4:
		{
		 asm sleep; \\все режимы прошли по кругу, тогда снова засыпаем до следующего прерывания
		}
	}
}

 

Изменено пользователем -=FISHER=-
Нашел ошибки

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Ну да, всё верно. По каждому внешнему прерыванию, меняем режим. На последнем режиме загоняем обратно в сон.
Change_Mode() вызываем как сменилась переменная MODE, или, если код будет не громозкий, то вызываем прямо из прерывания.
 

Не забудьте ещё от дребезга избавиться.
 

Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

18 минут назад, Alex сказал:

Ну да, всё верно. 

Не забудьте ещё от дребезга избавиться.
 

Спасибо! Буду пробовать! :)

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

В структуре switch() не забывайте break'и ставить.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Вообще-то не очень логичный подход. Если у нас есть состояния, то логично использовать машину состояний - 4 процедуры, которые реализуют каждый из режимов, запускаются процедуры поочерёдно, выход из процедуры - нажатие кнопки(без прерываний!) а на порт кнопки просто настроить на срабатывание прерывания по изменению уровня, без обработчика(сразу выход).

В 4-й процедуре - задержка 100...500мс и команда входа в спящий режим. можно даже зациклить вход в сон внутри и не выходить из процедуры пока кнопка не будет нажата дольше 100мс - для защиты от статических и импульсных помех.

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

Вариант с SWITCH годится только если функция каждого из режимов не более 1-2 строчек кода.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

10 часов назад, Alexeyslav сказал:

Вообще-то не очень логичный подход. Если у нас есть состояния, то логично использовать машину состояний - 4 процедуры, которые реализуют каждый из режимов, запускаются процедуры поочерёдно, выход из процедуры - нажатие кнопки

Добрый день! А могли бы Вы снабдить эти мылси небольшим программным скелетом такого подхода? Ну без внешнего прервывания на INT0 здесь не обойтись всё равно, так как больше ничего не разбуит МК из режима сна POWER_DOWN. 

Если исключить SWITCH, то должно выглядеть примерно так?

ISR(INT0_vect) //обработка прерывания, низкий уровень на INT0
{
    MODE++;
	IF (MODE>4) MODE = 1;
	if (MODE==1) MODE_1();
	if (MODE==2) MODE_2();
	if (MODE==3) MODE_3();
	if (MODE==4) GO_TO_SLEEP();
}

void MODE_1() //функция первого режима
{
	//делаем что-то
}

void MODE_2() //функция второго режима
{
	//делаем что-то
}

void MODE_3() //функция третьего режима
{
	//делаем что-то
}

void GO_TO_SLEEP() //функция "засыпания"
{
	sleep_cpu(); //отправляем МК в сон
}

 

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Нет, так делать ни в коем случае нельзя! Уход в сон идет в прерывании, так что контроллер никогда не проснется.
 

ISR(INT0_vect){}//заглушка для прерывания

...

char oldkey, key;

while(1){

  key = PINx & (1<<y); //считываем только бит, соответствующий кнопке

  if( key != oldkey ){ //если этот бит изменился то кнопка либо нажата, либо отпущена

    oldkey = key;

    if( key )mode++; if(mode > 4)mode=0; //если кнопка отпущена (лог. уровень на пине изменился с 1 до 0 ) меняем режим.

  }

  switch(mode){

    case 0: mode0_func(); break;

    case 1: mode1_func(); break;

    case 2: mode2_func(); break;

    case 3:

      GIMSK |= (1<<INT0); //разрешаем прерывание по низкому уровню - никакой другой не удовлетворяет условию

      sleep(); //уходим в сон

      GIMSK &=~(1<<INT0); //запрещаем прерывание чтобы не мешало. Можно это сделать в самом прерывании, но это его серьезно замедлит

      break;

  }

  _delay_ms(100); //задержка 100 мс против дребезга контактов

}

 

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

54 минуты назад, COKPOWEHEU сказал:

Нет, так делать ни в коем случае нельзя! 

Принципиальное отличие от моего первого варианта в том, что SWITCH находится не в прерывании, а в основном бесконечном цикле. Ведь так? А от прерывания нам в принципе только лишь и нужно, чтобы контролер ожил. Всё ясно. Спасибо!

Изменено пользователем -=FISHER=-
Нашел опечатку

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Прерывание настроить, обработчик оставить пустым - немедленный возврат.

SWITH в данном случае вообще не нужен, просто последовательное выполнение процедур.

т.е.
 

mode3_func(); // состояние сна, первое состояние по сбросу контроллера

while(1){

mode0_func();

mode1_func();

mode2_func();

mode3_func();

}

А уже внутри каждой функции ждём отпускания кнопки, выполняем в цикле основную нагрузку состояния, и по нажатию кнопки - выходим.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Это уже зависит от процедур и от того надо ли делать что-то одновременно с ними. Вариант со switch'ом несколько более гибкий, нет дублирования обработки кнопки.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Обработку кнопки можно вынести в отдельную процедуру и не будет никакого дублирования кода.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

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

В случае же конечного автомата все активные части кода максимально локализованы, действие происходит внутри одной процедуры и не зависит от внешнего кода, а значит разрабатывать их можно независимо и максимально удобно тестировать(отлаживать) поскольку код не имеет внешних зависимостей(глобальных переменных).

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

  • 2 недели спустя...
В 9/9/2016 в 12:58, COKPOWEHEU сказал:

Нет, так делать ни в коем случае нельзя! Уход в сон идет в прерывании, так что контроллер никогда не проснется.
 


ISR(INT0_vect){}//заглушка для прерывания

...

    case 3:

      GIMSK |= (1<<INT0); //разрешаем прерывание по низкому уровню - никакой другой не удовлетворяет условию

      sleep(); //уходим в сон

      GIMSK &=~(1<<INT0); //запрещаем прерывание чтобы не мешало. Можно это сделать в самом прерывании, но это его серьезно замедлит

      break;

  }

  _delay_ms(100); //задержка 100 мс против дребезга контактов

}

Добрый день! А подскажите тогда пожалуйста, как же контроллер проснется, если вы запретили прерывания в последнем case?

 

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Так я его запретил уже после того как контроллер проснется.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

А вообще получится сделать так что та самая кнопка, которая меняет режимы, будет висеть как раз на ножке INT0? Для того, чтобы управление фонарем происходило исключительно с одной кнопки?

То есть подключил батарейку: МК спит, ничего не светится, нажал на кнопку первый раз: МК проснулся, фонарь начал светиться, нажал второй раз: начал светиться по другому.......нажал n-ый раз, всё погасло, МК уснул. Нажал следующий раз, МК проснулся, и фонарь светит в первом режиме.

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

А чем это отличается от первоначальной задачи? В моем коде кнопка может висеть только на прерывании, иначе контроллер не проснется.

В порядке извращения можно повесить на другую переферию, UART, SPI, главное чтобы эта переферия могла вывести контроллер из выбранного режима сна.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

7 минут назад, COKPOWEHEU сказал:

Так я его запретил уже после того как контроллер проснется.

Не понял. Вот написано:

    sleep();

	GIMSK &=~(1<<INT0); //запрещаем прерывание чтобы не мешало. Можно это сделать в самом прерывании, но это его серьезно замедлит

    break;

Уходим в сон, а следующая команда запрещает сразу же прерывания. Или не так это работает?

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

А сколько тактов выполняется команда sleep?

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

7 минут назад, COKPOWEHEU сказал:

А сколько тактов?

Если бы я знал... То есть мы отправили контролер спать, но  пока он уснет цикл WHILE ещё несколько раз успеет прокрутиться?

 

Простоя сейчас отправляю МК спать из процедуры обработки нажатия кнопки и судя по всему он у меня засыпает и сразу же просыпается. Я так понимаю что это потому что кнопка висит на ножке прерывания.

Изменено пользователем -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Команда sleep "выполняется" пока не проснется контроллер. После этого идет прерывание от которого он проснулся и в самом конце возвращение к следующей за sleep командой. Насколько я помню, так. Не очень уверен, может после пробуждения контроллер выполняет одну следующую команду, тогда добавьте пару nop'ов после sleep'а.

Прерывание точно настроено правильно? Должно быть по низкому уровню. Еще можно 100мс задержку переместить перед case'ом.

Покажите весь код.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

22 минуты назад, COKPOWEHEU сказал:

Покажите весь код.

#define F_CPU 1000000UL

#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include <avr/sleep.h>

#define WAIT 10

// Declare your global variables here

unsigned char trig, trig1, br1, br2, i, sw=0, sw1, count=0, count1=0, SLEEP_MODE, FRONT_LAMP_MODE=0, STROB_MODE=0, STOP_MODE=0, PREV_STOP_MODE, FLASH_TIME_REAR=50, 

FLASH_TIME_FRONT=50;
unsigned int adc_value;
float acb_value;

void sleep_init (void)
{
	MCUCR |= (1<<SM1) //выбираем режим сна POWER_DOWN
	|(1<<SE); //разрешаем спящий режим
}

void int_init (void) //разрешаем прерывания
 {
 	GICR |= (1<<INT0);
}

void counter_init (void)
{
	TCCR0 = (1<<CS02); //устанавливаем делитесь Timer0 на 256
	SREG = 0x80;
	TIMSK = (1<<TOIE0);
	TCNT0 = 0xD2;
}

void PWM_timer_init (void) //функция инициализации ШИМ
{
	ASSR=0x00;
	TCCR1A |= (1<<COM1A1) | (1<<WGM10);
	TCCR1B |= (1<<WGM12) | (1<<CS11) | (1<<CS10);
	OCR1A=128; // изначально яркость устанавливается 50%
}

void port_init (void) //функция инициализации портов
{
	DDRB = 0x7;
	PORTB = 0x00;
	
	DDRD = 0x00;
	PORTD = 0x1;
	
	DDRC = 0x3C;
	PORTC = 0x00;
}

ISR (TIMER0_OVF_vect)
{
	TCNT0 = 0xD2;
	
	count++;
	if (count>FLASH_TIME_REAR)
	{
		if (sw==0)
		{
			sw=1;
		}
		else
		{
			sw=0;
		}
		count=0;
	}
	
	count1++;	
	if (count1>FLASH_TIME_FRONT)
	{
		if (sw1==0)
		{
			sw1=1;
		}
		else
		{
			sw1=0;
		}
		count1=0;
	}	
}

ISR (INT0_vect)  //заглушка прерывания
{

}

int main(void)
{
	// Declare your local variables here

	sei(); //глобально разрешаем прерывания
	counter_init(); //инициализируем счетчик	
	port_init(); //инициализируем порты
	PWM_timer_init(); //инициализируем ШИМ
	int_init(); //инициализируем прерырвания
	sleep_init(); //инициализируем режим сна
	sleep_cpu(); //засыпаем

	while (1)

	{

//************************************************ВЫБОР РЕЖИМА СТРОБОСКОПА ПЕРЕДНЕГО ФОНАРЯ**************************************
 		switch (STROB_MODE)
		{
			case 1:
			{
				if (sw1==0)
				{
					OCR1A=255;
				}
				else
				{
					OCR1A=0;
				}
				break;
			}
			break;
		}

//**************************************ВЫБОР РЕЖИМА ИНДИКАЦИИ ЗАДНИХ СТОП-СИГНАЛОВ*****************************************		
		switch (STOP_MODE)
		{
			case 0: 
			{
				if (sw==0)
				{
					PORTB = 0b00000101;
				}
				else
				{
					PORTB = 0x00;
				}
				break;
			}
			case 1:
			{
				if (sw==0)
				{
					PORTB = 0b00000001;
				}
				else
				{
					PORTB = 0b00000100;
				}
				break;				
			}
			
			break;
			
		}

/*************************************ОБРАБОТКА НАЖАТИЯ ЕДИНСТВЕННОЙ КНОПКИ**************************************************/

		if (!(PIND&0x4)) //обработка нажатия основной кнопки
		{
			if (trig==0) //если кнопка нажата в первый раз
			{
				FRONT_LAMP_MODE++; //увеличиваем значение переменной режима
			
				switch(FRONT_LAMP_MODE) //выбор режима переднего фонаря
				{
					case 1: //первый режим, "БЛИЖНИЙ СВЕТ"
					{
						OCR1A=128;
						break;
					}
				
					case 2: //второй режим, плавный розжиг в режим "ДАЛЬНИЙ СВЕТ"
					{
						for (i=128;i<255; i++)
						{
							OCR1A++;
							_delay_ms(3);
						}
						break;
					}
				
					case 3: //третий режим, "СТРОБОСКОП"
					{
						STROB_MODE=1;
						break;
					}
					
					case 4: //четвертый режим, "РЕЖИМ СНА"
					{
						PORTB=0x00; //выключаем все светодиоды
						STROB_MODE=0; //отключаем режим стробоскопа
						OCR1A=128; //переводим яркость переднего фонаря в режим "БЛИЖНИЙ СВЕТ"
						FRONT_LAMP_MODE=0; //устанавливаем нулевой режим
						sleep_cpu(); //отправляем МК в СОН
						break;
					}
				break;
			}
			trig=1; //включаем триггер-защелку
			}
		}
		else //если кнопка отпущена
		{
			if(trig) //если кнопка была нажата
			{
				trig++;
				if(trig>WAIT)trig=0; //ждем определенное время и отключаем триггер защелку
			}
		}

		
/*********************************НАЖАТИЕ НА ПЕРЕДНИЙ ИЛИ НА ЗАДНИЙ ТОРМОЗ**************************************************/
		
		if ((!(PIND&0x80)) || (!(PIND&0x40)))  
		{
			if (br1==0)
			{
				PREV_STOP_MODE = STOP_MODE;
				STOP_MODE=1;
				FLASH_TIME_REAR=20;
			}
			br1=1;
		}
		else
		{
			if(br1)
			{
				br1++;
				if(br1>WAIT) {br1=0; STOP_MODE=PREV_STOP_MODE; FLASH_TIME_REAR=50;}
			}
		}
		
/****************************НАЖАТИЕ НА ОБА ТОРМОЗА ОДНОВРЕМЕННО**********************************************************/

		if ((!(PIND&0x80)) && (!(PIND&0x40)))
		{
			if (br2==0)
			{
				PREV_STOP_MODE = STOP_MODE;
				STOP_MODE=1;
				FLASH_TIME_REAR=10;
			}
			br2=1;
		}
		else
		{
			if(br2)
			{
				br2++;
				if(br2>WAIT) {br2=0; STOP_MODE=PREV_STOP_MODE; FLASH_TIME_REAR=20;}
			}
		}

/***********************************ОБА ТОРМОЗА ОТПУЩЕНЫ**************************************************************/		
		
		if ((PIND&0x80) && (PIND&0x40)) {STOP_MODE=0; FLASH_TIME_REAR=50;}
			

	}
}

 

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Ну вы и траву развели. Тут вообще не нужен обработчик прерывания. Всё что нам нужно от прерывания - это разбудить контроллер, а обработчик пусть будет пустым.
Сразу после выхода из сна убеждаемся что кнопка ТОЧНО нажата а не была короткая помеха, иначе снова уходим в сон(цикл постоянного входа в сон, пока не будет установлен факт нажатия кнопки). Прерывания запрещать не нужно - они не мешают.
А дальше, выполняем все необходимые действия по факту нажатия кнопки - последовательно вызываем все режимы в порядке очереди, выход из каждого режима - факт нажатия и ОТПУСКАНИЯ кнопки.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

8 часов назад, Alexeyslav сказал:

Ну вы и траву развели. Тут вообще не нужен обработчик прерывания. Всё что нам нужно от прерывания - это разбудить контроллер, а обработчик пусть будет пустым.

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

ISR (INT0_vect)  //заглушка прерывания
{

}

 

8 часов назад, Alexeyslav сказал:

Сразу после выхода из сна убеждаемся что кнопка ТОЧНО нажата а не была короткая помеха, иначе снова уходим в сон(цикл постоянного входа в сон, пока не будет установлен фак

Согласен, этого у меня пока нет, потому что проблема пока в другом. А именно если усыплять контроллер из обработчика нажатия кнопки:

/*************************************ОБРАБОТКА НАЖАТИЯ ЕДИНСТВЕННОЙ КНОПКИ**************************************************/

		if (!(PIND&0x4)) //обработка нажатия основной кнопки
		{
			if (trig==0) //если кнопка нажата в первый раз
			{
				FRONT_LAMP_MODE++; //увеличиваем значение переменной режима
			
				switch(FRONT_LAMP_MODE) //выбор режима переднего фонаря
				{
					case 1: //первый режим, "БЛИЖНИЙ СВЕТ"
					{
						//делаем что-то
					}
				
					case 2: //второй режим, плавный розжиг в режим "ДАЛЬНИЙ СВЕТ"
					{
						//делаем что-то
					}
				
					case 3: //третий режим, "СТРОБОСКОП"
					{
						//делаем что-то
					}
					
					case 4: //четвертый режим, "РЕЖИМ СНА"
					{
						sleep_cpu(); //ОТПРАВЛЯЕМ МК В СОН
						break;
					}
				break;
			}
			trig=1; //включаем триггер-защелку
			}
		}
		else //если кнопка отпущена
		{
			if(trig) //если кнопка была нажата
			{
				trig++;
				if(trig>WAIT)trig=0; //ждем определенное время и отключаем триггер защелку
			}
		}

То как я наблюдаю в Протеусе, процедура отправки МК в сон, протекает параллельно с событием внешнего прерывания, то есть пока выполняется команда sleep_cpu(); успевает прийти внешнее прерывание и где-то на полпути БУДИТ контроллер. А происходит так, я полагаю, потому что кнопка висит на той же ножке, на которой разрешены внешние прерывания INT0 она же PD2. Это заметно, потому что после нажатия кнопки, МК, пусть и криво, но продолжает реагировать на нажатия кнопок. Когда же у меня кнопка висела на PB7, а для прерывания я сделал дополнительную кнопку на PD2 всё работало как надо.

 

Подскажите пожалуйста, как выйти из этой ситуации или это ехнически невозможно?

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...