Даже наверное не просто простые, а супер простые. Данный проект на
микроконтроллере можно назвать проектом выходного дня, так как на
разработку и создание этих часов с нуля ушло 1,25 дня, а учитывая, что
у вас будет под рукой готовый код, то вы управитесь быстрее.
Нам
понадобятся: Кварцевый резонатор на 16 МГц, микроконтроллер ATTINY2313,
2 кнопки, 2 конденсатора на 22 пф, конденсатор на 220 нф, линейный
стабилизатор питания 7805, 4 транзистора КТ817Б, ну и четыре
семисегментных светодиодных индикатора, у меня это SA15–11GWA (высота
цифр 38 мм) и горстка резисторов. Приведенный список соответствует той
конструкции, что на фотографиях. Вы можете использовать иные
комплектующие (более крупные индикаторы, другой микроконтроллер и
т.д.), и тогда придется пересчитать некоторые сопротивления. В общем
простор для творчества большой. Отечественные транзисторы пришлось
использовать, поскольку под рукой ничего другого не было, если бы была
возможность выбирать, то я бы поставил полевые транзисторы.
Итак, имеющиеся компоненты:
Микроконтроллер
обошелся в 41 руб, индикаторы по 52,8 руб за штуку. Всего получается
252,2 руб. Остальное было извлечено из запасов, но в любом случае
бюджет бы не превысил бы 300 рублей.
Микроконтроллер
тактируется кварцем с частотой 16 МГц. В качестве счетчика времени,
внутри микроконтроллера запущен 16 битный таймер с предделителем 256
(т.е. частота отсчетов таймера 62500 Гц), настроенный на создание
прерывания по достижении счетчиком значения 625. Таким образом, мы
получаем прерывания ровно 100 раз в секунду. Значение времени хранится
в глобальных переменных, и каждое прерывание мы увеличиваем значение
миллисекунд на 1. Если количество миллисекунд достигает 100, то мы
увеличиваем на 1 значение секунд, а значением миллисекунд сбрасываем. И
так далее вплоть до десятков часов, которые сбрасываются по достижении
24 без увеличения следующего разряда. Часы предельно простые, поэтому
не считают ни дату, ни перевод на зимнее/летнее время и т.д. Данные
функции можно реализовать программно, без изменения аппаратной части,
поэтому остаются для реализации желающим.
Разобравшись с
таймером и прерываниями мы получаем значение текущего времени в
глобальных переменных. Теперь займемся выводом этих значений. Так как
количество портов микроконтроллера ограничено, то будем эксплуатировать
инерционность зрения. Катоды всех 4 индикаторов соединены параллельно,
а аноды коммутируются отдельно, что позволяет нам в любой момент
времени вывести любую цифру на любой индикатор. Быстро переключая порт
B, к которому подключены катоды и быстро переключая аноды мы можем
создать видимость, что у нас работают все 4 цифры, хотя единовременно
работает только одна. Иными словами, если текущее время 12:51, то мы
выводим цифру 1 на первый индикатор, спустя малый промежуток времени (у
меня 1 мс) выводим цифру 2 на второй индикатор, спустя 1 мс выводим 5
на 3 индикатор, спустя 1 мс выводим 1 на 4 индикатор и так далее по
кругу.
Кнопки опрашиваются после каждого цикла отображения
(примерно 40 раз в сек), обработка нажатия снабжена антидребезгом и
«защелкой» в виде флага, что позволяет считать именно нажатия не
отвлекаясь на удержание.
// Timer 1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) //Прерывание происходит 100 раз в сек, сохраняем в глобальные переменные текущее время { milliseconds++; TCNT1H=0x00; TCNT1L=0x00;
void main(void) { unsigned char digits[10] = {18, 159, 56, 28, 149, 84, 80, 31, 16, 20}; //массив для генерации цифр. Какой элемент массива будет отправлен в порт, такая цифра и загорится.
// Crystal Oscillator division factor: 1
CLKPR=0x80; CLKPR=0x00;
// Input/Output Ports initialization // Port A initialization // Func2=In Func1=In Func0=In // State2=T State1=T State0=T PORTA=0x00; DDRA=0x00;
// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80;
// Global enable interrupts #asm("sei")
while (1) { PORTD |=1<<5; //включаем первый индикатор PORTB = digits[ten_hours]; //выводим на него десятки часов delay_ms(digit_display_time); //ждем, время индикации одного разряда задается в заголовке программы PORTD &=~(1<<5); //выключаем первый индикатор и переходим дальше и так в цикле для каждого из 4 разрядов PORTD |=1<<4; PORTB = digits[hours]; if (milliseconds >= 50) PORTB &=~(1<<4); else PORTB|=1<<4; //моргание точки delay_ms(digit_display_time); PORTD &=~(1<<4); PORTD |=1<<3; PORTB = digits[ten_minutes]; delay_ms(digit_display_time); PORTD &=~(1<<3); PORTD |=1<<6; PORTB = digits[minutes]; delay_ms(digit_display_time); PORTD &=~(1<<6);
//а вот теперь проверим кнопочки в стиле часов Электроника 13
Вы можете поддержать сайт напрямую через наши платежные реквизиты
WebMoney Z355095169785 R218396818010 E144063919939 Все средства полученные от пользователей сайта будут использованы исключительно для поддержки и дальнейшего развития сайта.