Hacerlo con delays es malo, seguramente le erre en tiempo y por mucho. Pero para comenzar no veo mal la idea. Tu programa lo deberias dividir en varias partes que poco a poco podes ir mejorando.. Necesitas:
- Leer los pulsadores y actuar en consecuencia.
- Aumentar el tiempo acumulado en caso de ser necesario
- Mostrar los datos en un display.
Entonces vamos a tener un main algo asi:
void main(void)
{
//Configuracion de pines
while(1)
{
LecturaDeSensores();
if(RelojCorriendo == 1)
{
AumentarReloj();
}
MostrarEnDisplay();
Delay_ms(10);
}
}
Algunas cosa a tener en cuenta al diseñar esto... la idea es que ninguna de esas funciones ocupe demasiado tiempo, sino que lo mas consumidor en todas las instrucciones que puede tener dentro del while sea el delay en este ejemplo. Esto te va a llevar a pensar de otra forma.
Ejemplo, como incremento mis numeros.
Yo se que pasaron 10ms (aproximado) desde que entro la anterior ves, gracias a mi delay de 10ms. Entonces podria aumentar mi decima de milisegundo cada ves que entra.. Supongamos que tenemos estas variables: ( MM:SS:mm
Milisegundo
DecimaMilisegundo
Segundo
DecimaSegundo
Minuto
DecimaMinuto
Entonces al entrar haria:
Milisegundo++;
if(Milisegundo>9)
{
Milisegundo = 0;
DecimaMilisegundo ++;
}
if(DecimaMilisegundo>9)
{
DecimaMilisegundo = 0;
Segundo ++;
}
// etc...
Es decir incremento mi decima y luego corrijo.
Pero.... que pasa con mostrar en el display...
Algo tentador seria hacer esto:
void MostrarDisplay(void)
{
//Muestro Display1
//delay
//Muestro Display2
//delay
}
Pero estariamos agregando delays, y eso afecta a nuestra base de tiempo conocida, que son esos 10ms!!!!!. NO sirve.. vamos a necesitar otra forma que muestre 1 numero y luego salga, pero la proxima ves que entre muestre el numero que le sigue! Para esto lo mejor son los arrays y tener una variable para indicar cual es el que debemos encender.
Todas tus funciones d1,d2,d3, etc se van a simplificar. Y por ahora vamos a usar un switch case, pero podrias tranquilamente tambien usar un array para guardar tus numeros, luego pongo un codigo mas simple.
unsigned char ComunPuerto[] = {0b1,0b10,0b100,0b1000,0b10000};
unsigned char numeroDeDigito = 0;
void Mostrar_Display(void)
{
switch(numeroDeDigito)
{
case 0:
PORTC = numero[Milisegundo];
break;
case 1:
PORTC = numero[DecimaMilisegundo];
break;
case 2:
PORTC = numero[Segundo];
break;
case 3:
// seguir rellenenado
}
PORTD = ComunPuerto[numeroDeDigito];
numeroDeDigito++;
if(numeroDeDigito > sizeof ComunPuerto) numeroDeDigito = 0;
}
Como ves mostramos mucho mas rapido con un array.. que pasaria si crearamos OTRO array para almacenar los numeros a mostrar. Ejemplo:
short numero[]={192,249,164,176,153,146,130,248,128,144};
unsigned char ComunPuerto[] = {0b1,0b10,0b100,0b1000,0b10000,0b100000};
unsigned char NumerosMostrar[] = {1,2,4,8,9,7}; // 12 minutos, 48 segundos, 97 milesimas
unsigned char numeroDeDigito = 0;
Mi funcion de mostrar ahora seria asi:
void Mostrar_Display(void)
{
PORTC = numero[NumerosMostrar[numeroDeDigito]];
PORTD = ComunPuerto[numeroDeDigito];
numeroDeDigito++;
if(numeroDeDigito > sizeof ComunPuerto) numeroDeDigito = 0;
}
Se simplifico bastante no?
Respecto a los sensores, es leer el pin, y si esta activo, podrias por ejemplo cambiar una variable RelojCorriendo, entre 0 y 1, de esa forma podes "parar" (haces que no auemnte la cuenta) el reloj. Y si activa el sensor de reset, procedes a poner a 0 en cada posicion el array NumerosMostrar. Por supuesto, esto va a entrar cada 10ms, por lo que vas a tener que tener en cuenta que si el sensor se mantiene activo por mas de 10ms, no le hagas caso, podes esperar que se suelte por ejemplo. Esta parte te la dejo a vos, venis con una solucion y luego le damos otra vuelta de tuerca.