An article about how to make a simple electronic clock using a microcontroller over the weekend from scratch. Only the basis of the clock is shown, the number of software and hardware features is limited only by your imagination).

This article is a logical continuation of the article on microcontrollers, published on Habré on August 26 (http://habrahabr.ru/blogs/hardware/37764/). The main task I put on is not to give step-by-step instructions on which wiring to which to solder, but to arouse the interest of readers to the topic, motivating for independent study.
So, in order to create a watch, it is necessary to master 2 technologies - this is soldering and the creation of printed circuit boards using laser-iron technology.
Soldering article:
licrym.org/index.php/%D0%9F%D0%B0%D0%B9%D0%BA%D0%B0An article on laser-iron technology for making boards:
licrym.org/wiki/index.php?wakka=Texnologii/LazernoUtjuzhnajaTexnologijaIzgotovlenijaPlatIf there is no desire / ability to make a PCB, then you can do with a breadboard, it looks like this:

Holes are drilled in it with a pitch of 2.54 mm, a piece of a suitable size is cut off from it, parts are installed and soldered (a circle of copper foil around each hole) and then the necessary connections are made with wire segments. It looks unaesthetic (cobweb of wires), but it is unnecessary to poison the board.
')
In the most extreme case, you can replace the mock-up board with a thick cardboard with punctured holes, but then this improvised card cannot be bent or bent.
So, we need
tools : a soldering iron, side cutters, a multimeter (for debugging, although everything worked right away for me).
Details : attiny2313 microcontroller, pad for it, 2 buttons, 7805 stabilizer microcircuit, four 7-segment LED indicators, I have it SA15–11GWA (digit height 38 mm). Any indicator size, the main thing is that the segment current does not exceed 40 mA (see the datasheet for a specific indicator), 4 KT817B transistors, 16 MHz quartz, 2 22 pF capacitors, 220 nF capacitor, and a couple of resistors. Specific components do not make sense, because may have to use analogs + resistors are calculated.
Let's start with the details in the picture:

The microcontroller cost 41 rubles, the indicators at 52.8 rubles apiece. Total turns 252.2 rubles. The rest was extracted from the reserves, but in any case the budget would not exceed 300 rubles.
The board was drawn by hand in the Sprint Layout 4 program. Here is the etched board:

Photo clock in the collection. In the background is my power supply, which I described here:
Universal Power Supply
View of the clock in the twilight:

And now let's see how it works. Here is the scheme (wide, because the link):
licrym.org/habrahabr/small_clock_scheme.jpgWhen the power is turned on, the microcontroller starts. The microcontroller is clocked from quartz with a frequency of 16 MHz. In the microcontroller filled control program.
The microcontroller has a so-called timer inside, usually there are several of them (8 and 16 bit). The timer can be used differently, for counting external pulses, for generating a given frequency, for generating a PWM signal, etc. In this case, we will use it for timing. We will enable the timer to count pulses on the system bus (ie, 16 MHz of quartz), turn on the prescaler 256 and interrupt by coincidence with the number 625. Ie the timer will tick at 16 MHz / 256 = 62500 Hz, and call the interrupt as soon as the timer will count to 625, ie we will have an interruption every 1/100 sec. Each program interruption will increase the counter of hundredths of seconds by 1, reset the timer and return to the time display.
If the number of hundredths of a second reaches 100, then we increase by 1 the value of seconds, and by the value of hundredths of a second we reset. And so on, up to dozens of hours, which are reset on reaching 24 without increasing the next level. The watches are extremely simple, that is why they do not consider either the date, or the translation for winter / summer time, etc. These functions can be implemented in software, without changing the hardware, and therefore remain for the implementation of the willing.
Having dealt with the timer and interrupts, we get the value of the current time in global variables. Now let's do the output of these values. Since the number of microcontroller ports is limited, we will exploit the inertia of view. The cathodes of all 4 indicators are connected in parallel, and the anodes are switched separately, which allows us at any time to output any digit to any indicator. By quickly switching the port B, to which the cathodes are connected, and by quickly switching the anodes, we can create the appearance that all 4 digits work for us, although only one works at a time. In other words, if the current time is 12:51, then we display the number 1 on the first indicator, after a short period of time (I have 1 ms) we display the number 2 on the second indicator, after 1 ms we display 5 on 3 indicator, after 1 ms we display 1 on the 4th indicator and so on in a circle.
The buttons are polled after each display cycle (approximately 40 times per second), the pressing processing is equipped with an anti-bounce and a “latch” in the form of a flag, which makes it possible to count just pressing without being distracted by the hold.
Transistors are installed for commutation of anodes. The fact is that the current that one foot of the port can pass through itself is limited to 40 mA, and my indicator, if all 7 segments and points are turned on (the separate LED on the circuit is just a point) will be 160 mA.
The code that controls the clock:
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7 beta 5 Professional
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech srl
www.hpinfotech.com
Project : Simple AVR Clock
Version :
Date : 01.05.2008
Author : Spiritus Sancti
Company : licrym.org
Comments:
Chip type : ATtiny2313
Clock frequency : 16,000000 MHz
Memory model : Tiny
External SRAM size : 0
Data Stack size : 32
*****************************************************/
#include <tiny2313.h>
#include <delay.h>
#define digit_display_time 1
unsigned char milliseconds, seconds, ten_seconds, minutes, ten_minutes, hours, ten_hours;
bit button_pressed1, button_pressed2;
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void) // 100 ,
{ milliseconds++;
TCNT1H=0x00;
TCNT1L=0x00;
if (milliseconds >= 100 ) // . milliseconds .
{
milliseconds = 0;
seconds++;
};
if (seconds >= 10)
{
seconds = 0;
ten_seconds++;
};
if (ten_seconds >= 6)
{
ten_seconds = 0;
minutes++;
};
if (minutes >= 10)
{
minutes = 0;
ten_minutes++;
};
if (ten_minutes >= 6)
{
ten_minutes = 0;
hours++;
};
if (hours >= 10)
{
hours = 0;
ten_hours++;
};
if (ten_hours >= 2 && hours == 4)
{
ten_hours = 0;
hours=0;
};
}
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;
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=1 State6=1 State5=1 State4=1 State3=1 State2=1 State1=1 State0=1
PORTB=0xFF;
DDRB=0xFF;
// Port D initialization
// Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=In Func0=In
// State6=0 State5=0 State4=0 State3=0 State2=0 State1=P State0=P
PORTD=0x03;
DDRD=0x7C;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x04;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0x71;
OCR1BH=0x00;
OCR1BL=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x00;
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;
// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=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
if ((PIND & 1<<0) == 0 && button_pressed1 == 0) // 1
{
delay_ms(1);
hours++;
button_pressed1 = 1;
};
if ((PIND & 1<<0) == 1) button_pressed1=0; //
if ((PIND & 1<<1) == 0 && button_pressed2 == 0) // 2
{
delay_ms(1);
minutes++;
button_pressed2 = 1;
};
if (PIND & 1<<1) button_pressed2=0;
};
}
The program is written in CodeVisionAVR. The circuit is created in the PROTEUS program. By the way, there you can draw a virtual circuit of the device in the proteus and immediately launch it for a simulation, knowing whether it is working or not.
Needless to say in the article it is impossible to answer all the questions and tell about all the subtleties. In particular, those who decide to repeat the construction will need to make a programmer (in the simplest case, 4 wiring to the LPT port, unsolder the programming block on the board (connect the 10-pin connector to the MOSI, MISO, SCK, RESET and GND legs) and set the FUSE bits microcontroller that would switch the clock generator from the internal RC chain to external quartz. About all this can be found on sites like avr123.nm.ru)
It took me 1.25 days to create these watches from scratch (from the idea to etching the board, decoupling and writing code).
Original article:
licrym.org/index.php/%D0%9F%D1%80%D0%BE%D1%81%D1%82%D1%8B% D0%B5_%D1%87 81% D1% 8BFeatures that can be added with a little blood:
1) attach a speaker to one of the free legs and get an alarm clock
2) hang on one of the free legs of the relay and get a timer (for example, to automatically turn on the garland)
3) the microcontroller has a USART module so by picking up a microcircuit - a level converter (for example, MAX232 and a pair of capacitors), you can establish bi-directional communication with a computer via the COM port.
PS I created a DIY blog (http://habrahabr.ru/blogs/DIY/) and henceforth I will publish all articles from the category of "do it yourself" there.
PPS In order to avoid misunderstanding I explain. I personally made these watches, and initially I published on my portal licrym.org but decided to transfer to the best and most interesting articles from my portal to Habrahabr.