Contador 0 a 99 con PIC y displays de 7 segmentos

Dr. Zoidberg

Well-known-Papá Pitufo
Por suerte el programa está en C. No me quiero imaginar si estuviera en assembler....
 

D@rkbytes

Moderador
Por lo que veo va a existir un problema de contención lógica con el pulsador al estar en el puerto A y este mismo usado como salida.
Ya que se usó #use standard_io(a) se debió haber hecho uso del set_tris_a(x); para definir entradas y salidas.

Edit: Cambiar #use standar_io(a) por #use fast_io(a) y en el main declarar: set_tris_a(0b00000100);
 
En lugar de unidad++; sería unidad--;
Lo mismo con las decenas.


asi??

if (input(pin_a3)==1)
{
unidad--;
if (unidad>9)
{
decena--;
unidad=0;
}

if(decena>9)
{
decena=0;
unidad=0;
}
}
 

D@rkbytes

Moderador
No, porque ahora estás restando y ya no se debe comparar con > 9, sino con == 0
De igual forma, ahora las variables se deben inicializar en 9 porque habrá un decremento.

Sería así:
C:
#include <16F628A.h>

#use delay(INTERNAL = 4 MHz)
#use fast_io(A)

int display[10] = {0b0000001, 0b1001111, 0b0010010, 0b0000110, 0b1001100,
                   0b0100100, 0b0100000, 0b0001111, 0b000000, 0b0000100};

void main (void)
{
    int unidad = 9;
    int decena = 9;
    int16 tiempo = 5;
 
    set_tris_a(0b00000100);

    while(TRUE)
    {
        if(input_state(PIN_A2))
        {
            output_a(0b10);
            output_b(display[unidad]);
            delay_ms(tiempo);
            output_a(0b01);
            output_b(display[decena]);
            delay_ms(tiempo);
        }
        else
        {
            delay_ms(tiempo);
            output_a(0b10);
            output_b(display[unidad]);
            delay_ms(tiempo);
            output_a(0b01);
            output_b(display[decena]);
            delay_ms(tiempo);
 
            if (input_state(PIN_A2))
            {
                unidad --;
         
                if (unidad == 0)
                {
                    decena --;
                    unidad = 9;
                }
             
                if (decena == 0)
                {
                    decena = 9;
                    unidad = 9;
                }
            }
        }
    }
}
Corrijo la comparación porque al parecer al llegar a 10 regresaría a 99
Quedaría de esta forma:
C:
            if (input_state(PIN_A2))
            {
                unidad --;
          
                if (unidad > 9)
                {
                    decena --;
                    unidad = 9;
                }
              
                if (decena > 9)
                {
                    decena = 9;
                    unidad = 9;
                }
            }
 
Qué tal, tengo un circuito que funciona como un contador ascendente de 0 a 99 con dos display 7 segmentos, teniendo un push botton como incrementador y otro como reset, el problema que tengo es que mi circuito físico no funciona correctamente, al probarlo en Proteus 8 funciona correctamente o como incrementador.

El problema que detecto según mi perspectiva es que hay algún cable que no esta conectado a tierra por que presenta ciertos cortos que hacen que el display se apague o prenda de forma aleatoria, incluso cuando pongo mis dedos en el pic, los display prenden.

Este problema ya lo había presentado con otro circuito, se arreglo conectando los puertos de entrada que no ocupaba a tierra.

Mis puertos de entrada son el PORTC

Mis puertos de salida son PORTA, PORTB.

Adjunto mas imágenes al respecto.

Si se requiere más información háganme saber, gracias.
 

Adjuntos

Por favor! Meté resistencias de al menos 100ohms para limitar la corriente en los segmentos.

En los simuladores nada se quema, en el mundo real sí.
 

D@rkbytes

Moderador
En el protoboard se ven 7 resistencias de 330 Ohms, debe ser una por segmento porque el sistema es multiplex.
 

D@rkbytes

Moderador
En dado caso que los transistores estuvieran bien conectados, sería mejor usar PNP e invertir la lógica de control.
 
En dado caso que los transistores estuvieran bien conectados, sería mejor usar PNP e invertir la lógica de control.
No creas, en esa configuración el transistor no llega a saturar (no puede el pobre) pero esa caída de tensión no afecta porque estás sobrado y despues de todo, la parte que no se disipa en el transistor se disipará en las resistencias de los segmentos. Además, si fueran muchos dígitos te ahorrás el espacio de las resistencias de base.
 
Tenés razón. Tal vez sea el color medio cambiado pero me parecen de 33ohms.
Aquí les dejo el código.
La palabra de configuración es una predeterminada que nos dieron para todos las prácticas en mi escuela, de hecho la he utilizado en anteriores prácticas y ha funcionado de forma correcta.

Las resistencias que conecté a los display son de 330 ohms.
Usé de manera invertida los transistores debido a que los display son ánodo común, por eso me conviene tenerlos conectados de esa forma.

Más dudas, háganme saber.
Código:
LIST P=18F4550
#INCLUDE <P18F4550.INC>

;Palabra de Configuración
;CONFIG1L dir 300000h 20
;CONFIG PLLDIV=1 ;
;CONFIG CPUDIV=OSC1_PLL2 ;CUANDO SE USA XTAL
  ;CONFIG USBDIV=2
  ;CONFIG1H dir 300001h 08
CONFIG FOSC=INTOSCIO_EC ;OSCILADOR INTERNO, RA6 COMO PIN, USB USA OSC EC
CONFIG FCMEN=OFF ;DESHABILITDO EL MONITOREO DEL RELOJ
CONFIG IESO=OFF
;CONFIG2L DIR 300002H 38
CONFIG PWRT=ON ;PWRT HABILITADO
CONFIG BOR=OFF ;BROWN OUT RESET DESHABILITADO
CONFIG BORV=3 ;RESET AL MINIMO VOLTAJE NO UTILZADO EN ESTE CASO
CONFIG VREGEN=ON ;REULADOR DE USB ENCENDIDO
;CONFIG2H DIR 300003H 1E
CONFIG WDT=OFF ;WATCH DOG DESHABILITADO
CONFIG WDTPS=32768 ;TIMER DEL WATCHDOG
;CONFIG3H DIR 300005H 81
CONFIG CCP2MX=ON ;CCP2 MULTIPLEXADAS CON RC1
CONFIG PBADEN=OFF ;PUERTO B PINES DEL 0 AL 4 ENTRADAS DIGITALES
CONFIG LPT1OSC=OFF ;TIMER1 CONFIURADO PARA OPERAR EN BAJA POTENCIA
CONFIG MCLRE=ON ;MASTER CLEAR HABILITADO
;CONFIG4L DIR 300006H 81
CONFIG STVREN=ON ;SI EL STACK SE LLENA CAUSE RESET
CONFIG LVP=OFF ;PROGRAMACIÒN EN BAJO VOLTAJE APAGADO
CONFIG ICPRT=OFF ;REGISTRO ICPORT DESHABILITADO
CONFIG XINST=OFF ;SET DE EXTENCION DE INSTRUCCIONES Y DIRECCIONAMIENTO INDEXADO DESHABILITADO
;CONFIG5L DIR 300008H 0F
CONFIG CP0=OFF ;LOS BLOQUES DEL CÒDIGO DE PROGRAMA
CONFIG CP1=OFF ;NO ESTAN PROTEGIDOS
CONFIG CP2=OFF
CONFIG CP3=OFF
;CONFIG5H DR 300009H C0
CONFIG CPB=OFF ;SECTOR BOOT NO ESTA PROTEGIDO
CONFIG CPD=OFF ;EEPROM N PROTEGIDA
;CONFIG6L DIR 30000AH 0F
CONFIG WRT0=OFF ;BLOQUES NO PROTEGIDOS CONTRA ESCRITURA
CONFIG WRT1=OFF
CONFIG WRT2=OFF
  CONFIG  WRT3=OFF
  ;CONFIG6H DIR 30000BH E0
CONFIG WRTC=OFF ;CONFIGURACION DE REGISTROS NO PROTEGIDO
CONFIG WRTB=OFF ;BLOQUE BOOTEBLE NO PROTEGIDO
  CONFIG  WRTD=OFF  ;EEPROMDE DATOS NO PROTGIDA
  ;CONFIG7L DIR 30000CH 0F
CONFIG EBTR0=OFF ;TABLAS DE LETURA NO PROTEGIDAS
CONFIG EBTR1=OFF
CONFIG EBTR2=OFF
  CONFIG  EBTR3=OFF
  ;CONFIG7H DIR 30000DH 40
CONFIG EBTRB=OFF ;TABLAS NO PROTEGIDAS

ORG 0X00

MOVLW 0XFF
MOVWF OSCCON

MOVLW 0X0F
MOVWF ADCON1

MOVLW 0X07
MOVWF CMCON

CBLOCK 0X00
UNIDAD
DECENA
CONTADOR
CONTADOR1
CONTADOR2
CONTADOR3
ENDC

; Entradas
#DEFINE BOTONI PORTC,RC0
#DEFINE BOTONR PORTC,RC1

MOVLW 0X7F
MOVWF TRISC

; Salidas
BCF TRISA,RA1
BCF TRISA,RA2
CLRF TRISB

RESETEO CLRF UNIDAD
CLRF DECENA
CALL LOOP
GOTO INICIO

INICIO CALL LOOP
BTFSS BOTONI
GOTO BOTONRESET
CICLO CALL LOOP
CALL RETARDO2
BTFSC BOTONI
GOTO CICLO
CALL LOOP
GOTO INCREMENTO

BOTONRESET
BTFSS BOTONR
GOTO INICIO
CICLO1 CALL LOOP
CALL RETARDO2
BTFSS BOTONR
GOTO CICLO1
GOTO RESETEO

INCREMENTO
INCF UNIDAD,1
MOVLW D'9'
CPFSGT UNIDAD
GOTO INICIO
MOVLW D'0'
MOVWF UNIDAD
INCF DECENA,1
MOVLW D'9'
CPFSGT DECENA
GOTO INICIO
GOTO RESETEO

LOOP
BCF PORTA,RA2
CALL UNIDADES
BSF PORTA,RA1
CALL RETARDO1
BCF PORTA,RA1
CALL DECENAS
BSF PORTA,RA2
CALL RETARDO1
BCF PORTA,RA2
RETURN

UNIDADES
MOVFF UNIDAD,WREG
RLNCF WREG
CALL DISPLAY
MOVWF PORTB
RETURN

DECENAS
MOVFF DECENA,WREG
RLNCF WREG
CALL DISPLAY
MOVWF PORTB
RETURN

RETARDO1
MOVLW D'124'
MOVWF CONTADOR

RUTINA NOP
DECFSZ CONTADOR,F
GOTO RUTINA
RETURN

RETARDO2
RUTINA4 MOVLW d'10'
MOVWF CONTADOR3

RUTINA3 MOVLW d'2'
MOVWF CONTADOR2

RUTINA2 MOVLW d'249'
MOVWF CONTADOR1

RUTINA1 NOP
DECFSZ CONTADOR1,F
GOTO RUTINA1
DECFSZ CONTADOR2,F
GOTO RUTINA2
DECFSZ CONTADOR3,F
GOTO RUTINA3
RETURN

DISPLAY
ADDWF PCL,F
RETLW b'1000000';0
RETLW b'1111001';1
RETLW b'0100100';2
RETLW b'0110000';3
RETLW b'0011001';4
RETLW b'0010010';5
RETLW b'0000010';6
RETLW b'1111000';7
RETLW b'0000000';8
RETLW b'0011000';9

END
 

D@rkbytes

Moderador
La palabra de configuración es más sencillo escribirla de esta forma:
Código:
    config    FOSC = INTOSCIO_EC, PLLDIV = 1
    config    PWRT = ON, LVP = OFF, WDT = OFF
Así se escriben únicamente los bits necesarios y se evitan redundancias en los fuses por defecto.

El registro OSCCON está mal configurado. (Aunque los bits más importantes son: IRCF2, IRCF1 e IRCF0)
1 MHz es el valor por defecto si no se configura.
Para 8 MHz debería tener el valor 0x72
Para 4 MHz debería tener el valor 0x62
Para otras frecuencias inferiores hasta 31 KHz, ver la hoja de datos.
El registro CMCON no se está usando, por lo tanto no tiene caso su configuración.
En este PIC con configurar el registro ADCON1 basta para establecer los pines que serán análogos o digitales.
En los PIC18 es más conveniente usar los registros LATX que los PORTX
Otro detalle. Tabular y comentar el código es importante.

Aunque existe algo de basura dentro del programa, debería funcionar físicamente.
Así que debe haber un problema de hardware.
 

Arriba