Construyendo un reloj. Necesito un poco de orientación

Muy bien, aprendí todos los fundamentos del AVR y ahora estoy pensando en construir un reloj como proyecto. Usaré el ATMega328P junto con el DS1307 RTC. La hora se mostrará en una pantalla LCD u OLED. Lo que quiero saber es cómo será la estructura general del programa general. Sé que habrá dos modos; uno para configurar la hora y otro en el que el reloj funciona normalmente. Necesito ayuda sobre cómo implementaré estos modos y dos cambiaré entre ellos usando botones externos. Sería genial si alguien pudiera arrojar luz sobre esto. Gracias.

Respuestas (2)

Cuando trabaje con modos y estados, le recomiendo encarecidamente que utilice bucles while.

Así que un comienzo sería algo como esto:

#define up_button 0
#define down_button 1
#define set_button 2
#define leave_set_button 3

main_loop(){

    read_RTC_clock();
    //Through spi or i2c or what have you

    write_RTC_clock_to_display(); 
    //To the LCD or OLED display

    read_button_states(); 
    //Update the input_port variable

    if(input_port&set_time_button){
        while(!input_port&leave_set_button){//"and" out the leave button
            //If you are in this loop, then you will stay in here
            //until the user chooses to leave.

            //so we better make it possible for the user to leave by
            //reading the inputs and updating the button status

            read_button_states(); 
            //Update the input_port variable

            switch(input_port){
                case up_button|down_button: 
                //up_button|down_button means that
                // I press both simultaneously
                increment_step = 60/increment_step;
                //if increment_step is 60, then it's now 1 second
                //if increment_step is 1, then it's now 60 seconds
                break;
                case up_button: time+=increment_step; break;                    
                case down_button: time-=increment_step; break;
            }

            //and why not show the LED or OLED what we're doing
            write_settings_to_display();
        }
        write_time_to_RTC_clock();//update the RTC with the time we set
    }
}

No escribiré más... pero... así empezaría el proyecto. También eliminaría los botones en el software. También me preguntaría cuántos botones realmente quiero, cuantos más botones, más fácil es de usar. Podría funcionar con solo 2 botones, pero luego necesita usar algo de tiempo, por lo que si mantiene presionado un botón durante 1 segundo, significa algo diferente que si solo lo toca durante 10 milisegundos.

¿Guía? Claro... no lo traigas a la escuela.

Con toda seriedad, si está utilizando el RTC, esto es bastante simple, ya que no tiene que preocuparse por mantener el tiempo. Mostrar el tiempo podría ser simplemente un bucle conveniente que consulta el RTC y luego actualiza la pantalla. Parece que su pantalla también está orientada a comandos en lugar de algo que necesitaría multiplexar explícitamente como un LED de 7 segmentos de 4 dígitos.

En términos de poner en hora el reloj, un enfoque sería considerar el concepto de una máquina de estados finitos .

Sin embargo, en el nivel más simple, podría tener una lógica que verifique si se presiona un solo botón de "ajuste". Si es así, entonces el tiempo avanza en una unidad de tiempo más rápida que la real y se muestra, se espera un retraso de un segundo y luego se repite el ciclo.

Ese retraso posterior tendrá el beneficio de marcar el ritmo para el usuario y de resolver el contact bounceproblema simplemente ignorando el botón por un momento después de cada vez que concluye que (aún) está presionado.

Un diseño más refinado podría ofrecer un botón rápido y otro lento. O podría crear un botón de aceleración en el que la demora comience siendo larga y se reduzca al mínimo cuanto más tiempo se mantenga presionado el botón.

En un extremo, podría proporcionar botones individuales hacia arriba y hacia abajo para las horas y los minutos, o incluso para cada dígito de cada uno.

O podría crear un esquema con más estado, en el que tenga un botón de selección de dígitos que cambie los dígitos que parpadean y un botón de incremento que incremente el dígito seleccionado.

Un proyecto más avanzado sería hacer todo esto con MCU y sus temporizadores en chip, sin el chip RTC. Potencialmente, incluso podría hacerlo desde el oscilador de baja velocidad que funciona con un cristal de reloj.

Esperaba 3 botones, ARRIBA, ABAJO y CONFIGURAR, que puede usar para configurar los segundos, los minutos, las horas, etc. La subrutina para configurar la hora se ejecutará una vez solo cuando el reloj esté encendido y luego el reloj funcionará normalmente hasta que se reinicie nuevamente para configurar la hora. Lo principal con lo que tendría que trabajar es cómo incrementar, disminuir el tiempo desde que el RTC se almacena en BCD y no en binario.
Algo como el recuento de botones y el requisito de BCD realmente debería ser explícito en su pregunta. No debería ser demasiado difícil hacer la suma e implementar la lógica de acarreo, solo piense en cómo lo haría manualmente . Comience sin el botón de abajo para que pueda diferir la preocupación por la resta, y establezca una regla implícita de que si se presionan tanto el botón de arriba como el de ajuste, uno "gana", ya que esto le permitirá considerar todo en el mismo ciclo de decisión/retraso con su implícito rebote