Attiny13 режим powerdown и пробуждение по кнопке

Автор: | 21.12.2018

Потребовалось восстановить работоспособность детской игрушки. Функционал очень простой — по нажатию кнопки начинают играть светодиоды. Проходит несколько секунд и игрушка выключается. И так до следующего нажатия на кнопку. Выключателя нет — часовые батарейки-«таблетки» в количестве трех штук питают устройство непрерывно, а родной неизвестный китайский контроллер, залитый каплей компаунда, больше не работает.

Attiny13 режим глубокого сна, экономия питания, пробуждение по кнопке.

Как видите, очень просто реализовать функционал с помощью Attiny13 с возможностями PicoPower. Стал копать интернет, и нашел статью на сайте radiotech.kz, используя её, как референс, сделал своё решение.

#define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sleep.h>
const int shrt=75;
const int flash=40;

void onebyone(void)
{
	for (int times=0;times<=20; times++) // running one by one
	{
		PORTB|= (1 << PB0);
		_delay_ms(shrt);
		PORTB&= ~(1 << PB0);
		_delay_ms(flash);
		PORTB|= (1 << PB1);
		_delay_ms(shrt);
		PORTB&= ~(1 << PB1);
		_delay_ms(flash);
		PORTB|= (1 << PB2);
		_delay_ms(shrt);
		PORTB&= ~(1 << PB2);
		_delay_ms(flash);
		PORTB|= (1 << PB3);
		_delay_ms(shrt);
		PORTB&= ~(1 << PB3);
		_delay_ms(flash);
	}
}

int main(void)
{
	  DDRB=0b00001111;
	  PORTB=0b00010000;
	  
	  MCUCR=0x30;             // Sleep enable, mode: power-down
	  GIMSK=0x20;             // Pin Change Interrupt Enable
	  PCMSK=0b00010000;             // PCINT4 & PCINT3 set
	  asm("sei");
	  
	  while(1)
	  {
		  asm ("sleep");
	  }
}
ISR(PCINT0_vect)
{
	if ((PINB & 0x08)==0x00)
	{
		_delay_ms (50);
		if ((PINB & 0x08)==0x00)
		{		
			onebyone();
		}
	}		
}


Чтобы активировать режим Power-down достаточно биты SM[1:0] регистра MCUCR установить в 10 и разрешить спящий режим МК (бит SE регистра MCUCR в 1). Усыпляется МК командой asm («sleep»);
Остается только настроить прерывание по нажатию кнопок и написать его обработчик.

Лично мне было не удобно, что режимы работы портов указаны в оригинальной статье, как HEX-значения. Честно, я долго сидел и втыкал, что значит «DDRB=0x27; PORTB=0x18;», пока не догадался, что надо значения перевести в двоичный код, и получить очень наглядное значение для каждого бита, где 1 — включен, 0 — выключен. Например, 0x27=0b100111, а 0x18=0b11000.

У меня в проекте микроконтроллер после определения нажатой кнопки переходит к исполнению процедуры «onebyone» — светодиоды бегут друг за другом. Вместо этого можно сделать выполнять любую другую задачу.

Итак, закрепим полученные знания:

  • строка define F_CPU 1000000UL указывает частоту внутреннего таймера микроконтроллера.
  • Двойной if в обработчике прерывания отвечает за простой программный антидребезг контактов. Может, он и примитивный, но неверных срабатываний я пока не заметил. А то уже собирался ставить триггер Шмитта.
  • В основном цикле программы контроллер только и делает, что спит — «asm («sleep»);» — Не совсем наглядно, когда в коде на Си возникают вставки на ассемблере, но так, наверное, можно сэкономить много ценных байтов программной памяти.

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

Attiny13 режим powerdown и пробуждение по кнопке: 3 комментария

  1. Дмитрий

    Разве, после входа в обработчик прерывания ISR(PCINT0_vect) не следует его отрубать? Оно настроено на изменение состояния: отпустите кнопку и опять вывалитесь в него…

    1. tinyadmin Автор записи

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

      1. Дмитрий

        Отпуская, Вы скорее всего инициируете установку флага по PCINT0 и при выходе из обработчика, вновь влезаете в него, но т.к. кнопка отжата, то никаких действий в теле обработчика не выполняется и только теперь, выйдя вторично из него, вы попадаете в asm («sleep»);

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *