Okay, I took someone else's code and started figuring out the second lab work on computer hardware. The laboratory work consists in realizing on the board the pin code input and saving it in the non-volatile memory of the board (EEPROM).

You can display the digit on a seven-segment indicator like this:

*Тыкни чтобы посмотреть картинку*

Where the 'get_digit_code' function puts into the tmp register the code corresponding to the digit display on the indicator.

These codes look something like this:

*Тыкни чтобы посмотреть картинку*

I wrote a simple program with the output of different numbers on indicators when they are periodically changed. Example of work:

*Тыкни чтобы посмотреть картинку*

The task is as follows: write a program to adjust the pincode. The setting starts from the rightmost indicator, pd0 increases the value, pd1 decreases it. If the button is pressed for more than two seconds, the value on the indicator starts to change once every 0.25s. Delays cannot be used, only timers and their overflow interrupts should be used. This makes sense, because during a delay the program freezes in an infinite loop, i.e. nothing useful can be done. The pincode must also be stored in EEPROM, i.e. in the non-volatile memory of the board.

Timer1 in my program is used to implement blinking of the adjustable indicator value at a frequency of 2Hz, that is 2 times per second. The TCCR1B register is needed for setting the predivider (101 corresponds to the predivider 1024).

Different predividers:

> 000 - timer is stopped
> 001 - the predivider is equal to 1, i.e. it is switched off. the timer counts clock impulses.
> 010 - the predelimiter is equal to 8, the clock frequency is divided by 8
> 011 - the predelimiter is equal to 64, the clock frequency is divided by 64
> 100 - the predelimiter is equal to 256, the clock frequency is divided by 256
> 101 - the predelimiter is 1024, the clock frequency is divided by 1024.

The frequency of the timer (by incriminating the value in the counting registers TCNT1H, TCNT1L) is equal to the frequency of the board divided by the predivider. The counting registers are needed to increment the value in them. Timer overflow is caused when they overflow. Initially I put the number 0xFF into the registers to make the overflow happen instantly.

*Тыкни чтобы посмотреть картинку*

By placing the number 101 in the TIMSK and TIFR registers, I tell the board that the mode of operation of timer0 and timer1 is by overflow.

Timer0 should turn on when the button is pressed and turn off when it is released. It differs from timer2 in that it is eight-bit. The TCCR0 register is needed for placing the predivider in it. And the start value is placed in TCNT0. There are no more low and high bytes here as in the registers for placing the start value in timer1.

*Тыкни чтобы посмотреть картинку*

The code executed when the timer overflows is written at the location of these labels:

*Тыкни чтобы посмотреть картинку*

For example, this is what my code looks like, called when the count registers overflow into timer1:

*Тыкни чтобы посмотреть картинку*

The value in init_tim1_05 is calculated in such a way that the next overflow occurs exactly after 0.5 seconds. (formula: .equ init_tim1_05 = 61629 because 65536-0.5*8000000/1024 = 61629, where 1024 is the selected predivider and 8000000 is the frequency of my board).

Next, about 500 lines of code were written to directly implement the functionality. But this did not require any special knowledge of the board device. Except for working with EEPROM and interrupts int0, int1, but I already wrote about it in the last post about programming for AVR.

Also, there is a perfect ru lang video on the topic of AVR timers: click