Contador ascendente/descendente con PIC

¿Qué tal? Tengo un proyecto que cuenta en ascendencia y muestra la cuenta en un display de 7 segmentos de ánodo común.
Quisiera que contara en descendencia y seleccionar el modo con un solo push button, que con un toque cuente ascendente y con otro descendente y así sucesivamente.
Estoy programando el PIC16F877A en PIC C

Espero puedan ayudarme. De antemano, muchas gracias.
PHP:
#include <16f877a.h>
#use delay (clock = 4000000)

#byte p_b = 6

void main (void)
{ 
     int c;
     int display [10]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x83,0xb8,0x80,0x98};
     set_tris_b (0x00);
     c=0;
      while(TRUE) {
         output_b(display[ c ]);
         delay_ms (500);
         c++;
         if (c>9)
         {
           c=0;
         }
       }
}
 
Disculpen, amigos. Tengo este problema.
Necesito hacer un contador en un PIC con esta condición; si pulso una vez el botón, empiece a contar ascendente y si lo vuelvo a pulsar, que cuente descendente.
La dificultad es que es un solo botón y no se me ocurre como hacerlo.

Aquí está mi código:

PHP:
#include <16f877A.h> // busca la librería del dispositivo
#use delay (clock = 4000000) //configura el dispositivo para operar esta frecuencia
#use fast_io(b)
#byte puerto_b = 06 //la variable de nombre puerto_b esta apuntando

#use standard_io(A)

///DECLARACION DE FUNCIONES
void up(void);      //funcion cuenta ascendente
void down(void);   //funcion cuenta descendente

///DECLARACION VARIABLES GLOBALES
signed char i;   //contador para tabla 7 seg (se tiene en cuenta el signo)
int tab7seg[10]={0x3F,6,91,79,102,109,125,7,127,103};   //7seg binario 0-9
      
///PROGRAMA
void main(void)
{
   set_tris_a(0xFF);            //porta como entrada   
   set_tris_b(0x00);            //portb como salida
   disable_interrupts(GLOBAL);      //todas las interrupciones desactivadas
///inicializamos el contador   
   if(!input(PIN_A0))      //para ello leemos el estado del pin A0 del porta
      i=10;            //contador descendente
   else
      i=i--;            //contador ascendente

   do{                        //bucle...
      if(input(PIN_A0))         //¿switch abierto?
         up();               //SI -> contador ascendente
      else// pregunta dos veces ...
         down();//NO -< contador descendente
         
      output_b(tab7seg[ i ]);     //muestra por portb dígito 7 segmentos
      delay_ms(500);
      }while(TRUE);            //...infinito         
}

void up(void)                  //función cuenta ascendente
{         
      i++;                  //incremento contador para visualizar siguiente dígito
      if(i>9)                  //¿ya se ha mostrado el dígito 9?
         i=0;               //SI -< vuelve a empezar(dígito 0)         
}

void down(void)                  //función cuenta descendente
{
      i--;                  //decremento contador para visualizar siguiente dígito
      if(i==-1)               //¿ya se ha mostrado el dígito 0?
         i=9;               //SI -< vuelve a empezar(dígito 9)
}
 
Última edición por un moderador:
Hola!

Te recomendaría usar una interrupción, que con el botón controles una variable global y en las interrupción que sólo pueda tomar dos valores.

Ejemplo:
PHP:
int contbot = 0; //Contador botón

void Interrput(){

  contbot += 1;

  if (contbot >= 2){  // De esta manera contbot solo valdrá 0 o 1

    contbot = 0;
  
  }

IntFlag = 0;  // Bandera interrupción igual a 0 para salir de la interrupción.

 }

seguido de este, en tu función principal un case con tus funciones up y down

void main (){

switch contbot {   // Switch con la variable global del botón.
 case 0; up() ; break;
 case 1; down(); break;         
}

}
Espero haberte ayudado! Saludos
 
Última edición por un moderador:
Hola buenas tardes querida comunidad pido su apoyo ya que me encuentro haciendo un contador ascendente y descendente pero lo que me falta es hacer el descenso y no encuentro la forma de programarlo ya que lo intento pero lo único que me sale es que se reinicia el conteo espero puedan ayudarme
 

Adjuntos

  • contador 0-FFFF.zip
    883 bytes · Visitas: 13
No he mirado muy a fondo tu código pero no veo que sea un contador, mas bien parece un cronómetro o un reloj y no veo por ningún lado que haya opción ascendente o descendente, solo hay un cronómetro.

Comenta el código porque no se entiende mucho y pregunta en concreto.
Publicalo en el post que no tengo ganas de ir abriendo archivos.
Creo que copiaste el código de algún sitio y así sin abrirlo nos lo has colgado a ver si hacemos tu trabajo.
C++:
#include <16f877a.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,BROWNOUT
#use delay(clock=4M)
#use standard_io(A)
#use standard_io(C)
#use fast_io(D)

#define boton_inicio PIN_A0
#define boton_detener PIN_A1
#define boton_reset PIN_A2


int display[16] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x18,0x08,0x03,0x46,0x21,0x06,0x0e};
int16 contador;
int unidades_seg, decenas_seg;
int unidades_min, decenas_min;
int tiempo = 1;
void mostrar_cronometro();

#int_timer0                                              // Interrupcion para 1 segundo
void timer0()
{
   contador++;
   if(contador == 1000)
   {
      unidades_seg++;
      contador = 0;
      if(unidades_seg > 15){
         unidades_seg = 0;
         decenas_seg++;
         if(decenas_seg > 15){
            decenas_seg = 0;
            unidades_min++;
            if(unidades_min > 15){
               unidades_min = 0;
               decenas_min++;
            }
         }
      }
   }
  set_timer0(10);
}

void main()
{
   set_tris_d(0x00);
   setup_timer_0(RTCC_INTERNAL |RTCC_DIV_4);
   unidades_seg = 0;
   decenas_seg = 0;
   unidades_min = 0;
   decenas_min = 0;
  
   while(true)
   {
      mostrar_cronometro();
      
      if(input(boton_inicio) == 1){
         while(input(boton_inicio) == 1){
            mostrar_cronometro();
         }
         set_timer0(131);
         enable_interrupts(INT_TIMER0);
         enable_interrupts(GLOBAL);
      }
      
      if(input(boton_detener) == 1){
         while(input(boton_detener) == 1){
            mostrar_cronometro();
         }
         disable_interrupts(GLOBAL);
      }
      
      if(input(boton_reset) == 1){
         while(input(boton_reset) == 1){
            mostrar_cronometro();
         }
         unidades_seg = 0;
         decenas_seg = 0;
         unidades_min = 0;
         decenas_min = 0;
      }
      
      if(decenas_min > 16)
      {
         disable_interrupts(GLOBAL);
         unidades_seg = 0;
         decenas_seg = 0;
         unidades_min = 0;
         decenas_min = 0;
      }
   }
}

void mostrar_cronometro()
{
   output_c(0b1110);
   output_d(display[unidades_seg]);                      // Mostramos las unidades de los segundos
   delay_ms(tiempo);
 
   output_c(0b1101);
   output_d(display[decenas_seg]);                       // Mostramos las decenas de los segundos
   delay_ms(tiempo);
  
   output_c(0b1011);
   output_d(display[unidades_min]);                      // Mostramos las decenas de los minutos
   delay_ms(tiempo);
  
   output_c(0b0111);
   output_d(display[decenas_min]);                       // Mostramos las decenas de los minutos
   delay_ms(tiempo);
}
 
Algo no cuadra leyendo un poco mas:
"me encuentro haciendo un contador ascendente y descendente"

Pero en el código dice:
"
#define boton_inicio PIN_A0
#define boton_detener PIN_A1
#define boton_reset PIN_A2
"


¿Donde están boton_incrementa y boton_decrementa? ¿Como es que cuenta algo si no hay por donde meter la cuenta?
O bien boton_cuenta boton_direccion o algo así.
 
Atrás
Arriba