/*// Подключаем необходимые библиотеки
#include <TimerOne.h>
// Массив для быстрого отображения нужных цифр на семисегментнике
// Формат: abcdefg
const byte digits[] = {
/* B00111111, // 0
B00000110, // 1
B01011011, // 2
B01001111, // 3
B01100110, // 4
B01101101, // 5
B01111101, // 6
B00000111, // 7
B01111111, // 8
B01101111 // 9*/
/*B01000000, // 0
B01111001, // 1
B00100100, // 2
B00110000, // 3
B00011000, // 4
B00010010, // 5
B00000010, // 6
B01111000, // 7
B00000000, // 8
B00010000 // 9
};
// Пин-код для кнопок и светодиодов
const int btnStart = A2; // кнопка начала отсчета
const int btnStop = A3; // кнопка остановки отсчета
const int btnMode = A4; // кнопка переключения режима
const int ledIndicator = A5; // светодиод-индикатор режима
// Выводы семисегментников
const int unitsDisplay[] = {2, 3, 4, 5, 6, 7, 8}; // Единицы секунд
const int tensDisplay[] = {9, 10, 11, 12, 13, A0, A1}; // Десятки секунд
// Текущее время в секундах
int seconds = 0;
// Режим счета (true - прямой, false - обратный)
bool directMode = true;
// Признак начала отсчета
bool countStarted = false;
// Временные метки
unsigned long previousMillis = 0;
unsigned long interval = 1000; // Интервал обновления (1 секунда)
// Период обновления дисплея
void timerUpdate() {
Timer1.detachInterrupt(); // отключаем таймер, пока обновляем
// Получаем единицы и десятки секунд
int unitSec = seconds % 10;
int tenSec = seconds / 10;
// Обновляем оба семисегментника
for (int i = 0; i < 8; i++) {
digitalWrite(unitsDisplay[i],bitRead(digits[unitSec],i));
digitalWrite(tensDisplay[i], bitRead(digits[tenSec],i));
}
Timer1.attachInterrupt(timerUpdate); // вновь подключаем таймер
}
void setup() {
// Конфигурируем пины дисплеев
for (int i = 0; i < 8; i++) {
pinMode(unitsDisplay[i], OUTPUT);
pinMode(tensDisplay[i], OUTPUT);
}
// Настраиваем кнопки и светодиод
pinMode(btnStart,INPUT_PULLUP);
pinMode(btnStop, INPUT_PULLUP);
pinMode(btnMode, INPUT_PULLUP);
pinMode(ledIndicator, OUTPUT);
// Настраиваем внутренний таймер Arduino для периодического обновления дисплея
Timer1.initialize(interval);
Timer1.attachInterrupt(timerUpdate);
// Готовимся начать отсчет
countStarted = false;
seconds = 0;
directMode = true;
digitalWrite(ledIndicator,LOW); // светодиод погашен
}
void loop() {
// Обрабатываем события кнопок
if (digitalRead(btnStart) == HIGH) {
countStarted = true;
}
if (digitalRead(btnStop) == HIGH) {
countStarted = false;
}
if (digitalRead(btnMode) == HIGH) {
directMode = !directMode; // меняем режим счета
digitalWrite(ledIndicator, directMode ? LOW : HIGH); // индикация режима
}
// Обновляем время только если запущен отсчёт
if (countStarted) {
unsigned long currentMillis = millis();
if ((currentMillis - previousMillis) >= interval) {
previousMillis = currentMillis;
if (directMode) {
seconds++;
} else {
seconds--;
// Проверка конца обратного отсчета
if (seconds <= 0) {
countStarted = false;
seconds = 0;
}
}
}
}
}*/
/*#include <TimerOne.h>
// Константа для массива отображаемых цифр
const byte DIGITS[] = {
/*B00111111, // 0
B00000110, // 1
B01011011, // 2
B01001111, // 3
B01100110, // 4
B01101101, // 5
B01111101, // 6
B00000111, // 7
B01111111, // 8
B01101111 // 9
B01000000, // 0
B01111001, // 1
B00100100, // 2
B00110000, // 3
B00011000, // 4
B00010010, // 5
B00000010, // 6
B01111000, // 7
B00000000, // 8
B00010000 // 9
};
// Пины для первой кнопки (start), второй кнопки (stop) и третьей кнопки (mode)
const int BTN_START = A2;
const int BTN_STOP = A3;
const int BTN_MODE = A4;
// Пин для светодиода
const int LED_INDICATOR = A5;
// Пины для семисегментных дисплеев
const int SEC_DISPLAY[] = {2, 3, 4, 5, 6, 7, 8}; // Первый дисплей (секунды)
const int MSEC_DISPLAY[] = {9, 10, 11, 12, 13, A0, A1}; // Второй дисплей (сотни миллисекунд)
// Переменные для секунд и сотен миллисекунд
uint16_t totalSeconds = 0;
uint16_t hundredthsOfSeconds = 0;
// Переменные состояния
bool started = false;
bool direct_mode = true;
// Интервал времени (10 мс)
const unsigned long INTERVAL = 10;
unsigned long prev_millis = 0;
// Обработчик прерываний таймера
void timerISR() {
Timer1.detachInterrupt(); // отключаем прерывание, чтобы обновить дисплей
// Преобразуем общее время в отдельные составляющие
int sec = totalSeconds % 60;
int msec = hundredthsOfSeconds % 100;
// Отображаем первую цифру (секунды)
for (int i = 0; i < 8; i++) {
digitalWrite(SEC_DISPLAY[i], bitRead(DIGITS[sec], i));
}
// Отображаем вторую цифру (сотни миллисекунд)
for (int i = 0; i < 8; i++) {
digitalWrite(MSEC_DISPLAY[i], bitRead(DIGITS[msec], i));
}
Timer1.attachInterrupt(timerISR); // возобновляем прерывание
}
void setup() {
// Настраиваем пины для дисплеев
for (int i = 0; i < 8; i++) {
pinMode(SEC_DISPLAY[i], OUTPUT);
pinMode(MSEC_DISPLAY[i], OUTPUT);
}
// Настраиваем пины для кнопок
pinMode(BTN_START, INPUT);
pinMode(BTN_STOP, INPUT);
pinMode(BTN_MODE, INPUT);
// Настраиваем светодиод
pinMode(LED_INDICATOR, OUTPUT);
// Инициализируем аппаратный таймер для периодического обновления дисплея
Timer1.initialize(INTERVAL);
Timer1.attachInterrupt(timerISR);
// Начинаем с нуля
totalSeconds = 0;
hundredthsOfSeconds = 0;
started = false;
direct_mode = true;
digitalWrite(LED_INDICATOR, LOW); // Горящий светодиод означает обратный счет
}
void loop() {
// Обрабатываем событие запуска секундомера
if (digitalRead(BTN_START) == HIGH) {
started = true;
}
// Обрабатываем событие остановки секундомера
if (digitalRead(BTN_STOP) == HIGH) {
started = false;
}
// Обрабатываем событие переключения режима
if (digitalRead(BTN_MODE) == HIGH) {
direct_mode = !direct_mode;
digitalWrite(LED_INDICATOR, direct_mode ? LOW : HIGH); // Прямой счет - горит, обратный - погас
}
// Если запущено, обновляем значения времени
if (started) {
unsigned long currMillis = millis();
if ((currMillis - prev_millis) >= INTERVAL) {
prev_millis = currMillis;
if (direct_mode) {
hundredthsOfSeconds++; // Прямой счет
if (hundredthsOfSeconds >= 100) {
hundredthsOfSeconds = 0;
totalSeconds++;
}
} else {
hundredthsOfSeconds--; // Обратный счет
if (hundredthsOfSeconds < 0) {
hundredthsOfSeconds = 99;
totalSeconds--;
}
}
}
}
}*/
//Подключаем необходимые библиотеки
const int buttonStartPin = A2; // Кнопка пуска
const int buttonStopPin = A3; // Кнопка останова
const int buttonModePin = A4; // Кнопка выбора режима (фиксированная)
const int ledPin = A5; // Светодиод индикации режима
byte digits[10][7] = {
{0,0,0,0,0,0,1}, // 0
{1,0,0,1,1,1,1}, // 1
{0,0,1,0,0,1,0}, // 2
{0,0,0,0,1,1,0}, // 3
{1,0,0,1,1,0,0}, // 4
{0,1,0,0,1,0,0}, // 5
{0,1,0,0,0,0,0}, // 6
{0,0,0,1,1,1,1}, // 7
{0,0,0,0,0,0,0}, // 8
{0,0,0,0,1,0,0} // 9
};
int secondUnits = 0; // Единицы секунд
int tenSeconds = 0; // Десятки секунд
boolean running = false; // Флаг текущего состояния секундомера
boolean reverseCount = false; // Флаг обратного счёта
void setup() {
pinMode(buttonStartPin, INPUT_PULLUP);
pinMode(buttonStopPin, INPUT_PULLUP);
pinMode(buttonModePin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
for(int i = 2; i <= 8; i++) {
pinMode(i, OUTPUT);
}
}
void loop() {
checkButtons();
if(running) {
delay(1000); // Пауза 1 секунда
updateTime(); // Изменяем показания секундомера
}
showDigits(tenSeconds, secondUnits); // Показываем единицы и десятки секунд
}
void checkButtons() {
if(digitalRead(buttonStartPin) == HIGH) {
running = true;
}
if(digitalRead(buttonStopPin) == HIGH) {
running = false;
}
if(digitalRead(buttonModePin) == HIGH) {
reverseCount = true;
digitalWrite(ledPin, HIGH); // Горит светодиод, обозначающий обратный счёт
} else {
reverseCount = false;
digitalWrite(ledPin, LOW); // Гаснет светодиод
}
}
void updateTime() {
if(!reverseCount) { // Прямой счёт
secondUnits++; // Увеличиваем единицу секунд
if(secondUnits > 9) {
secondUnits = 0;
tenSeconds++; // Переходим к десяткам секунд
if(tenSeconds > 5) { // Ограничиваем счётчик до 59 секунд
tenSeconds = 0;
}
}
} else { // Обратный счёт
secondUnits--;
if(secondUnits < 0) {
secondUnits = 9;
tenSeconds--;
if(tenSeconds < 0) {
tenSeconds = 5;
}
}
}
}
void showDigits(byte tens, byte units) {
setSegments(digits[tens]); // Отобразить десятки секунд
delay(5); // Короткая задержка
setSegments(digits[units]); // Отобразить единицы секунд
}
void setSegments(byte segments[]) {
for(int i = 0; i < 7; i++) {
digitalWrite(i + 2, segments[i]);
}
}