Autor Tema: multiplexacion con el pic 16f877a  (Leído 2523 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Zhunio

  • PIC10
  • *
  • Mensajes: 5
multiplexacion con el pic 16f877a
« en: 09 de Mayo de 2018, 17:19:24 »
tengo un problema, realicé un programa en el cual ingreso un numero por teclado y me aparece en un display de 7 segmentos multiplexado, el problema es que en todos me aparece el mismo numero o el otro problema que cada columna manejaba su propio display. como puedo hacer que cada boton del teclado que se presione me muestre en cada display sin corrimiento

ejemplo: si se presiona el 1 ell primer display muestra el numero, 4 segundo display 4 y asi sucesivamente.



CÓDIGO:

    list p=16f877A
    #include <p16f877A.inc>
    ERRORLEVEL-302
    __CONFIG H'3D3A'

    TECLA   EQU   0x30 ;variable que va contando el numero de teclas
    REG1    EQU 0x31 ; RETARDO
    REG2    EQU 0x32 ; RETARDO
    CARACTER EQU 0x33; CONTADOR DE CARACTER
    CONTADOR EQU 0x02; MUESTRA EL NUMERO
    CONTEO EQU 0x0C ;ACTIVO AL PUERTO DE LOS TRANSISTORES
     
    ORG 0x00
    GOTO INICIO
    ORG 0x05   
     
    TABLA
    ADDWF  CONTADOR,1
    NOP ; UTILIZO COMO INSTRUCCION DENTRO DE BUCLES PARA GENERAR RETARDOS DE TIEMPSO
    RETLW  B'01111001';1
    RETLW  B'00011001';4
    RETLW  B'01111000';7
    RETLW  B'00001110';F
    RETLW  B'00100100';2
    RETLW  B'00010010';5
    RETLW  B'00000000';8
    RETLW  B'01000000';0
    RETLW  B'00110000';3
    RETLW  B'00000011';6
    RETLW  B'00011000';9
    RETLW  B'01000110';C
    RETLW  B'00001000';A
    RETLW  B'00000011';B
    RETLW  B'00000110';E
    RETLW  B'00100001';D 
   
    INICIO:
    CLRF PORTB ;LIMPIA PORTB
    CLRF PORTC ;LIMPIA PORTB
    CLRF PORTD ;LIMPIA PORTB
    BSF STATUS,RP0 ; ACEDO AL BANCO 1
    MOVLW 0xF0 ; PORTB0-3 SALIDAS
    MOVWF TRISB ; PORTB4-7 ENTRADAS
    BCF OPTION_REG,7 ; HABILITA RESISTENCIA DE POLARIZACION EN ENTRADAS
    CLRF TRISD  ; PUERTO D COMO SALIDA AL DISPLAY
    MOVLW B'11110000' ;DECLARANDO SALIDA LOR PUERTO DE 0 A 3
    MOVWF TRISC ;PUERDO C COMO SALIDA
    BCF STATUS,RP0 ; REGRESO AL BANCO 0
    CLRF PORTB ;LIMPIA PORTB
    CLRF PORTC ;LIMPIA PORTB
    CLRF PORTD ;LIMPIA PORTB
   
    PRINCIPAL:
    CLRF CARACTER
    CALL INICIA_DISPLAY
    CALL CHEQUEO_TECLA
    GOTO PRINCIPAL
   
    ;SUBRUTINA PARA INICIALIZAR EL DISPLAT
    INICIA_DISPLAY:
    MOVLW B'01000000'; EL COMANDO 0X01 LIMPIA LA PANTALLA DLEL DISPLAY
    MOVWF PORTD
    RETURN
   
    COMANDO:
    ADDWF  CONTADOR,1
    NOP ; UTILIZO COMO INSTRUCCION DENTRO DE BUCLES PARA GENERAR RETARDOS DE TIEMPSO
    RETLW  B'00001110';1
    RETLW  B'00001101';4
    RETLW  B'00001011';7
    RETLW  B'00000111';F
    RETURN
   
    DELAY:           
    MOVLW 0xFF
    MOVWF REG2
    loop1:
    MOVLW 0xFF
    MOVWF REG1
   
    loop2:
    DECFSZ REG1,1
    GOTO loop2
    DECFSZ REG2,1
    GOTO loop1
    RETURN

    ;Escaneo del teclado
    CHEQUEO_TECLA:
    CLRF TECLA; BORRA EL CONTENIDO DE TECLA
    INCF TECLA,1;INICIALIZA TECLA
    MOVLW D'14'; PONE A 0 LA PRIMERA FILA
    MOVWF PORTB
    CLRF CONTEO; BORRA EL CONTENIDO DE CONTEO PARA LOS TRANSISTORES
    INCF CONTEO,1
    MOVLW D'14'
    MOVWF PORTC
    NOP
       
    CHECK_COL:
    BTFSS   PORTB,4 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO ENCENDIDO ; SALE SI SE HA PULSADO UNA TECLA
    INCF    TECLA,1  ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    INCF    CONTEO,1  ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    NOP          ;PONE UN CICLO DE RETARDO PARA QUE SE ESTABILICE LA SE?AL
   
    BTFSS   PORTB,5 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO ENCENDIDO; SALE SI SE HA PULSADO UNA TECLA
    INCF    TECLA,1 ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    INCF    CONTEO,1  ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    NOP          ;PONE UN CICLO DE RETARDO PARA QUE SE ESTABILICE LA SE?AL
   
    BTFSS   PORTB,6 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO ENCENDIDO ; SALE SI SE HA PULSADO UNA TECLA
    INCF TECLA,1;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    INCF    CONTEO,1  ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    NOP          ;PONE UN CICLO DE RETARDO PARA QUE SE ESTABILICE LA SE?AL
     
    BTFSS   PORTB,7 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO ENCENDIDO; SALE SI SE HA PULSADO UNA TECLA
    INCF TECLA,1;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    INCF    CONTEO,1  ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    NOP
    
    MOVLW   D'17'       ;CARGA W CON TECLA=TECLA + 1
    SUBWF   TECLA,W       ;compara si el valor de la tecla con W es 0
    BTFSC   STATUS,Z       ;REGRESA A CHEQUEO DE TECLAS
    GOTO    CHEQUEO_TECLA
   
    SIGUIENTE_COLUM:
    BSF       STATUS,C; ENCIENDE EL CARRY PARA PONER EN 1 LA FILA RECORRIDA
    RLF       PORTB,1; REALIZA CORRIMIENTO A LA IZQUIERA, PONER A CERO LA SIFUIENTE FILA
    RLF       PORTC,1
    GOTO    CHECK_COL; ESCANEA LA SIGUIENTE COLUMNA
   
    ENCENDIDO:
    ;RUTINAS QUE ESPERAN A QUE SE DEJE PRESIONAR LA TECLA ES PARA EVITAR ECO
    ESPERA1
    BTFSS PORTB,4; SI NO SE SUELTA LA TECLA DE LA COLUMNA1
    GOTO ESPERA1; VUELVE ESPERAR
    ESPERA2
    BTFSS PORTB,5; SI NO SE SUELTA LA TECLA DE LA COLUMNA 2
    GOTO ESPERA2; VUELVE ESPERAR
    ESPERA3
    BTFSS PORTB,6; SI NO SE SUELTA LA TECLA DE LA COLUMNA 3
    GOTO ESPERA3;VUELVE ESPERAR
    ESPERA4
    BTFSS PORTB,7; SI NO SE SUELTA LA TECLA DE LA COLUMNA 4
    GOTO ESPERA4;VUELVE ESPERAR
   
    ;UNCA VEZ QUE DEJO DE PRESIONAR LA TECLA
    MOVF TECLA,W ;PONER EN W EL VALOR DE TECLA
    CALL TABLA ;LLAMO A TABLA
    MOVWF PORTD; MANDO TABLA A D
    MOVF CONTEO,W;
    CALL COMANDO; MANOD DATOS AL DISPLAY
    MOVWF PORTC
    INCF CARACTER,1;INCREMENTO CONTADOR
   
    ;VERIFICA SI SE HA LLENADO LA LNEA DE 1 CARACTERES
    MOVLW D'16';NUMERO DE CARACTERES
    XORWF CARACTER,W;REALIZA D'16' XOR CARACTER
    BTFSC STATUS,Z;VERIFICA EL ESTADO DE Z
   
    ;VERIFICA SI SE HA LLENADO LA LINEA DE 2 CARACTERES
    MOVLW D'32'
    XORWF CARACTER,W
    BTFSC STATUS,Z
    RETURN
    GOTO CHEQUEO_TECLA
    END

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:multiplexacion con el pic 16f877a
« Respuesta #1 en: 09 de Mayo de 2018, 21:30:36 »
Bueno, veo unos cuantos problemas... pero deberías adjuntar un esquema, para entender que es lo que hace cada pin ya que no se que es lo que debe activarse.

Y explicate mejor como es que queres que funcione... Por ejemplo

Si presiono 4 y 8 en ese orden, y tenes 4 display 7 segmentos puede aparecer de estas formas:

- - 4 8   (Donde - serian los displays apagados) En estos 2 casos se va corriendo el valor

0 0 4 8

4 8 - -  (Este es mas simple y no va corriendose)

4 8 0 0 


Desconectado Zhunio

  • PIC10
  • *
  • Mensajes: 5
Re:multiplexacion con el pic 16f877a
« Respuesta #2 en: 10 de Mayo de 2018, 00:02:07 »
No me deja subir el archivo de simulacion, pero le subo un pdf con la imagen.

El Puerto B es el del teclado, el Puerto D es a los display, Puerto C es el que controla la multiplexacion de los display.
En el funcionamiento seria asi:
Presiono cualquier tecla y se debe colocar en primer display, si presiono cualquier otra tecla se debe colocar en el segundo diplay, si presiono cualquier otra tecla se debe colocar en el tercer diplay,si presiono cualquier otra tecla se debe colocar en el cuarto diplay, si presiono cualquier otra tecla se debe colocar en el primer diplay, los demas dispay debe mantener la visualizacion del numero que presiono antes.
Algo asi;

(- - - -) display apagados.

Presiono la tecla 1:

(1 - - -)
Presiono la tecla 8:

(1 8 - -)

Presiono la tecla 6:

(1 8 6 -)

Presiono la tecla 4:

(1 8 6 4)

Presiono la tecla 9

(9 8 6 4)

Asi sucesivamente


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:multiplexacion con el pic 16f877a
« Respuesta #3 en: 10 de Mayo de 2018, 11:41:28 »
Como te comentaba hay varios problemas, por ejemplo estas modificando tu "CONTEO" pero lo ubicaste sobre la direccion del registro PIR1 lo cual en realidad estas modificando PIR1...

Este no es un error, pero no se que sentido tiene cambiarle el nombre al PCL definido en el .inc, por CONTADOR, dejale los nombres a los registros que vos uses. O usar D'14' en ves de B'1110' que es mas entendible o 0xFE en hexa que tambien es mas entendible que 14. Los NOP en la tabla no tienen sentido, podes usar un indice que comience desde 0. los NOP para que se estabilice la señal tampoco
Usa las definiciones que te da el .inc, por ejemplo INCF CONTADOR, F   usar el F en ves de 1, o W en ves de 0, es mas simple de recordar, PCL y no CONTADOR, etc..

Pero el error mas grande es querer hacer todo junto.. y me refiero a todo.. multiplexar, leer teclado,etc
Al hacer esto y encima esperar que se suelte la tecla lo estas haciendo mal, ya que no vas a poder multiplexar asi. Si tenes presionada la tecla te vas a encontrar conque no muestra mas nada el display de forma correcta.

Te propongo realizar algo parecido pero un poco mas separado.

Código: ASM
  1. PRINCIPAL:
  2.         CALL     LEER_TECLADO
  3.         CALL     CARGAR_REGISTROS
  4.         CALL     MOSTRAR_DISPLAY
  5.         CALL     DELAY
  6.         GOTO    PRINCIPAL

Voy a explicar que va a hacer cada una de las funciones.

LEER_TECLADO:
   Esta subrutina debe:
   - Leer el teclado, es decir el multiplexado, sin demoras entre medio, pasar y leer, apenas detecta un boton presionado sale y carga el boton presionado en algun registro, supongamos TECLA.
  - Si se presiona algo debera devolver de 0x00 a 0x0F que son las teclas. Si no se presiona nada un valor ilogico como 0xFF

CARGAR_REGISTROS:
   Esta subrutina va a tomar el valor de TECLA (producido en la etapa anterior) y verifica que no sea 0xFF, esto es para indicar que si debe hacer algo o no, si detecta un 0xFF sale sin hacer nada. Tambien esta subrutina debe verificar que la tecla presionada no sea la misma que la anterior!
Si detecta un numero procede a cargar el registro que corresponde, propongo tener 4 registros, uno para cada display. De esa forma poder cargar el valor a donde corresponde, tal ves aca sea bueno usar el FSR.

MOSTRAR_DISPLAY:
   Esta subrutina se encarga de tomar los registros generados por CARGAR_REGISTROS, es decir los 4 numeros y mostrarlos, pero OJO, no mostrarlos todos, en cada paso muestra 1 de ellos. Es decir, la primera ves que pasa muestra el digito uno y sale, al pasar de vuelta, desactiva el digito 1 y activa el digito 2, y asi hasta el 4 y volver a comenzar. Tambien si detecta algun valor mayor a 0xF que no muestre nada.

DELAY:
 Este es el secreto del programa, poner un delay que afecte a todos por igual, como el teclado no es prioritario ni necesita  que se ejecute a gran velocidad, ni tampoco las otras subrutinas entonces  lo unico que importa es el tiempo del multiplexado, aca pones el delay del multiplexado.

¿Cual es la ventaja de hacer esto como te lo digo?
- Independencia de las subrutinas
- Enfocadas en un solo punto.
- Facil mantenimiento y mejora la legibilidad.

Ahora lo del teclado va  estar en lo del teclado. No funciona la rutina del teclado? no hay problema con lo demas, todo lo demas va a funcionar. Y sabes que tu problema esta contenido en un solo lugar.

Otra cosa... supongamos que tenemos 4 regitros DIGITO1,DIGITO2,DIGITO3 DIGITO4. Esos registros carga la subrutina CARGAR_REGISTROS. Pero todavia no la hice a esa subrutina ni tampoco la del teclado, pero quiero probar mi subrutina MOSTRAR_DISPLAY la cual usa esos 4 registros. entonces puedo modificar PRINCIPAL para que quede asi:


Código: ASM
  1. PRINCIPAL:
  2.         ;CALL     LEER_TECLADO
  3.         ;CALL     CARGAR_REGISTROS
  4.         MOVLW  0x01
  5.         MOVWF  DIGITO1
  6.         MOVLW  0x02
  7.         MOVWF  DIGITO2
  8.         MOVLW  0x03
  9.         MOVWF  DIGITO3
  10.         MOVLW  0x04
  11.         MOVWF  DIGITO4
  12.         CALL     MOSTRAR_DISPLAY
  13.         CALL     DELAY
  14.         GOTO    PRINCIPAL


Y ya con ese codigo puedo probar la subrutina de multiplexacion, en ves de esperar que la subrutina sea quien cargue los valores, procedi a darle valores fijos para ver como funcionaba. Entonces puedo probar subrutina a subrutina...

Suponete que pobaste MOSTRAR_DISPLAY y funciona perfectamente con todos los valores.
Ahora es tiempo de hacer CARGAR_REGISTROS. Supongamos que escribiste la misma, recorda que esta subrutina tomaba lo que le da la subrutina de teclado y que depositaba en el registro TECLA. Entonces podemos probar que pasa si se presiona esta tecla podemos hacer:

Código: ASM
  1. PRINCIPAL:
  2.         ;CALL     LEER_TECLADO
  3.         MOVLW  0x06
  4.         MOVWF  TECLA
  5.         CALL     CARGAR_REGISTROS
  6.         CALL     MOSTRAR_DISPLAY
  7.         CALL     DELAY
  8.         GOTO    PRINCIPAL

Ahora en ves de esperar que LEER_TECLADO nos devuelva la tecla, procedemos a darle una tecla fija, y ver como reacciona CARGAR_REGISTROS.

Con esto logras una "independencia", cada subrutina posee registros de entrada y de salida.
LEER_TECLADO: Entrada: PORTx  Salida: TECLA
CARGAR_REGISTROS: Entrada: TECLA , Salida: DIGITO1,DIGITO2,DIGITO3,DIGITO4
MOSTRAR_DISPLAY: Entrada: DIGITO1,DIGITO2,DIGITO3,DIGITO4, Salida:PORTx

Espero que se entienda.

Desconectado Zhunio

  • PIC10
  • *
  • Mensajes: 5
Re:multiplexacion con el pic 16f877a
« Respuesta #4 en: 14 de Mayo de 2018, 20:51:34 »
Disculpe otra vez por molestar, hice como usted lo sugerio, tampoco me sale, o algo este haciendo mal.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:multiplexacion con el pic 16f877a
« Respuesta #5 en: 14 de Mayo de 2018, 21:37:00 »
Pone el codigo de lo que hiciste, para ver cual es el problema.

Desconectado Zhunio

  • PIC10
  • *
  • Mensajes: 5
Re:multiplexacion con el pic 16f877a
« Respuesta #6 en: 14 de Mayo de 2018, 21:46:22 »
    list p=16f877A
    #include <p16f877A.inc>
    ERRORLEVEL-302
    __CONFIG H'3D3A'

   
   
    TECLA   EQU   0x30 ;variable que va contando el numero de teclas
    REG1    EQU 0x31 ; RETARDO
    REG2    EQU 0x32 ; RETARDO
    CARACTER EQU 0x33; CONTADOR DE CARACTER
    CONTEO EQU 0X34;
   
    ORG 0x00
    GOTO INICIO
    ORG 0x05   
     
    TABLA
    ADDWF  PCL,1
    NOP ; UTILIZO COMO INSTRUCCION DENTRO DE BUCLES PARA GENERAR RETARDOS DE TIEMPSO
    RETLW  B'01111001';1
    RETLW  B'00100100';2
    RETLW  B'00110000';3
    RETLW  B'00001000';A
    RETLW  B'00011001';4
    RETLW  B'00010010';5
    RETLW  B'00000011';6
    RETLW  B'00000011';B
    RETLW  B'01111000';7
    RETLW  B'00000000';8
    RETLW  B'00011000';9
    RETLW  B'01000110';C
    RETLW  B'00001110';F
    RETLW  B'01000000';0
    RETLW  B'00100001';D 
    RETLW  B'00000110';E
   
    INICIO:
    CLRF PORTB ;LIMPIA PORTB
    CLRF PORTC ;LIMPIA PORTB
    CLRF PORTD ;LIMPIA PORTB
    BSF STATUS,RP0 ; ACEDO AL BANCO 1
    MOVLW 0xF0 ; PORTB0-3 SALIDAS
    MOVWF TRISB ; PORTB4-7 ENTRADAS
    BCF OPTION_REG,7 ; HABILITA RESISTENCIA DE POLARIZACION EN ENTRADAS
    CLRF TRISD  ; PUERTO D COMO SALIDA AL DISPLAY
    MOVLW B'11110000' ;DECLARANDO SALIDA LOR PUERTO DE 0 A 3
    MOVWF TRISC ;PUERDO C COMO SALIDA
    BCF STATUS,RP0 ;REGRESO AL BANCO 0
    CLRF PORTB ;LIMPIA PORTB
    CLRF PORTC ;LIMPIA PORTB
    CLRF PORTD ;LIMPIA PORTB
    MOVLW B'01000000'; COMIENZA CON 0 LOS DISPLAY
    MOVWF PORTD
   
    PRINCIPAL:
    CALL CHEQUEO_TECLA; INTENTAR VERIFICAR EL TECLADO
    CALL VER_DISPLAY; COLOCA LA TECLA AL DISPLAY
    CALL MOSTRAR_DISPLAY; MUESTRA EL VALOR AL DISPLAY
    CALL RETARDO_1MS;RETARDO
    GOTO PRINCIPAL
    ;--------------------------------------------------
    ;--------------------------------------------------   
    VER_DISPLAY:
    CALL TABLA ;LLAMO A TABLA
    MOVWF PORTD; MANDO TABLA A D
    RETURN
    ;--------------------------------------------------
    ;--------------------------------------------------
    MOSTRAR_DISPLAY:
    CALL BARRIDO
    MOVFW TECLA ; PASA EL VALOR DE TECLA A W
    SUBLW 0x01 ; RESTA EL VALR DE W
    BTFSC STATUS,Z ; SI ES CERO ENTRA A REGISTRO1
    CALL REGISTRO1
 
   
    MOVFW TECLA
    SUBLW 0x02
    BTFSC STATUS,Z
    CALL REGISTRO2
   
    MOVFW TECLA
    SUBLW 0x03
    BTFSC STATUS,Z
    CALL REGISTRO3
   
    MOVFW TECLA
    SUBLW 0x04
    BTFSC STATUS,Z
    CALL REGISTRO4
       
    MOVFW PCL
    SUBLW 0x04
    BTFSC STATUS,Z
    CLRF PCL
    RETURN   
    ;--------------------------------------------------
    ;--------------------------------------------------
    REGISTRO1:
    ADDWF  PCL,1
    CALL RETARDO_1MS
    RETLW  B'00001110';1
    RETLW  B'00001101';2
    RETLW  B'00001011';2
    RETLW  B'00000111';2       
    RETURN
    REGISTRO2:
    ADDWF  PCL,1
    CALL RETARDO_1MS
    RETLW  B'00001110';1
    RETLW  B'00001101';2
    RETLW  B'00001011';2
    RETLW  B'00000111';2
    RETURN
    REGISTRO3:
    ADDWF  PCL,1
    CALL RETARDO_1MS
    RETLW  B'00001110';1
    RETLW  B'00001101';2
    RETLW  B'00001011';2
    RETLW  B'00000111';2
    RETURN
    REGISTRO4:
    ADDWF  PCL,1
    CALL RETARDO_1MS
    RETLW  B'00001110';1
    RETLW  B'00001101';2
    RETLW  B'00001011';2
    RETLW  B'00000111';2
    RETURN
    ;--------------------------------------------------
    ;--------------------------------------------------
    BARRIDO:
    BSF PORTC,0
    CALL RETARDO_1MS
    BCF PORTC,0
    BSF PORTC,1
    CALL RETARDO_1MS
    BCF PORTC,1
    BSF PORTC,2
    CALL RETARDO_1MS
    BCF PORTC,2
    BSF PORTC,3
    CALL RETARDO_1MS
    BCF PORTC,3
    RETURN 
    ;--------------------------------------------------
    ;--------------------------------------------------
    ;Escaneo del teclado
    CHEQUEO_TECLA:
    CLRF TECLA; BORRA EL CONTENIDO DE TECLA
    INCF TECLA,F;INICIALIZA TECLA
    MOVLW B'11111110'; PONE A 0 LA PRIMERA FILA
    MOVWF PORTB
    CALL RETARDO_1MS
    CALL BARRIDO
   
    CHECK_COL:
    TECLA_COLUMNA1:
    BTFSS   PORTB,4 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO TECL_GUARADVALOR ; SALE SI SE HA PULSADO UNA TECLA
    INCF    TECLA,F  ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    CALL RETARDO_1MS          ;PONE UN CICLO DE RETARDO PARA QUE SE ESTABILICE LA SE?AL
    TECLA_COLUMNA2:
    BTFSS   PORTB,5 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO TECL_GUARADVALOR; SALE SI SE HA PULSADO UNA TECLA
    INCF    TECLA,F ;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    CALL RETARDO_1MS          ;PONE UN CICLO DE RETARDO PARA QUE SE ESTABILICE LA SE?AL
    TECLA_COLUMNA3:
    BTFSS   PORTB,6 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO TECL_GUARADVALOR; SALE SI SE HA PULSADO UNA TECLA
    INCF TECLA,F;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    CALL RETARDO_1MS          ;PONE UN CICLO DE RETARDO PARA QUE SE ESTABILICE LA SE?AL
    TECLA_COLUMNA4:     
    BTFSS   PORTB,7 ;CHEQUEA LA PRIMERA COLUMNA BUSCANDO 0
    GOTO TECL_GUARADVALOR; SALE SI SE HA PULSADO UNA TECLA
    INCF TECLA,F;CASO CONTRARIO, INCREMENTA NUMERO DE TECLA
    CALL RETARDO_1MS
     
    ULTIMA_TECLA:
    MOVLW   D'17'       ;CARGA W CON TECLA=TECLA + 1
    SUBWF   TECLA,W       ;compara si el valor de la tecla con W es 0
    BTFSC   STATUS,Z       ;REGRESA A CHEQUEO DE TECLAS
    GOTO CHEQUEO_TECLA
   
    SIGUIENTE_COLUM:
    BSF       STATUS,C; ENCIENDE EL CARRY PARA PONER EN 1 LA FILA RECORRIDA
    RLF       PORTB,1; REALIZA CORRIMIENTO A LA IZQUIERA, PONER A CERO LA SIFUIENTE FILA
    GOTO CHECK_COL
    BCF STATUS,C ; POSICION C=0, INDICANDO QUE NO HA PULSADO
    GOTO TECL_FINTECLADOLEE
    TECL_GUARADVALOR: ;EL QUE GUARDA LA TECLA SELECCIONADA
    MOVF TECLA,W
    BSF STATUS,C ; CINI HAY TECKA PULSADA, PONE C=1
    TECL_FINTECLADOLEE:
    RETURN
   
    RETARDO_1MS:
    MOVLW D'1'
    MOVWF REG2
    R1MS_BUCLEEXTERNO
    MOVLW D'249'
    MOVWF REG1
    R1MS_BUCLEINTERNO
    DECFSZ REG1,F
    GOTO R1MS_BUCLEINTERNO
    DECFSZ REG2,F
    GOTO R1MS_BUCLEINTERNO
    RETURN
    END

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:multiplexacion con el pic 16f877a
« Respuesta #7 en: 14 de Mayo de 2018, 22:48:37 »
No seguiste nada de lo que te dije que hicieras, si hiciste parte... pero no todo... Este es el codigo solo falta hacer la multiplexacion del teclado, cargar los valores correctos en la tabla y definir un valor delay, suponete 5ms.

Código: ASM
  1. ;Registros de Chequear teclado
  2. TECLA   EQU 0x28 ;variable que va contando el numero de tecla
  3.    
  4. ; Registro para CARGAR_REGISTROS
  5. NTECLA  EQU 0x29
  6. TECLA_ANTERIOR  EQU 0x30
  7.  
  8. ; Registros temporales usados para delays y otras cosas mas
  9. TMP1    EQU 0x31 ; RETARDO
  10. TMP2    EQU 0x32 ; RETARDO
  11.  
  12. ; Registros de MOSTRAR_DISPLAY
  13. DIGITO1 EQU 0x33 ; 1er digito
  14. DIGITO2 EQU 0x34 ; 2do digito
  15. DIGITO3 EQU 0x35 ; 3er digito
  16. DIGITO4 EQU 0x36 ; 4to digito
  17. NDIGITO EQU 0x37 ; Numero de digito a mostrar
  18.  
  19.  
  20. ;Comienzo de programa
  21.    
  22.     ;Vector de reset
  23.     ORG 0x00
  24.     GOTO INICIO
  25.     ;Vector de interrupcion
  26.     ORG 0x04
  27.     RETURN
  28.      
  29. TABLA:
  30.     ADDWF  PCL, F
  31.     RETLW  B'00000000'; Todo apagado
  32.     RETLW  B'01111001';1
  33.     RETLW  B'00100100';2
  34.     RETLW  B'00110000';3
  35.     RETLW  B'00001000';A
  36.     RETLW  B'00011001';4
  37.     RETLW  B'00010010';5
  38.     RETLW  B'00000011';6
  39.     RETLW  B'00000011';B
  40.     RETLW  B'01111000';7
  41.     RETLW  B'00000000';8
  42.     RETLW  B'00011000';9
  43.     RETLW  B'01000110';C
  44.     RETLW  B'00001110';F
  45.     RETLW  B'01000000';0
  46.     RETLW  B'00100001';D  
  47.     RETLW  B'00000110';E
  48.    
  49. INICIO:
  50.     CLRF PORTB ;LIMPIA PORTB
  51.     CLRF PORTC ;LIMPIA PORTB
  52.     CLRF PORTD ;LIMPIA PORTB
  53.     BSF STATUS,RP0 ; ACEDO AL BANCO 1
  54.     MOVLW 0xF0 ; PORTB0-3 SALIDAS
  55.     MOVWF TRISB ; PORTB4-7 ENTRADAS
  56.     BCF OPTION_REG,7 ; HABILITA RESISTENCIA DE POLARIZACION EN ENTRADAS
  57.     CLRF TRISD  ; PUERTO D COMO SALIDA AL DISPLAY
  58.     MOVLW B'11110000' ;DECLARANDO SALIDA LOR PUERTO DE 0 A 3
  59.     MOVWF TRISC ;PUERDO C COMO SALIDA
  60.     BCF STATUS,RP0 ;REGRESO AL BANCO 0
  61.     CLRF PORTB ;LIMPIA PORTB
  62.     CLRF PORTC ;LIMPIA PORTB
  63.     CLRF PORTD ;LIMPIA PORTB
  64.     MOVLW B'01000000'; COMIENZA CON 0 LOS DISPLAY
  65.     MOVWF PORTD
  66.  
  67.     ;Preparacion de los registros
  68.  
  69.     CLRF DIGITO1
  70.     CLRF DIGITO2
  71.     CLRF DIGITO3
  72.     CLRF DIGITO4
  73.     CLRF NDIGITO
  74.     CLRF NTECLA
  75.     CLRF TECLA    
  76.    
  77. PRINCIPAL:
  78.     CALL CHEQUEO_TECLA      ; Verifica el teclado y devuelve un valor de 0x0 a 0xF en caso de presionado, o otro numero en caso de que no hay nada presionado
  79.     CALL CARGAR_REGISTROS   ; Carga los registros para que MOSTRAR_DISPLAY muestre lo que debe
  80.     CALL MOSTRAR_DISPLAY    ; MUESTRA EL VALOR AL DISPLAY
  81.     CALL RETARDO_5MS        ;RETARDO
  82.     GOTO PRINCIPAL
  83.    
  84. CARGAR_REGISTROS:
  85.     MOVF    TECLA, W
  86.     XORWF   TECLA_ANTERIOR, W   ; Reviso si la tecla presionada es la misma que la anterior ves que entro
  87.     BTFSC   STATUS, Z
  88.     RETURN                      ; Es la misma, entonces salgo, no la tengo en cuenta.
  89.     MOVF    TECLA, W
  90.     ANDLW   0xF                 ; ¿ No hay nada presionado ?, revisar que el numero sea
  91.     BTFSC   STATUS, Z           ; Tenemos 16 teclas que se pueden representar como 0x0 a 0xF, cualquier otro valor significa que no se presiono.
  92.     RETURN                      ; En caso de no ser un valor valido salgo
  93.     MOVLW   DIGITO1             ; En caso de haber algo presionado, debo guardarlo
  94.     ADDWF   NTECLA, W           ; NTECLA me va a dar la posicion, y DIGITO1 la posicion inicial, es decir voy a guardar en DIGITO1 + NTECLA
  95.     MOVWF   FSR
  96.     MOVF    TECLA, W            ;
  97.     MOVWF   TECLA_ANTERIOR      ; Guardo la tecla, para ser tenida en cuenta la proxima ves que entre aca
  98.     MOVWF   INDF                ; incremento en 1, para distinguirlo de cuando este todo apagado
  99.     INCF    INDF, F
  100.     RETURN
  101.    
  102. MOSTRAR_DISPLAY:
  103.     MOVLW   DIGITO1         ;La direccion de Digito1 (0x33)
  104.     ADDWF   NDIGITO, W      ;Le agrego el numero de digito
  105.     MOVWF   FSR
  106.     MOVF    INDF, W         ; Obtengo el valor de (0x33 + N de digito)
  107.     CALL    TABLA           ; Ya poseeo el digito, ahora con esto consigo el valor a poner en el display
  108.     MOVWF   PORTD           ; Pongo el valor en el Puerto
  109.     RLF     PORTC, W        ; el PORTC podemos hacer que tenga un 1, y lo vamos rotando asi queda 0001 luego 0010 lueg 0100 y asi
  110.     ANDLW   0xF             ; Revizamos si paso de 0000 1000 a 0001 0000
  111.     BTFSC   STATUS, Z       ; En caso de serlo, ponemos a 1 el Carry para comenzar de nuevo
  112.     BSF     STATUS, C       ; Esto tiene en cuenta que las RC4 a RC7 sean entradas
  113.     RLF     PORTC, F        ; Rotamos el PORTC
  114.     INCF    NDIGITO, F      ; Incrementamos nuestro numero de digito a mostrar
  115.     MOVF    NDIGITO, W      ; Cuando nos pasemos, es decir mostyramos los digitos 1,2,3 y4 (numeros 0,1,2 y 3 respectivamente)
  116.     XORLW   0x4             ; Reseteamos asi vuelve a mostrar del primero
  117.     BTFSC   STATUS, Z
  118.     CLRF    NDIGITO
  119.     RETURN

La funcion de MOSTRAR_DISPLAY ya la probe... No probe la de cargar registros.
Si tenes dudas del codigo pregunta
« Última modificación: 14 de Mayo de 2018, 22:55:38 por KILLERJC »

Desconectado Zhunio

  • PIC10
  • *
  • Mensajes: 5
Re:multiplexacion con el pic 16f877a
« Respuesta #8 en: 15 de Mayo de 2018, 00:41:21 »
En esta parte:

MOVLW   DIGITO1             ; En caso de haber algo presionado, debo guardarlo
ADDWF   NTECLA, W           ; NTECLA me va a dar la posicion, y DIGITO1 la posicion inicial, es decir voy a guardar en DIGITO1 + NTECLA
MOVWF   FSR

El FSR que es lo que hace.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:multiplexacion con el pic 16f877a
« Respuesta #9 en: 15 de Mayo de 2018, 08:49:38 »
El registro FSR y el registro INDF se usan juntos...

acceder al registro INDF es lo mismo que acceder a lo que apunta el registro FSR... Un ejemplo concreto seria.. en el PIC16F877A tenes que el PORTB esta en la direccion de memoria 0x06
Si cargas el registro FSR con 0x06. Y luego lees el registro INDF lo que estarias leyendo es el registro PORTB.
Al igual que si escribo en INDF mientras el registro FSR tiene el valor 0x06, estaria escribiendo el PORTB.

Entonces resumiendo:
- en FSR cargo la direccion del registro que quiero modificar.
- con INDF accedo al registro apuntado por el FSR

En el ejemplo anterior supuse que accediamos al PORTB pero fue un ejemplo tonto para ver que hace, ya que no seria un buen provecho hacerlo, ya que es mas facil directamente acceder al PORTB. Pero en el caso del codigo este queremos que funcione de otra forma distinta.

Código: ASM
  1. DIGITO1 EQU 0x33 ; 1er digito
  2. DIGITO2 EQU 0x34 ; 2do digito
  3. DIGITO3 EQU 0x35 ; 3er digito
  4. DIGITO4 EQU 0x36 ; 4to digito

Nuestro primero registro se encuentra en 0x33 y tengo ademas un registro (NTECLA o NDIGITO) que va a tener los valores de 0,1,2 y 3 a medida que vaya pasando para indicarme que display/tecla estoy encendiendo o intentando llenar. Entonces aprovecho el FSR

La primer instruccion

Citar
MOVLW   DIGITO1             

Observaras que uso un MOVLW, por que DIGITO1 es igual (EQUal) a 0x33 segun nuestra declaracion.
Aca pongo W = 0x33

Citar
ADDWF   NTECLA, W

Quiero saber que tecla/digito tengo que llenar/mostrar, si no hubiera usado el FSR deberia haber realizado el codigo para todos los digitos en una tabla en cada una de las subrutinas.
En este caso la primera ves que se toque una tecla va a suceder que W va a ser 0x33 + 0x0, por lo tanto queda en 0x33, eso cargo al FSR y por ende actuó sobre DIGITO1.
Yo tuve un error en el codigo y me comi un INCF de NTECLA al final y tambien su limpieza, como tiene NDIGITO.
Entonces para la proxima ves que entre NTECLA deberia tener el valor 1, ahora si pasa por ese codigo W va a ser 0x33 + 0x1 = 0x34, y esto apunta a DIGITO2.
Y asi hasta llegar a DIGITO4 (0x33 + 0x3 = 0x36 ) al incrementar una ves mas NTECLA quedaria en 0x4, eso lo debemos detectar y proceder a poner a NTECLA en 0x0.

Observaras que para que esto funcione, necesitas que DIGITO1 a DIGITO4 esten seguidos en memoria ( 0x33,0x34,0x35,0x36 )

Creo que esto arreglaria el error que tuve, actualizo para agregar el incremento de NTECLA y su limite:

Código: ASM
  1. CARGAR_REGISTROS:
  2.     MOVF    TECLA, W
  3.     XORWF   TECLA_ANTERIOR, W   ; Reviso si la tecla presionada es la misma que la anterior ves que entro
  4.     BTFSC   STATUS, Z
  5.     RETURN                      ; Es la misma, entonces salgo, no la tengo en cuenta.
  6.     MOVF    TECLA, W
  7.     ANDLW   0xF                 ; ¿ No hay nada presionado ?, revisar que el numero sea
  8.     BTFSC   STATUS, Z           ; Tenemos 16 teclas que se pueden representar como 0x0 a 0xF, cualquier otro valor significa que no se presiono.
  9.     RETURN                      ; En caso de no ser un valor valido salgo
  10.     MOVLW   DIGITO1             ; En caso de haber algo presionado, debo guardarlo
  11.     ADDWF   NTECLA, W           ; NTECLA me va a dar la posicion, y DIGITO1 la posicion inicial, es decir voy a guardar en DIGITO1 + NTECLA
  12.     MOVWF   FSR
  13.     MOVF    TECLA, W            ;
  14.     MOVWF   TECLA_ANTERIOR      ; Guardo la tecla, para ser tenida en cuenta la proxima ves que entre aca
  15.     MOVWF   INDF                ; incremento en 1, para distinguirlo de cuando este todo apagado
  16.     INCF    INDF, F
  17.     INCF    NTECLA, F
  18.     MOVLW   0x04
  19.     XORWF   NTECLA, W
  20.     BTFSC   STATUS, Z
  21.     CLRF    NTECLA
  22.     RETURN

Otra de las ventajas del FSR es que puede direccionar en los 4 bancos, el FSR posee 8 bits, mas 1 que se encuentra en STATUS. Entonces si por ejemplo si accedes a un registro siempre del banco1 suponete el TRISB y no queres estar cambiando de banco para cambiar el PORTB, te quedas en el banco0 y cargas en el FSR la direccion del TRISB, esto te permitiria manejarlo desde el banco0. Y es una "ganancia" si es que tenes que modificarlo seguido.

Otro ejemplo... supongamos que queres poner a 0 todos los registros que definiste, es decir desde TECLA hasta NDIGITO, una de las formas es poner CLRF de todos ellos. Otra es cargar la direccion de TECLA en el FSR, un CLRF al INDF, aumentar en 1 el FSR, revisar si nos pasamos de NDIGITO, y repetir. Entonces si tenes Muuuuchos registros, con unas cuantas instrucciones terminas haciendo lo mismo.