You really need to think through what each section and every single line of code is doing, or you will be spending most of your time trying to debug all sorts of problems unrelated to the simple timing issues.
A couple of points jumped out at me while glancing through your code:
The very first priority is to determine or set your CPU clock speed. The F_CPU parameter is nonfunctional in your original posting, because the #define is preceded by //. Without the correct F_CPU (which might be set elsewhere in your development system), the library _delay_ routines won’t work correctly. There are also strict limitations on the delays that can be produced by these routines, and that in turn depends on the clock speed.
The subroutine lcd_time as defined in your original post won’t work reliably. This is because the string has no terminating zero byte. The string display routine will cruise through memory, sending bytes to the LCD, looking for that zero. Unless you are extremely lucky, total garbage will appear on the display.
Accurate timing can’t be done in a main loop because you have no way of knowing what the overhead is in reading the timer and resetting it to zero. You certainly can’t make a clock this way. For accurate timing of a button press, you need to use interrupts for both the timer and the button press, which have their own (very small) overhead. The ringtone routine that I just posted contains an example of an interrupt-driven timer that accurately counts 8.192 ms intervals and another to produce arbitrary but accurate audio tones. It is easy to modify either routine to produce any desired clock tick, and this takes about 8 lines of code, total. There are examples of button press or pin change interrupts in this forum as well. One example would be the code that I posted to measure RPM’s.
It is always a great idea to study working code examples – any that you can find!
Good luck, Jim