Озадачился недавно созданием небольшой платы сопряжения для автоматизированного управления шторами. Решил делать платку на ATTiny13 с питанием от 3-вольтовой батареи CR2032. Встал вопрос энергосбережения, вроде как тини много и не жрет, но повесил на МК две кнопки, два транзистора и 3-вольтовой батарейки хватило ровно на неделю.
Посмотрев даташит, понял что режимов энергосбережения не так уж и много: Idle Mode, Power-down Mode и ADC Noise Reduction Mode. Не буду тут описывать чем один от другого отличается, это можно прочитать в даташите, скажу лишь что самый экономичный из них это Power-down Mode.
Power-down — наиболее экономный режим, при котором микроконтроллеры серии Tiny фактически отключаются от энергопотребления. В этом состоянии происходит остановка тактового генератора, выключается вся периферия. Активным остается лишь модуль обработки прерываний от внешнего источника. При обнаружении прерывания микроконтроллер выходит из режима Power-down и переходит в рабочий режим, останавливается на 4 машинных цикла, выполняет подпрограмму обработки прерывания, после чего выполнение программы возобновляется с инструкции, следующей за командой SLEEP. Содержимое РОН, ОЗУ и РВВ при этом не изменяется. Следует помнить, что между наступлением события, приводящего к выходу микроконтроллера из режима Power-down, и началом работы микроконтроллера проходит некоторое время, в течение которого тактовый генератор микроконтроллера выходит на рабочий режим.
немного о прерываниях
Микроконтроллеры без использования прерываний практически ничего не стоят. Прерывание (interrupt) получило свое название из того факта, что при срабатывании прерывания по какому-нибудь событию нормальное выполнение программы прерывается, и выполняется особый код — код обработчика прерывания (interrupt handler). Прерывания можно рассматривать просто как подпрограммы, которые приостанавливают нормальный процесс выполнения программы до тех пор, пока код подпрограммы обработчика прерывания не будет завершен. После того, как обработчик прерывания завершит свою работу, ядро микроконтроллера вернется к исполнению основной программы точно в той точке, где она была прервана прерыванием. События прерывания обычно происходят от каких-то внешних асинхронных воздействий на микроконтроллер — например, переключение логического уровня на внешнем выводе порта, либо переполнение регистра таймера, что означает истечение заданного интервала времени, и т. д.
схема
Схема очень простая и не заслуживает описания, просто приведу ее здесь:
Программа
Чтобы активировать режим Power-down достаточно биты SM[1:0] регистра MCUCR установить в 10 и разрешить спящий режим МК (бит SE регистра MCUCR в 1). Усыпляется МК командой asm («sleep»);
Остается только настроить прерывание по нажатию кнопок и написать его обработчик. Далее привожу полный код:
#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define F_CPU 1000000UL char zakr=0x00; char otkr=0x00; int main(void) { DDRB=0x27; PORTB=0x18; MCUCR=0x30; // Sleep enable, mode: power-down GIMSK=0x20; // Pin Change Interrupt Enable PCMSK=0x18; // PCINT4 & PCINT3 set asm("sei"); while(1) { asm ("sleep"); } } ISR(PCINT0_vect) { if ((PINB & 0x08)==0x00) { _delay_ms (50); if ((PINB & 0x08)==0x00) { zakr=~zakr; otkr=0x00; PORTB|=(1<<0); // закрыть шторы while ((PINB & 0x08)==0x00) {} PORTB&=~(1<<0); if (zakr==0x00) { PORTB|=(1<<0); // стоп PORTB|=(1<<1); _delay_ms (200); PORTB&=~(1<<0); PORTB&=~(1<<1); } } } if ((PINB & 0x10)==0x00) { _delay_ms (50); if ((PINB & 0x10)==0x00) { otkr=~otkr; zakr=0x00; PORTB|=(1<<1); // открыть шторы while ((PINB & 0x10)==0x00) {} PORTB&=~(1<<1); if (otkr==0x00) { PORTB|=(1<<0); // стоп PORTB|=(1<<1); _delay_ms (200); PORTB&=~(1<<0); PORTB&=~(1<<1); } } } }
Прописан программный антидребезг контактов, флаги zakr и otkr используются для отлавливания повторного нажатия на кнопку (повторное нажатие останавливает мотор).
Разве, после входа в обработчик прерывания ISR(PCINT0_vect) не следует его отрубать? Оно настроено на изменение состояния и продолжает «следить» за линиями кнопок…
Нет, отрубать его не следует, потому что после усыпления микроконтроллера он не сможет выйти из режима энергосбережения.
Имелось ввиду, что отпустить кнопку — это тоже изменить состояние на ее линии, т.е. вызвать прерывание ISR(PCINT0_vect)
Отпуская кнопку, Вы скорее всего инициируете установку флага по PCINT0 и при выходе из обработчика, вновь влезаете в него, но т.к. кнопка отжата, то никаких действий в теле обработчика не выполняется и только теперь, выйдя вторично из обработчика, Вы попадаете в asm («sleep»);
1. Нафига в этой схеме нужен контроллер? Включать мосфет ключ кнопками через посредничество контроллера? В чем идея?
2. В power done режиме pcint прерывания не работают! Только int0 по низкому уровню!
3. Что за манера присваивать регистры шестнадцатиричными числами? Абсолютно не наглядно!
В Power-down режиме контроллер будится int0 по низкому уровню а так же pcint по любой ноге .
7.1.3 Power-down Mode
Only an External Reset, a Watchdog Reset, a Brown-out
Reset, an external level interrupt on INT0, or a pin change interrupt can wake up the MCU.
Реально, зачем в данной схеме микроконтроллер? Какую функцию он выполняет? Неужели без него автор не сумел справиться? Или есть какой-то тайный смысл везде и всюду совать микроконтроллеры?
Думаю, автор на пальцах разъяснил как это работает. Для начинающих достаточно наглядно и понятно.
Собственно и причину он так же указал.