slava68: (Default)
[personal profile] slava68
Для занятий со студентами набросал код программки, которая переключает состояние светодиода при коротком нажатии на кнопку и включает или выключает оба светодиода при длительном нажатии. Задание задумывалось для загрузки в ATTiny13a и написанная студентами программа не влезла туда по размеру. Я решил реализовать её сначала для ATmega328 (Arduino Nano), получилось более 1024 байт. Небольшая оптимизация алгоритма позволила получить 684 байта.

----------------------------------------------------------------
unsigned long old_time = 0;                    // переменная для измерения времени удержания кнопки
boolean Button = 1;                            // флаг состояния кнопки

void setup() {
  DDRD |= (3 << 3);                            // переключаем выводы PD3 и PD4 в режим "выход"
}

void loop() {

boolean butt =  PIND & (1 << 5);             // проверяем состояние кнопки
  if ((butt == 0) && (Button == 1)) {          // если кнопка нажата и до этого была не нажата
    Button = 0;                                // устанавливаем флаг нажатия кнопки
        old_time = millis();                   // фиксируем время нажатия кнопки
  }
  if ((butt != 0) && (Button == 0)) {          // если кнопка не нажата, а раньше была нажата, то
    old_time = millis() - old_time;            // вычисляем время, сколько была нажата кнопка
    if ((old_time >10) && (old_time < 300)) {  // если время нажатия было менее 300 миллисекунд, то
      butt = PIND & (1 << 3);                  // проверяем состояние светодиода на выводе PD3
      switch (butt) {
        case 0:                                // если PD3 выключен, то
          PORTD &= ~(1 << 4);                  // устанавливаем низкий уровень на выводе PD4
          PORTD |= (1 << 3);                   // устанавливаем высокий уровень на выводе PD3
          break;
        case 1:                                // если PD3 включен, то
          PORTD &= ~(1 << 3);                  // устанавливаем низкий уровень на выводе PD3
          PORTD |= (1 << 4);                   // устанавливаем высокий уровень на выводе PD4
          break;
      }
    }
    else if (old_time > 300) {                 // если время нажатия было более 300 миллисекунд, то
      butt = PIND & (3 << 3);                  // проверяем состояние PD3 и PD4, если
      switch (butt) {
        case 0:                                // оба выключены, то
          PORTD |= (3 << 3);                   // устанавливаем высокий уровень на выводе PD3,4
          break;
        case 1:                                // любой из них включен, то
          PORTD &= ~(3 << 3);                  // устанавливаем низкий уровень на выводе PD3,4
          break;
      }
    }
    Button = 1;                                // устанавливаем флаг ненажатой кнопки
 }
}
----------------------------------------------------------------


Это, в принципе, уже влезает в микроконтроллер ATTiny13a и можно было бы остановиться на достигнутом, но нет предела совершенству. Хочется "красивый" код. Если избавиться от void setup() и void loop(), то получается 464 байт, но .... перестаёт работать (функция millis() и delay() это "фишка" Arduino) :-(
Реализовывать их через таймеры не хочется на этом этапе, видимо придётся остановиться на первом варианте.
Как подключить стандартную библиотеку Arduino для реализации этих функций - я так и не нашёл :-(
----------------------------------------------------------------
unsigned long old_time = 0;                    // переменная для измерения времени удержания кнопки
boolean Button = 1;                            // флаг состояния кнопки

void setup() {
  DDRB |= (3 << 3);                            // переключаем выводы PB3 и PB4 в режим "выход"
}

void loop() {

boolean butt =  PINB & (1 << 2);             // проверяем состояние кнопки
  if ((butt == 0) && (Button == 1)) {          // если кнопка нажата и до этого была не нажата
    Button = 0;                                // устанавливаем флаг нажатия кнопки
        old_time = millis();                   // фиксируем время нажатия кнопки
  }
  if ((butt != 0) && (Button == 0)) {          // если кнопка не нажата, а раньше была нажата, то
    old_time = millis() - old_time;            // вычисляем время, сколько была нажата кнопка
    if ((old_time >10) && (old_time < 300)) {  // если время нажатия было менее 300 миллисекунд, то
      butt = PINB & (1 << 3);                  // проверяем состояние светодиода на выводе PB3
      switch (butt) {
        case 0:                                // если PB3 выключен, то
          PORTB &= ~(1 << 4);                  // устанавливаем низкий уровень на выводе PB4
          PORTB |= (1 << 3);                   // устанавливаем высокий уровень на выводе PB3
          break;
        case 1:                                // если PB3 включен, то
          PORTB &= ~(1 << 3);                  // устанавливаем низкий уровень на выводе PB3
          PORTB |= (1 << 4);                   // устанавливаем высокий уровень на выводе PB4
          break;
      }
    }
    else if (old_time > 300) {                 // если время нажатия было более 300 миллисекунд, то
      butt = PINB & (3 << 3);                  // проверяем состояние PB3 и PB4, если
      switch (butt) {
        case 0:                                // оба выключены, то
          PORTB |= (3 << 3);                   // устанавливаем высокий уровень на выводе PB3,4
          break;
        case 1:                                // любой из них включен, то
          PORTB &= ~(3 << 3);                  // устанавливаем низкий уровень на выводе PB3,4
          break;
      }
    }
    Button = 1;                                // устанавливаем флаг ненажатой кнопки
 }
}
----------------------------------------------------------------


При компиляции в Attiny13a получилось 486 байт. Загрузилось с 25-й попытки и почему заработало так и не понял. С повторяемостью этого эксперимента, возможно будут сложности. В качестве программатора использовалась сама же Arduno. Схема подключения и настройки здесь.
Фотки:

fullsize photo http://b6.icdn.ru/s/slava_68/2/42921082aMX.jpg ............... http://b6.icdn.ru/s/slava_68/3/42921083NVU.jpg

Profile

slava68: (Default)
slava68

February 2026

S M T W T F S
1234567
891011121314
15161718192021
22232425262728

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 13th, 2026 01:53 pm
Powered by Dreamwidth Studios