Si existe forma de hacerlo.
Lo que te comente era lo ideal.
Entonces tenemos que en el loop principal debemos:
- Multiplexar los digitos
- leer los botones ( para aumentar y decrementar el contador )
- generar un delay para que no todo suceda rapido
Y aca nos enfrentamos al problema de siempre...
Si el delay es muy grande, el multiplexado de los digitos en el display se va a notar. Pero los botones va a ser simple su control.
Si el delay es pequeño los botones se van a leer demasiado rapido. pero el display se va a ver bien.
Lo bueno es que es posible buscar formas de leer los botones mas lento... Hasta ahora el programa queda asi:
void main(void)
{
// Aca configuracion de pines
while(1)
{
// Multiplexado
if(PORTAbits.RA2)
{
// Aca entra si estaban activas las unidades en el anterior paso
PORTAbits.RA2 = 0; // Comun unidades las apago
PORTAbits.RA3 = 1; // Comun decenas las activo
PORTB = leds_unidad[dec];
}
else
{
// Aca entra si estaban activas las decenas en el anterior paso
PORTAbits.RA2 = 1; // Comun unidades las apago
PORTAbits.RA3 = 0; // Comun decenas las activo
PORTB = leds_unidad[uni];
}
// Botones
// Aca hay que agregar el codigo de los botones
// Delay de cada vuelta del loop
__delay_ms(20);
}
}
A partir de aca lo unico que hay que hacer es el codigo de los botones.
En el codigo de los botones NO SE USA DELAYS¿ Como no usar delays ? En realidad el unico delay que tenemos es el de los 20ms que esta fuera.
Y te propongo 2 formas de leer los botones.
- 1era opcion
Usar un contador extra que cuente las veces que pasa por el codigo de los botones. Y por ejemplo si quisiera que entre a cada segundo a ver si hay algo presionado, entonces voy a poner a aumentar una variable y cuando pase 50 veces ( 20ms * 50 = 1s ) entro a leer los botones. Otra forma de verlo, cada vuelta del while tarda 20ms gracias al delay, si esperamos que pasen 50 vueltas, estariamos leyendo los botones cada 1s.
Esta opcion esta buena en el sentido de que es simple de implementar.
botones++;
if (botones >= 50)
{
botones = 0;
if(RA0 == 1 y RA1 == 0)
{
//sumo contador
} else if (RA0 == 0 y RA1 == 1)
{
//resto contador
}
}
La ventaja es que es facil de implementar. La desventaja es que tenes que presionar el boton justo cuando se cumple el segundo, en el peor caso el maximo tiempo que debes tenerlo presionado es 1s, ya que si por ejemplo justo persionamos cuando nuestro contador de vueltas esta en 1 y lo soltamos cuando esta en 49, no va a reconocer esa accion, un simple persion del boton son 200/300ms. reducir la cantidad de vueltas implica que si lo tenes presionado, se incremente o decremente mas rapido, hasta que si lo persionas un poco de mas termines aumentando de a 2. Entonces ganas "responsividad" pero perdes control.
-2da opcion
Esta es la ideal.
En esta opcion vamos a guardar el valor de los botones, asi cuando pase una vuelta volvemos a revisarlo y comparamos con la proxima vuelta.
De aca se desprende 2 posibilidades, que sean iguales o que no, si son iguales quiere decir que se mantuvo presionado el boton y no hacemos nada, si no lo son entonces significa que algo cambio..
botonesactual = PORTA & 0x3; // Solo RA0 yRA1
if ( botonesanteriores != botonesactual)
{
//Algo cambio, entonces reviso
if(botonesactual == 0x01) // Solo RA0 presionado
{
contador++;
if(contador > 99) contador = 99;
}
if(botonesactual == 0x02) // Solo RA1 presionado
{
if(contador != 0) contador--;
contador--;
}
// Actualizo botones anteriores para la proxima vuelta
botonesanteriores = botonesactual;
}
Este ultimo codigo posee una ventaja, y es que responde al minimo tiempo que se puede ejecutar esto, que son los 20ms del delay principal, desventajas asi como esta puede llegar a ser cuando se presionen varios botones, pero que modificando el programa tranquilamente podrias arreglar ese problema. Tambien esos 20ms del loop while nos sirven de una especie de antirebote.
Ahora juntamos todo y....
int leds_unidad [10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x18};
int uni = 0,dec = 0;
int botonesanteriores = 0; // Variable usada para mantener el estado de los botones de la vuelta del while anterior
int botonesactual; // Variable usada para guardar el valor de los botones presionados en ese ciclo.
void main(void)
{
// Aca configuracion de pines/oscilador/etc
OSCCONbits.SCS = 11;
OSCCONbits.IRCF = 110;
ADCON1 = 0xF;
TRISA = 0x3;
TRISB = 0;
while(1)
{
// Multiplexado
if(PORTAbits.RA2)
{
// Aca entra si estaban activas las unidades en el anterior paso
PORTAbits.RA2 = 0; // Comun unidades las apago
PORTAbits.RA3 = 1; // Comun decenas las activo
PORTB = leds_unidad[dec];
}
else
{
// Aca entra si estaban activas las decenas en el anterior paso
PORTAbits.RA2 = 1; // Comun unidades las apago
PORTAbits.RA3 = 0; // Comun decenas las activo
PORTB = leds_unidad[uni];
}
// Botones
botonesactual = PORTA & 0x3; // Solo RA0 yRA1
if ( botonesanteriores != botonesactual)
{
//Algo cambio, entonces reviso
if(botonesactual == 0x01) // Solo RA0 presionado
{
uni++;
if(uni > 9)
{
if(dec != 9)
{
dec++;
uni = 0;
}
else
{
uni = 9;
}
}
}
if(botonesactual == 0x02) // Solo RA1 presionado
{
if(uni != 0)
{
uni--;
}
else
{
if(dec != 0)
{
dec--;
uni = 9;
}
}
}
// Actualizo botones anteriores para la proxima vuelta
botonesanteriores = botonesactual;
}
// Delay de cada vuelta del loop
__delay_ms(20);
}
}
O si queres usar el contador como venias haciendo:
int leds_unidad [10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x18};
int uni = 0,dec = 0, contador = 0;
int botonesanteriores = 0; // Variable usada para mantener el estado de los botones de la vuelta del while anterior
int botonesactual; // Variable usada para guardar el valor de los botones presionados en ese ciclo.
void main(void)
{
// Aca configuracion de pines/oscilador/etc
OSCCONbits.SCS = 11;
OSCCONbits.IRCF = 110;
ADCON1 = 0xF;
TRISA = 0x3;
TRISB = 0;
while(1)
{
// Multiplexado
if(PORTAbits.RA2)
{
// Aca entra si estaban activas las unidades en el anterior paso
PORTAbits.RA2 = 0; // Comun unidades las apago
PORTAbits.RA3 = 1; // Comun decenas las activo
PORTB = leds_unidad[dec];
}
else
{
// Aca entra si estaban activas las decenas en el anterior paso
PORTAbits.RA2 = 1; // Comun unidades las apago
PORTAbits.RA3 = 0; // Comun decenas las activo
PORTB = leds_unidad[uni];
}
// Botones
botonesactual = PORTA & 0x3; // Solo RA0 yRA1
if ( botonesanteriores != botonesactual)
{
//Algo cambio, entonces reviso
if(botonesactual == 0x01) // Solo RA0 presionado
{
contador++;
if(contador > 99) contador = 99;
}
if(botonesactual == 0x02) // Solo RA1 presionado
{
if(contador != 0) contador--;
contador--;
}
// Actualizo botones anteriores para la proxima vuelta
botonesanteriores = botonesactual;
// Actualizo uni y dec
dec = contador/10;
uni = contador%10;
}
// Delay de cada vuelta del loop
__delay_ms(20);
}
}