Interfaz de un solo botón para el reloj de pulsera AVR

0

Entonces, quiero hacer un reloj de pulsera y decidí usar un Atemga32. Estoy usando el temporizador / contador2 con un reloj externo de 32 kHz para mantener el tiempo en segundos. Cada vez que se produce la interrupción por exceso de flujos TCNT2, se incrementan los segundos. Muy fácil. Pero ahora necesito una interfaz de un solo botón para que cuando el usuario presione el botón, se muestre la hora y cuando el usuario mantenga presionado el botón durante más de 2 segundos, el reloj entrará en el modo de configuración de la hora. Para eso decidí usar la INT2 de ATmega32.

#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/io.h>


static char not_leap(void);
static void init(void);
volatile unsigned int interruptFlag = 0;
unsigned char interruptTime;

typedef struct {
unsigned char second;
unsigned char minute;
unsigned char hour;

} time;

time t;

int main(void)
{

/* Initialize registers and configure RTC. */
init();
while (1) {
    /* Enter sleep mode.
     * (Will wake up from timer overflow interrupt) */
    sleep_mode();

    /*The MCU should always be awake for a minimum of one
     * TOSC cycle, before re-entering sleep mode. Otherwise,
     * the interrupt flag will not be cleared, and the MCU
     * will stay in sleep mode until it is reset. We solve
     * this by doing a dummy write to the TCCR0 register
     * and waiting until the ASSR register reports that TC0
     * has been updated, before going to sleep*/

    if (interruptFlag == 1)
    {
        //display time
        interruptFlag = 0;
    }

    if(t.second => interruptTime + 2 && (PINB & 1<< PINB2))
    {
            GICR &= ~(1<<INT2); //disable interrupt

            //set time using button as input

            GICR |= (1<<INT2); //Enable interrupt
        }

    /* Dummy write the desired prescaler */
    TCCR2 = (1 << CS20) | (1 << CS22);

    /* Wait until TC2 is updated */
    while (ASSR & ((1 << TCN2UB) | (1 << OCR2UB) | (1 << TCR2UB))) {
    }
}
}

static void init(void)
{
/* Wait for external clock crystal to stabilize */
for (uint8_t i = 0; i < 0x40; i++) {
    for (int j = 0; j < 0xFFFF; j++) {
        /* Do a nop instruction to keep the empty
         * loop from being optimized away */
        asm volatile("nop");
    }
}

/* Make sure all TC2 interrupts are disabled */
TIMSK &= ~((1 << TOIE2) | (1 << OCIE2));

/*disable interrupt IN2 */

GICR &= ~(1<<INT2);

/* set Timer/counter2 to be asynchronous from the CPU clock.
 * This will clock TC2 from the external 32,768 kHz crystal. */
ASSR |= (1 << AS2);

/* Reset timer */
TCNT2 = 0;

/* Prescale the timer to be clock source/128 to make */
/* TC2 overflow precisely once every second. */
TCCR2 = (1 << CS20) | (1 << CS22);

/* Wait until TC2 is updated */
while (ASSR & ((1 << TCN2UB) | (1 << OCR2UB) | (1 << TCR2UB))) {
}

/* Enable Timer/Counter0 Overflow Interrupts */
TIMSK |= (1 << TOIE2);

//clear interrupt flag bit
GIFR &= ~(1<<INTF2);

//Set INT2/PB2 to input

DDRB &= ~(1 << PB2);
PORTB &= ~(1<< PB2);

GICR |= 1<<INT2;                    // Enable INT2
MCUCSR |= 1<<ISC2;               //rising edge

/* Set the Global Interrupt Enable Bit */
sei();

/* Setting the sleep mode to be used to power save mode. */
set_sleep_mode(SLEEP_MODE_PWR_SAVE);

/* Enabling sleep mode */
sleep_enable();
}

/* keep track of time, date, month, and year */
ISR(TIMER2_OVF_vect)
{
if (++t.second == 60) {
    t.second = 0;
    if (++t.minute == 60) {
        t.minute = 0;
        if (++t.hour == 24) {
            t.hour = 0;

}

ISR(INT2_vect)
{
interruptFlag ++;
interruptTime = t.second;
}

Utilicé una variable para aumentar cuando ocurrió la interrupción y también grabé la marca de tiempo en segundos (usando el RTC que ya se está ejecutando) del momento en que ocurrió la interrupción. La interrupción se produce en el borde ascendente. Ahora que se produjo la interrupción, el contador aumentó de 0 a 1, lo que indica que el botón se presionó al menos una vez, así que muestro la hora y vuelvo a configurar el contador en 0.

Ahora compruebo si han transcurrido 2 segundos en el tiempo RTC desde la última interrupción y también presiona el botón para ver si aún está presionado. Si es así, desactiva la interrupción. Esto lleva al usuario al modo de configuración de tiempo. Ahora puedo sondear el pin y leer las entradas altas y desplazarme por la hora y los minutos para configurar la hora.

Después de configurar el tiempo, el MC volverá a dormir y habilitará la interrupción [aún no se ha implementado en el código]

De esta manera, la hora se mostrará cada vez que se presione el botón y entrará en el modo de configuración de tiempo si se mantiene presionado el botón durante 2 segundos o más.

Así que mi pregunta es ¿Puede leer el pin INT2 / PB2 cuando el INT2 está habilitado?

¿Este código tiene alguna posibilidad de funcionar?

    
pregunta user2626326

0 respuestas

Lea otras preguntas en las etiquetas