Tenes una buena estructura del programa y es como lo deberias estar haciendo. Lo unico que te falta es crear las funciones para Rb0, tmr0 y principal,etc
Todo va a depender del cristal que uses. es la velocidad que va a contar, te voy a ir dando pistas y un pseudocodigo para que busques como hacerlo vos misma.
La entrada al TMR0 puede ser externa o interna usando el cristal a un pulso cada cada 4/Fosc , si usas 4Mhz son 4/4Mhz = 1uS, Pero antes que entre lo podes hacer pasar por un prescaler (un divisor de frecuencia ) asi obtenes tiempos mas largos.
En el 16f84a esta compartido con el WDT y se modifica en el registro OPTION (fijate en el diagrama del TMR0 en el datasheet), el minimo que corresponde al TMR0 es de 1:2 y el maximo 1:256, utilizaremos el de 1:64.
Asi que tu tiempo seria: 1uS * 64 = 64uS
Para que tu TMR llegue a 1 segundo necesitarias que cuente hasta = 1s / 64uS = 15625 (elegi 1:64 por que da entero y facilita mucho las cosas)
Pero tu TMR0 tiene un registro de 8 bits , es decir 2^8 = 256
Por lo cual vas a tener que tener una variable que cuente al menos 15625 / 256 = 61.03515625 veces que entra a la interrupcion.
Si te fijas no es un entero, 61 vueltas al TMR0 contaria 15616 y nos faltaria 9, por lo tanto cuando cuente llegue a 61 tenes que cargar el TMR0 con otro valor y no 0x00, el TMR0 es ascendente por lo que tendrias que cargarlo con su complemento a 2. El complemento de 0x09 (9) es el negado y sumado 1, es decir 0xF7 (247).
Con eso ya tenes tu TMR0 a 1s Cuando se cumpla esas condiciones, es decir cuando ocurra la interrupcion y tengas 61 vueltas en tu contador.
Obviamente una ves todo inicializado activas las interrupciones y luego al final activas la interrupcion global, recorda borrar el TMR0 antes.
-------------------------------------------------------------------------
Para tu boton.... podes usar tanto Rb0 como Rb4 a Rb7, Rb0 simplifica un poco las cosas por que tiene una interrupcion segun flanco.
Para detectar el boton, haces una interrupcion en el flanco ascendente, entra a tu interrupcion, cambias al flanco de bajada, guardas unas variables mas y salis de tu interrupcion, Cuando entre de nuevo es por que solto y ahi es cuando volves a flanco ascendente y te fijas si las variables tienen lo que pedis.
El flanco con el que se dispara el RB0 esta dado por el registro OPTION y la habilitacion de la interrupcion en el INTCON junto con el flag de todas las interrupciones.
Para utilizar nuevamente nuestro TMR0 como lo teniamos configurado. Podes hacerlo de 2 formas una mas simple que es perder un poco de precision pero te va a ahorrar bastante codigo que es la de contar solamente las vueltas y sino
la forma "correcta" ( asi es un segundo exacto ) necesitarias 2 variables, una va a contener el valor del TMR0 y otra la cantidad de vueltas mientras esta presionado el boton ( asi que en el codigo del TMR0 tenes que pensar en sumar esa variable si es que esta presionado un boton )
Hago la mas simple:
Interrupcion:
Desabilito interrupciones globales
leo si es la interrupcion del RB0
Voy a la funcion
Fue por flanco ascendente?
SI: {
Habilito alguna flag asi el codigo del TMR0 sabe que deberia contar
cambio el flanco a descendente
}
NO(flanco descendente): {
Reviso que se dieron la cantidad necesaria de vueltas, es decir + de 61, si se dieron menos quiere decir que se presiono por menos de 1s.
Se dieron la cantidad de vueltas del TMR0 correctas?
SI: {
Activo flag para el programa principal, diciendo que se activo un segundo
}
NO : {
Activo flag para el programa principal, diciendo que se pulso por menos de un segundo
}
Borro cantidad de vueltas de mi contador de este pulsador
Vuelvo a flanco ascendente
}
Limpio flag de interrupciones antes de habilitar de nuevo.
Habilito interrupciones. ; Aunque esto iria en tu funcion de interrupciones general
Y tu programa principal quedaria muy simple:
principal:
Pregunto por flag de boton > 1s: {
Pongo a 0 los leds
Borro el flag
}
Pregunto por flag de boton < 1s: {
Borro el flag del boton de menos de 1s
Pongo a 0 contador propio del TMR ( me refiero a tu variable que deberia contar 61 que hable en el TMR0, no confundir con el contador del pulsador que el trabajo es el mismo pero esta destinado al boton )
Borro mi flag propia del TMR0
Prendo verde
Pregunto por flag propia cuando ocurra la vuelta 61 + el pedacito ese ( 62 ) si es asi paso 1 seg
Apago rojo
Pongo a 0 contador propio del TMR
Borro mi flag propia del TMR0
Prendo rojo
Pregunto por flag propia cuando ocurra la vuelta 61 + el pedacito ese ( 62 ) si es asi paso 1 seg
Apago rojo
}
Volver a Principal
En si este programa prenderia los leds como queres solo cuando presionas por menos de 1 segundo, Aunque no verias exactamente cuando borras todo por la forma que hice el programa principal, pero solo deberias modificar el programa principal.
En el caso que te di solo utilizarias 3 posiciones de memoria ( no me acuerdo si me olvido de alguna variable que use ademas xD) que pondrias en tu Cblock
ContadorTMR0
ContadorRB0
Flags