Загрузка данных


#define BUTTON A0

// Сегменты A B C D E F G DP
int pins[8] = {2, 3, 4, 5, 6, 7, 8, 9};

// Цифры для ИНВЕРТИРОВАННОГО индикатора
// 0 = сегмент включен, 1 = выключен
byte numbers[10] = {
  0xC0,  // 0
  0xF9,  // 1
  0xA4,  // 2
  0xB0,  // 3
  0x99,  // 4
  0x92,  // 5
  0x82,  // 6
  0xF8,  // 7
  0x80,  // 8
  0x90   // 9
};

// Разряды индикатора
int pinDigits[4] = {10, 11, 12, 13};

// Секундомер
int seconds = 0;
int minutes = 0;

unsigned long millis1 = 0;

// Режим:
// false = остановлен
// true  = работает
bool mode = false;

// Кнопка
bool curButton = LOW;
bool prevButton = LOW;


void setup() {

  pinMode(BUTTON, INPUT);

  // Сегменты
  for (int i = 0; i < 8; i++) {
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], HIGH);
  }

  // Разряды
  for (int i = 0; i < 4; i++) {
    pinMode(pinDigits[i], OUTPUT);
    digitalWrite(pinDigits[i], HIGH);
  }
}


void loop() {

  // -------------------------
  // КНОПКА
  // -------------------------

  curButton = debounce(prevButton);

  if (prevButton == LOW && curButton == HIGH) {

    mode = !mode;

    // Запуск
    if (mode) {
      millis1 = millis();
    }
  }

  prevButton = curButton;


  // -------------------------
  // СЕКУНДОМЕР
  // -------------------------

  if (mode) {

    unsigned long currentMillis = millis();

    if (currentMillis - millis1 >= 1000) {

      // Сохраняем остаток времени,
      // чтобы секундомер не накапливал ошибку
      millis1 += 1000;

      seconds++;

      // 60 секунд = 1 минута
      if (seconds >= 60) {

        seconds = 0;
        minutes++;

        // После 99:59 начинаем сначала
        if (minutes >= 100) {
          minutes = 0;
        }
      }
    }
  }


  // -------------------------
  // МУЛЬТИПЛЕКСИРОВАНИЕ
  // -------------------------

  for (int i = 0; i < 4; i++) {

    // Сначала выключаем все разряды
    for (int j = 0; j < 4; j++) {
      digitalWrite(pinDigits[j], HIGH);
    }


    int digitValue;


    // Получаем нужную цифру
    switch (i) {

      // Правая цифра секунд
      case 0:
        digitValue = seconds % 10;
        break;

      // Левая цифра секунд
      case 1:
        digitValue = seconds / 10;
        break;

      // Правая цифра минут
      case 2:
        digitValue = minutes % 10;
        break;

      // Левая цифра минут
      case 3:
        digitValue = minutes / 10;
        break;
    }


    showNumber(digitValue, i);


    // Включаем текущий разряд
    digitalWrite(pinDigits[i], LOW);

    delay(2);
  }
}


// -------------------------
// ВЫВОД ЦИФРЫ
// -------------------------

void showNumber(int num, int dig) {

  for (int i = 0; i < 8; i++) {

    bool segment = bitRead(numbers[num], i);

    digitalWrite(pins[i], segment);
  }


  // Точка между MM и SS
  // У нас DP = pins[7]
  //
  // Инвертированная логика:
  // LOW = включено

  if (dig == 2) {
    digitalWrite(pins[7], LOW);
  }
}


// -------------------------
// АНТИДРЕБЕЗГ КНОПКИ
// -------------------------

bool debounce(bool last) {

  bool current = digitalRead(BUTTON);

  if (last != current) {

    delay(5);

    current = digitalRead(BUTTON);
  }

  return current;
}