Autor Tema: BIN a BCD-MULTIPLEXADO-USART(comunicación serial)-Uso de retardos e interrup.  (Leído 3235 veces)

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

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Muy buenas gente, qué tal? Bueno voy al grano, realice un programa en pic 16f88 con el cual mando datos por 4 llaves y las envía a dos displays 7 segmentos el número de las llaves pero el ASCII de cada uno, a su vez manda el dato por el TX para visualizarlo en la pc correcto? Si desde la pc yo le envío un dato los displays se pondran en 0 y parpadearan a 0.5 seg durante 5 seg, luego que termina esa "animación" vuelve al número que estaba cuando se recibió cualquier dato de la pc. Bueno primero que nada cuando lo simulo en proteus hace cualquier cosa, le pregunte a un profesor y me sigue haciendo cualquier cosa, se queda trabado o como en un loop en la primera parte de transformar de bin a bcd. En el proteus uso el pic16f88, un 4511 para los displays, 7seg cátodo común, el DIPSW_4 que serían las 4 llaves pull down. Les pondría una foto del circuito pero cada vez que intento no la pone.
Les pongo el programa y si se puede me dan una manita?
Código: [Seleccionar]
;=====================================================================================
; ENCABEZADOS
;=====================================================================================
LIST P=16F88, R=DEC ;ESPECIFICACIONES DEL MICRO
#INCLUDE <P16F88.INC> ; INCLUSION DE ARCHIVOS Y REGISTROS

    __CONFIG _CONFIG1, _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _MCLR_OFF & _LVP_OFF & _INTRC_IO
    __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF



;=====================================================================================
; ETIQUETAS Y DECLARACION DE VARIABLES
; SE DEBE PONER EN CBLOCK EL INICIO DE LA MEMORIA RAM
; SEGUN EL MICROCONTROLADOR A USAR
;=====================================================================================
;SON 80 BYTES, BANCO 0
;VA DESDE LA POSICION DE MEMORIA H'20' HASTA H'6F'
CBLOCK H'20' ;SE PUEDE ESCRIBIR EN OCTAL O'23' EN BINARIO B'101' Y EN ASCII 'A'
   BCD_Centenas
   BCD_Decenas
   BCD_Unidades
   CONTADOR
   DATO_A_ENVIAR
   R1
   R2
ENDC


#DEFINE     Display     PORTB
M       EQU .65
N       EQU .5


ORG 0x00
GOTO START
            ORG         0x04        ;vector de interrupciones
            GOTO        Inter
;CONFIGURACION
            BANKSEL PORTA ; SELECT BANK OF PORTA
CLRF PORTA ; INITIALIZE PORTA BY
BANKSEL OSCCON
MOVLW 0X60  ;RELOJ INTERNO 4MHZ
MOVWF OSCCON
BANKSEL ANSEL ; SELECT BANK OF ADCON1
MOVLW 0X00  ; CONFIGURE ALL PINS
MOVWF ANSEL ; AS DIGITAL INPUTS
            BSF     STATUS,RP0  ;PASO AL BANK 1
            CLRF    Display ;salida
            BCF     STATUS,RP0  ;PASO AL BANK 0
            BANKSEL PORTA
            MOVLW   B'11110000'
            MOVWF   PORTA
            MOVLW   B'00100100'
            MOVWF   PORTB
            BANKSEL TRISB
            MOVLW   B'00011000'
            MOVWF   TRISB
            CLRF    CONTADOR

START
            BANKSEL PORTA
            MOVF    PORTA,W
            MOVWF   DATO_A_ENVIAR
            CALL    BIN_a_BCD


;--------------------PASO A DE BIN A BCD------------------------------
BIN_a_BCD
clrf BCD_Centenas ; Carga los registros con el resultado inicial.
clrf BCD_Decenas ; En principio las centenas y decenas a cero.
movwf BCD_Unidades ; Se carga el número binario a convertir.
BCD_Resta10
movlw .10 ; A las unidades se les va restando 10 en cada
subwf BCD_Unidades,W ; pasada. (W)=(BCD_Unidades) -10.
btfss STATUS,C ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Unidades)>=10?
goto BIN_BCD_Fin ; No, es menor de 10. Se acabó.
BCD_IncrementaDecenas
movwf BCD_Unidades ; Recupera lo que queda por restar.
incf BCD_Decenas,F ; Incrementa las decenas y comprueba si ha llegado
movlw .10 ; a 10. Lo hace mediante una resta.
subwf BCD_Decenas,W ; (W)=(BCD_Decenas)-10).
btfss STATUS,C ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Decenas)>=10?
goto BCD_Resta10 ; No. Vuelve a dar otra pasada, restándole 10 a
BCD_IncrementaCentenas ; las unidades.
clrf BCD_Decenas ; Pone a cero las decenas
incf BCD_Centenas,F ; e incrementa las centenas.
goto BCD_Resta10 ; Otra pasada: Resta 10 al número a convertir.
BIN_BCD_Fin
swapf BCD_Decenas,W ; En el nibble alto de (W) también las decenas.
addwf BCD_Unidades,W ; En el nibble bajo de (W) las unidades.
return ; Vuelve al programa principal.

;-------------------------------------------------------------------

;------------------ENVIO POR PUERTO SERIE------------------------------------

;********************************************************************************************
;Tx_Dato: Transmite vía serie el dato presente en el reg. W

TX_DATO      BCF   PIR1,TXIF   ;Restaura el flag del transmisor
             MOVWF   TXREG      ;Almacena el byte a transmitir
             BSF   STATUS,RP0
Tx_Dato_Wait BTFSS   TXSTA,TRMT   ;Byte transmitido ??
             GOTO   Tx_Dato_Wait   ;No, esperar
             BCF   STATUS,RP0
             return         ;Si

;******************************************************************************************
;Tratamiento de la interrupción

Inter      BTFSS   PIR1,RCIF   ;Ha sido interrupción en la recepción ??
      retfie         ;No, falsa interrupción
      BCF   PIR1,RCIF   ;Si, restaurar el flag de interrupción
      MOVLW  .0       ;Lee el dato recibido
      MOVWF  Display      ;Lo saca por el display unidades
      MOVLW  .0
      MOVWF  Display    ;Lo saca por el display decenas
      BSF    PORTB,3
      BSF    PORTB,4
      CALL   Retardo_1ms
      BCF    PORTB,3
      BCF    PORTB,4

      CALL   TX_DATO      ;Lo retransmite a modo de eco
      retfie

;*******************************************************************************************
;Programa principal de transmision

STR

      movlw   b'11001111'
      movwf   OPTION_REG   ;Preescaler de 128 asociado al WDT

      movlw   b'00100100'
      movwf   TXSTA      ;TX en On, modo asíncrono con 8 bits y alta velocidad
      movlw   .25
      movwf   SPBRG      ;9600 baudios con Fosc=4MHz
      BSF   PIE1,RCIE   ;Habilita interrupción en la recepción
      BCF   STATUS,RP0   ;Selecciona banco 0

      movlw   b'10010000'
      movwf   RCSTA      ;USART en On, recepción contínua
      bsf   INTCON,PEIE   ;Activa interrupción de periféricos
      bsf   INTCON,GIE   ;Activa interrupciones

;Loop
;AQUI TU PROGRAMA
;para enviar datos sólo carga W con el valor a enviar y llama a la subrutina Tx_Dato
     MOVF    DATO_A_ENVIAR
     CALL    TX_DATO

;Lo recibido te lo guarda automáticamente en el registro RCREG y te lo muestra por puerto B

;goto   Loop

;-----------------------MULTIPLEXADOWACHOOOOOOO--------------
            BANKSEL PORTB

            MOVF    BCD_Unidades,W
            CALL    SIETE_SEGMENTOS
            MOVWF   Display
            BSF     PORTB,3
            CALL    Retardo_1ms
            BCF     PORTB,3

            MOVF    BCD_Decenas,W
            CALL    SIETE_SEGMENTOS
            MOVWF   Display
            BSF     PORTB,4
            CALL    Retardo_1ms
            BCF     PORTB,4
;----------(SI TUVIERA OTRO O MÁS DISPLAYS LOS PONGO A PARTIR DE ACA:)--------------
            MOVF    BCD_Centenas,W
            CALL    SIETE_SEGMENTOS
            MOVWF   Display
            BSF     PORTB,6
            CALL    Retardo_1ms
            BCF     PORTB,6
           
            RETURN


Retardo_1ms
            MOVLW   N
            MOVWF   R1
S2          MOVLW   M
            MOVWF   R2
S1          DECFSZ  R2
            GOTO    S1
            DECFSZ  R1
            GOTO    S2
            RETURN



SIETE_SEGMENTOS     ; TABLA

        ADDWF   PCL,F

        RETLW   B'11000000' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 0
        RETLW   B'11111001' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 1
        RETLW   B'10100100' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 2
        RETLW   B'10110000' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 3
        RETLW   B'10011001' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 4
        RETLW   B'10010010' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 5
        RETLW   B'10000011' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 6
        RETLW   B'11111000' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 7
        RETLW   B'10000000' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 8
        RETLW   B'10011000' ; EL CODIGO 7 SEGMENTOS PERTENECE AL NUMERO 9






    END

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: BIN a BCD-MULTIPLEXADO-USART(comunicación serial)-Uso de retardos e interrup.
« Respuesta #1 en: 16 de Abril de 2015, 13:12:43 »
Esto te lo tengo que decir:

Parece que has juntado algunos programas pero veo que no logras dar la tecla con la programacion. Y en 2/3 meses no le has dado importancia al mismo.
Hay muchos errores partiendo como que no sabes como funcionan las instrucciones, ni que se ejecutan secuencialmente. Me refiero a instrucciones tales como los CALL - RETURN

Y Es exactamente el mismo tema que preguntaste hace unos 3 meses atras. Uno de esos temas es este:
http://www.todopic.com.ar/foros/index.php?topic=44027
que luego lo seguiste en este:
http://www.todopic.com.ar/foros/index.php?topic=44056.msg365073#msg365073


Con respecto a tu codigo.
Viendo tu codigo observo que es un rejunte de varios codigos (que es perfectamente valido si sabes que estas haciendo)

Este es uno (UART):
http://www.todopic.com.ar/foros/index.php?topic=25655.0
BIN_BCD ( Hasta tiene centenas y vos solo necesitas decena como maximo )
http://www.todopic.com.ar/asm/rama/bin_bcd.asm%20.txt
Otra parte (mas sobre UART):
http://www.todopic.com.ar/foros/index.php?topic=25798.15
Otra mas (encabezados , fuses y configuracion) Este no molesta tanto:
http://www.forosdeelectronica.com/f24/configurar-clock-interno-16f88-asembler-13042/
Parece ser que otra parte de aca (Configuracion de Oscilador y registros ANSEL):
http://www.todopic.com.ar/foros/index.php?topic=28945.0

No se si realmente lo estas haciendo a proposito o no al copiarles hasta lso comentarios.
El ultimo programa que te habia pasado el cual habia realizado la mayoria, es decir tomar los datos de las llaves pasarlo a BCD, Envio, Multiplexado, y creo que habia dejado para que hicieras (voy a autoquotearme)

Citar
1- Limitar para cuando este la "animacion" de los ceros que la funcion "Mostrar display" y/o las demas funciones se ejecuten cuando este en marcha la animacion esa.
2- Hacer el programa para los ceros, eso es todo.

Que si no mal recuerdo tu profesor habia dicho que queria interrupciones pero en su video que paso se notaba que usaba delays. Y ademas tenia un error en su programa xD. Eso SI lo recuerdo.

De todas formas tus preguntas seran contestadas. Aunque no me voy a esmerar en explicaciones o codigos por obvias razones. Siguiendo el tema:

Como dije tu programa es una coleccion de programas puestos en ubicaciones al azar, tu programa principal no posee un loop infinito, estas usando un CALL ( el de BIN_a_BCD ) mal usado ya que este se ejecutaria 2 veces, no estas limitando la entrada a la tabla, ademas si seguis el hilo del programa vas a usar un RETURN cuando no existe nada en el stack (pila) del micro, esto ocurre en varios lados no solo 1, estas tambien usando una interrupcion para enviar un dato y que encima se queda esperando ahi hasta que se envia por completo, mas un intento de multiplexar el cual no funcionaria como queres. No estas salvando el contexto en las interrupciones, si no me crees que esta tan mal, intenta seguir el hilo de ejecucion instruccion a instruccion y vas a ver lo que hace tu programa.

Solucion:
Crear un un programa principal para que realize un loop infinito y llame a cada subrutina que quieras hacer.
Eliminar el multiplexado y envio de datos por UART desde la interrupcion.
Entender como funcionan / que hacen las instrucciones, como funciona el micro y como es el flujo del programa

PD: Esto no lo tenias en entregar en febrero ? Aca lo encontre:

Cita de: Fedextrem
Necesitaría un poco de ayuda con un programa que tengo que realizar para febrero (Para el colegio) de programación en lenguaje assemble
« Última modificación: 16 de Abril de 2015, 14:09:42 por KILLERJC »

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Re: BIN a BCD-MULTIPLEXADO-USART(comunicación serial)-Uso de retardos e interrup.
« Respuesta #2 en: 16 de Abril de 2015, 15:18:11 »
Tenes razón y tuve un quilombo en vacaciones con la materia y me pc que perdí todo pero acabo de encontrar en un pendrive el programa que vos me decís, lo estuve mirando para acordarme y si errores básicos, aparte que ahora estoy con arduino más problemas pero bueno en fin lo probé en Proteus y también tira el error como 10611 veces en el Proteus. El mensaje/error que me tira dice así: [PIC16 CORE] PC=0x0053. Stack underflow executing RETURN instruction.
Y este es el programa al que vos te referías:
Código: [Seleccionar]
;========================PLANTILLA 16F88=========================================
;_CONFIG1
;_CONFIG2
;Configuration Byte 1 Options
;_CP_ALL ;All Program Memory Protected
;_CP_OFF ;No Code Protection
;_CCP1_RB0 CCP1 function on RB0
;_CCP1_RB3 CCP1 function on RB3
;_DEBUG_OFF In-Circuit Debugger disabled, RB6 and RB7 are general purpose I/O pins
;_DEBUG;_ON In-Circuit Debugger enabled, RB6 and RB7 are dedicated to the debugger
;_WRT_PROTECT;_OFF ;No program memory write protection
;_WRT_PROTECT_256 ;First 256 program memory protected
;_WRT_PROTECT_2048 ;First 2048 program memory protected
;_WRT_PROTECT_ALL ;All of program memory protected
;_CPD_ON Data EE Memory Code Protection Enabled
;_CPD_OFF Data EE Memory Code Protection Disabled
;_LVP_ON Low-Voltage Programming Enable Enabled
;_LVP_OFF Low-Voltage Programming Enable Disabled
;_BODEN_ON Brown Out Reset Detec Enabled
;_BODEN_OFF Brown Out Reset Detec Disabled
;_MCLR_ON Pin function is MCLR
;_MCLR_OFF Pin function is digital Input, MCLR internally tied to VDD
;_PWRTE_OFF 72 msec. Time Up Delay Off
;_PWRTE_ON 72 msec. Time Up Delay On
;_WDT_ON Watchdog Timer Enable bit On
;_WDT_OFF Watchdog Timer Enable bit Off
;_EXTRC_CLKOUT
;_EXTRC_IO ;Habilita el Clock Externo -
;_INTRC_CLKOUT
;_INTRC_IO ;Habilita el Oscilador Interno - Pines RA6 y RA7 activados
;_EXTCLK
;_HS_OSC HS oscillator
;_XT_OSC XT oscillator
;_LP_OSC LP oscillator
;Configuration Byte 2 Options
;_IESO_ON Internal External Switchover mode enabled
;_IESO_OFF Internal External Switchover mode disabled
;_FCMEN_ON Fail-Safe Clock Monitor enabled
;_FCMEN_OFF Fail-Safe Clock Monitor disabled

;=====================================================================================
;
;=====================================================================================
; ENCABEZADOS
;=====================================================================================
list p=16f88, r=dec ;especificaciones del micro
#include <p16f88.inc> ; inclusion de archivos y registros

__CONFIG _CONFIG1, _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _MCLR_OFF & _LVP_OFF & _INTRC_IO
__CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF



;=====================================================================================
; ETIQUETAS y Declaracion de Variables
; se debe poner en CBLOCK el inicio de la memoria RAM
; segun el Microcontrolador a usar
;=====================================================================================
;son 80 BYTES, BANCO 0
;va desde la posicion de memoria H'20' hasta H'6F'
CBLOCK H'20' ;se puede escribir en octal O'23' en binario B'101' y en ASCII 'a'
d1
d2
d3
ENDC


;*** VARIABLES PARA TODOS LOS BANCOS ***
; son 16 bytes en Bank0/1/2/3
;*******************************************
CBLOCK H'70' ;van desde H'70' hasta H'7F'
;son Variables usadas en la subrutina INTERRUPCION
W_TEMP, STATUS_TEMP
FSR_TEMP, PCLATH_TEMP
DATO_A_ENVIAR
    UNIDADES
    DECENAS
    CONTADOR_DISPLAYS
    FLAG
    ;BCDH
    ;BCDL
ENDC



;BANCO 1 -- son 80 BYTES, desde H'A0' hasta H'EF'
;y luego vienen 16 Bytes compartidos desde H'F0' hasta H'FF'
CBLOCK H'A0'
ENDC

;BANCO 2 son 80 BYTES, desde H'110' hasta H'16F'
;y luego vienen 16 Bytes compartidos desde H'170' hasta H'17F'
CBLOCK H'110'
ENDC

;BANCO 3 son 80 BYTES, desde H'190' hasta H'1EF'
;y luego vienen 16 Bytes compartidos desde H'1F0' hasta H'1FF'
CBLOCK H'190'
ENDC
;

;PROGRAMA DE TESTEO DE PICS INVIERTE EL ESTADO DE PORTB
;SEGUN SE PULSE RA0 (TIENE UN DELAY DE 100ms POR LO MALO DE LOS PULSADORES)
;org 0x000
; goto INICIA



    org 0x00
    NOP
    NOP
    GOTO CONFIGURACION
    org 0x04
    GOTO INTERRUPCION


CONFIGURACION       ; Aca configuro todo (puertos, timers, inicializo todas las  variables a 00 o el valor que tengan, cargo valor de timer y activo interrupciones al ultimo )

BANKSEL PORTA ; SELECT BANK OF PORTA
CLRF PORTA ; INITIALIZE PORTA BY
BANKSEL OSCCON
MOVLW 0X60  ;RELOJ INTERNO 4MHZ
MOVWF OSCCON
BANKSEL ANSEL ; SELECT BANK OF ADCON1
MOVLW 0X00  ; CONFIGURE ALL PINS
MOVWF ANSEL ; AS DIGITAL INPUTS
BANKSEL TRISA
MOVLW 0X0F  ; VALUE USED TO
MOVWF TRISA ; SET RA<7:0> AS INPUTS
BANKSEL TRISB
            CLRF TRISB
BANKSEL PORTA
            CLRF INTCON
            CALL    TIMER
            BANKSEL DECENAS
            MOVLW   .78
            MOVWF   CONTADOR_DISPLAYS
            CLRF    PORTB
            MOVLW   .0
            MOVWF   DECENAS
            MOVLW   .0
            MOVWF   UNIDADES
            CLRF    FLAG

   BANKSEL   OSCCON
   MOVLW   0X60   ;RELOJ INTERNO 4MHZ
   MOVWF   OSCCON
  BANKSEL PORTA       ; BANK0
MOVLW     B'00001111'       ;entradas y salidas
MOVWF     PORTA
MOVLW     B'11000000'
MOVWF     PORTB

BANKSEL TRISA       ; BANK1
MOVLW     B'00001111'       ;entradas y salidas
MOVWF     TRISA
MOVLW     B'11100100'
MOVWF     TRISB
MOVLW     B'00000000'
MOVWF     ANSEL         ; PORTA INPUTS = DIGITAL NOT ANALOG
;
; BAUD RATE SETTINGS
;
;  BAUD VALUES WITH BRGH = 0
;  ((20000000/9600)/64)-1 = 32
;    MOVLW     D'207'    ;  1200 BAUD @ 16 MHZ FOSC +0.16 ERR
;    MOVLW     D'103'          ;  2400 BAUD @ 16 MHZ FOSC +0.16 ERR
;    MOVLW     D'25'           ;  9600 BAUD @ 16 MHZ FOSC +0.16 ERR
;    MOVLW     D'12'           ; 19200 BAUD @ 16 MHZ FOSC +0.16 ERR
;    MOVLW     D'255'          ;  1200 BAUD @ 20 MHZ FOSC +1.73 ERR
;    MOVLW     D'129'          ;  2400 BAUD @ 20 MHZ FOSC +0.16 ERR
;    MOVLW     D'32'          ;  9600 BAUD @ 20 MHZ FOSC -1.36 ERR
;    MOVLW     D'15'          ; 19200 BAUD @ 20 MHZ FOSC +1.73 ERR

;  BAUD VALUES WITH BRGH = 1
;  ((20000000/9600)/16)-1 = 32
MOVLW     D'25'         ;  9600 BAUD @ 20 MHZ FOSC +0.16 ERR
MOVWF     SPBRG
MOVLW     B'00100100'    ; BRGH = 1
MOVWF     TXSTA           ; ENABLE ASYNC TRANSMISSION, SET BRGH
BANKSEL   RCSTA       ; BANK0
MOVLW     B'10010000'
MOVWF     RCSTA          ; ENABLE ASYNC RECEPTION
MOVF RCREG,W
MOVF RCREG,W
MOVF RCREG,W           ; FLUSH RECEIVE BUFFER

TIMER
            BANKSEL OPTION_REG
            MOVLW       B'00000110'
            MOVWF       OPTION_REG
            BCF INTCON,6             ;INT EXTERNAS
            BSF         INTCON,5              ;TMR0
            BCF         INTCON,4               ;INT RB0
            BCF         INTCON,3               ;INT RB4-RB7
            BCF         INTCON,1            ;BANDERA RB0
            BCF         INTCON,0         ;BANDERA RB4-RB7
            BCF         INTCON,2           ;BANDERA TMROIF
            BSF INTCON,7           ;INT GENERAL
            MOVLW D'217'
            BANKSEL     TMR0
            MOVWF TMR0
            RETURN


    GOTO MAIN


;******COMIENZO DE INTERRUPCION********

INTERRUPCION
;guardo contexto
    SWAPF    STATUS, W       ;Swap status to be saved into W
CLRF     STATUS          ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF    STATUS_TEMP     ;Save status to bank zero STATUS_TEMP register
MOVF     PCLATH, W       ;Only required if using page 1
MOVWF    PCLATH_TEMP     ;Save PCLATH into W
CLRF     PCLATH          ;Page zero, regardless of current page
    CLRF     PORTB
;--------------------------------------------------------------------------
BTFSC PIR1,RCIF ; Pregunto por si llego algo en la UART
    GOTO int_uart
BTFSS INTCON,TMR0IF ; Pregunto si la interrupcion fue del timer
GOTO salir_int ; Aca podria seguir agregando por eso pregunte arriba, y puse el GOTO, sino no hacia flata pregunta si era lo unico 2 que estaba activo
DECF  CONTADOR_DISPLAYS ;Implemento contador por si es muy corta la interrupcion y para hacerla mas larga ( es decir contar la cantidad de interrupciones )
BTFSS STATUS,Z
GOTO salir_int
BSF    FLAG,1 ; mi flag al pasar X veces por aca habilitando que se muestre
MOVLW .217 ; Recargo mi temporizador
MOVWF TMR0
MOVLW .78 ; Recargo mi contador
MOVWF CONTADOR_DISPLAYS
BCF INTCON,TMR0IF
GOTO salir_int

int_uart

BSF FLAG,0 ; mi flag de que llego algo por la UART
        MOVF RCREG ; Limpio el buffer de lectura
        MOVF RCREG ; Limpio el buffer de lectura
        MOVF RCREG ; Limpio el buffer de lectura, 3 por que es posible tener 2 en la FIFO + 1 en el shift register, al vaciar la FIFO se pone a 0 RCIF

salir_int
;devuelvo el contexto------------------------------------
    BCF      INTCON,TMR0IF
    MOVLW    .217
    MOVWF    TMR0
    MOVF     PCLATH_TEMP, W ;Restore PCLATH;
    MOVWF    PCLATH         ;Move W into PCLATH
    SWAPF    STATUS_TEMP, W ;Swap STATUS_TEMP register into W
                                    ;(sets bank to original state)
MOVWF    STATUS         ;Move W into STATUS register
SWAPF    W_TEMP, F ;Swap W_TEMP
SWAPF    W_TEMP, W      ;Swap W_TEMP into W
RETFIE

;******FIN DE INTERRUPCION********

;******COMIENZO DE PROGRAMA PRINCIPAL********

MAIN
CALL TOMAR_DATOS
CALL ENVIAR
CALL MOSTRAR_DISPLAYS
CALL ANIMACION
GOTO MAIN
;-------------------------------------------------------------------------------
       ; *************** Toma de datos y conversion a BCD ********************
;
; Registro de entrada: PORTA 3:0
; Registros de salida: dato original: DATO_A_ENVIAR , BCD: UNIDADES, DECENAS

TOMAR_DATOS

        BANKSEL PORTA
    MOVF PORTA,W ;supongo que esta en el porta el dato en el nibble bajo
        ANDLW 0x0F              ; solo dejo pasar el nibble bajo
    MOVWF DATO_A_ENVIAR   ; lo guardo en DATO_A_ENVIAR asi las demas subrutinas pueden usar el valor original que se tomo
        addlw    .256-.10       ; Procedo a pasarlo a BCD
        BTFSC    STATUS,C
        addlw    .6
        addlw    -(.256-.10)   ; Final del paso a BCD
        MOVWF UNIDADES     ; Utilizo al registro como un registro temporal.  UNIDADES = decenas:unidades
    SWAPF  UNIDADES,W  ; Cambio de lugar los nibbles    W = unidades:decenas
        ANDLW 0x0F             ; Elimino las unidades en W, me quedan las decenas ... W = 0:decenas
        MOVWF DECENAS       ; Guardo las decenas
        MOVF UNIDADES,W        ; Vuelvo a cargar todo el resultado del BCD -> decenas:unidades
        ANDLW 0x0F             ; Elimino las decenas   W = 0:unidades
        MOVWF UNIDADES     ; Guardo las unidades
        RETURN


; *************** Realiza multiplexado en los displays ********************
;
; Registro de entrada: FLAG,2 (flag de displays) , FLAG,1(flag de tiempo), DECENAS y UNIDADES
; Registros de salida: PORTB 3:0 bits BCD al 4511, PORTB,6 catodo_unidades y PORTB,7 catodo_decenas


MOSTRAR_DISPLAYS
    BANKSEL PORTA
BTFSC FLAG,2    ; Con este indico que display estoy mostrando, si esta en 1 significa que es mi 2do display
GOTO  display2

display1
BTFSS FLAG,1    ; Espero hasta que pase el tiempo se ejecute la interrupcion y me habilite la flag sino sigo saliendo
RETURN
BCF  PORTB,6    ; apago catodo_unidades
MOVF DECENAS,W
MOVWF PORTB ; Aca supongo que todo lo demas que no es dato esta en 0
BSF  PORTB,7      ; enciendo mi diplay de decenas
BSF FLAG,2      ; Activo el flag para que pase al otro display ( 2 )
    BCF FLAG,1          ; Desactivo el flag del timer
RETURN

display2
BTFSS FLAG,1
RETURN
BCF  PORTB,7      ; apago catodo_decenas
MOVF UNIDADES,W
MOVWF PORTB ; Aca supongo que todo lo demas que no es dato esta en 0
BSF PORTB,6         ; activo catodo_unidades
BCF FLAG,2      ; Activo el flag para que pase al otro display ( 1 )
    BCF FLAG,1          ; Desactivo el flag del timer
RETURN


; *************** Envia datos por la UART ********************
;
; Registro de entrada: DATOS_A_ENVIAR
; Registros de salida: Ninguno


ENVIAR

                                ;Aca me fijo si es de 0 a 9 asi le sumo 0x30 ('0') o si es una A a F asi le sumo una 'A' a DATO_A_ENVIAR
    BANKSEL TXSTA
    BTFSS TXSTA,TRMT            ; Pregunto por si esta libre el USART para mandar otro dato
    RETURN
    BANKSEL PORTA
    MOVF    DATO_A_ENVIAR,W
    ANDLW    0x0F ; Limito a 15 aunque ya lo hice en tomar_datos
    SUBLW   .9
    BTFSC   STATUS,C ; Si esta en 0 es negativo, es decir 9 - DATO_A_ENVIAR = negativo o 9 < DATO_A_ENVIAR  , apartir de 10 se pondria C = 1
    GOTO    SUMO30

SUMOA      ; el dato no es cero por lo tanto sumo A
    MOVF    DATO_A_ENVIAR,W
    ADDLW   .55 ; 'A' - 10
    MOVWF   TXREG      ;Cargo el valor asi se envia
    RETURN

SUMO30        ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
    MOVF    DATO_A_ENVIAR,W
    ADDLW   0x30
    MOVWF   TXREG      ;Cargo el valor asi se envia
    RETURN



; *************** Enia datos por la UART ********************
;
; Registro de entrada: FLAG,1 (flag de tiempo) y FLAG,0 (indicador de que algo llego)
; Registros de salida: Ninguno


ANIMACION

    BTFSS FLAG,0 ;Pregunto si algo llego, sino no hago nada.
    RETURN
    CLRF     FLAG
            MOVLW    .0
            MOVWF    UNIDADES
            MOVLW    .0
            MOVWF    DECENAS
            GOTO     MULTI

MULTI

            BTFSS    CONTADOR_DISPLAYS,0
            GOTO     DISP2
            GOTO     DISP1

DISP1


            BANKSEL UNIDADES
            MOVF    UNIDADES,0
            BANKSEL PORTB
            MOVWF   PORTB

            MOVLW   B'00000010'
            MOVWF   CONTADOR_DISPLAYS
            BSF     PORTB,7
            RETURN
DISP2
            BANKSEL DECENAS
            MOVF    DECENAS,0
            BANKSEL PORTB
            MOVWF   PORTB
            MOVLW   B'00000001'
            MOVWF   CONTADOR_DISPLAYS
            BSF     PORTB,6
            BCF FLAG,0
    RETURN




 END

Sinceramente te pido disculpas  :cry: assembler es el lenguaje que más me va a costar aprender bien y para esta materia que me tengo que sacar sabiendo el lenguaje sino a fin de año no tengo mi título.

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re: BIN a BCD-MULTIPLEXADO-USART(comunicación serial)-Uso de retardos e interrup.
« Respuesta #3 en: 16 de Abril de 2015, 16:30:53 »
Que tal Fedextrem,

Mira con todo respeto, pero creo que necesitas comenzar con un primer paso, luego otro y así sucesivamente. Quieres abarcar todo de un solo tiro y pues esa no es la manera correcta.

Mi recomendación es que primero hagas lo de los displays, es decir que mustres cualquier número, para que parendas la técnica del multiplexado.
Luego puedes continuar leyendo el dipswitch, realizar la conversion binario a BCD y finalmente mostrarlo en los displays. Despues realizar la rutina de destello.
Tercer paso seria trabajar sobre la interface serial. Enviando y recibiendo datos entre la PC y el micro.
El paso final seria colocar todo junto para obtener el resultado deseado.

Aqui estamos para ayudarte, pero no para hacer tu tarea.
Espero no lo tomes mal.

Elreypic.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: BIN a BCD-MULTIPLEXADO-USART(comunicación serial)-Uso de retardos e interrup.
« Respuesta #4 en: 16 de Abril de 2015, 22:22:48 »
El mensaje/error que me tira dice así: [PIC16 CORE] PC=0x0053. Stack underflow executing RETURN instruction.

Te lo voy a explicar en algunos ejemplos cual es tu problema. Pero antes necesitas saber como es que funciona el PIC.
El PIC ejecuta las instrucciones una detras de otra, las unicas instrucciones capaces de quebrar esto son aquellas que proveen un salto, tales como BTFSS/BTFSC , DECFSZ/INCFSZ , GOTO/CALL
Cada una funciona de distinta manera. Como sabe el micro que instruccion esta ejecutando ? Bueno el micro tiene un registro que se llama PC ( contador de programa - tiene otro nombre PCL ) Ahi es donde va guardando la direccion de la instruccion a ejecutarse.
Esas instrucciones modifican el PC, pero hay algunas instrucciones como el CALL que guardan ese valor en una pila ( stack ) para saber de donde se lo llamo, Asi cuando se ejecuta el RETURN se saca esto del stack y se pone nuevamente en el PC

Código: ASM
  1. MAIN
  2.      NOP                               ;Intruccion 1
  3.      CALL ALGO                      ;Instruccion 2
  4.      SUBLW 0x01                   ; Instruccion 3
  5.  
  6. ALGO
  7.      SUBLW 0x10                   ;Instruccion 4
  8.      RETURN                ;Instruccion 5

Este este ejemplo es algo muy parecido a tu programa donde tenes tu error, si seguis la logica secuencial, comenzarias por la instruccion 1, luego se ejecutaria la 2, al ejecutarse la 2 se guarda en el stack la proxima direccion (instruccion 3) y salta a la instruccion 4, ejecuta la 5 y esta saca la direccion de la pila y la pone en el PC, por lo cual la proxima instruccion a ejecutar es la 3, pero ahi no termina tu main, sino que sigue ejecutando instrucciones, sigue con la 4 y luego la 5, pero cuando llego a la 5 ocurrio un problema, que es el que tenes, Ya antes se habia ejecutado un CALL - RETURN, por lo tanto se puso algo en la pila y se saco. y ahora estas haciendo un RETURN pero sin un CALL, entonces la pila esta VACIA, no tiene ningun lugar a "volver" y se libera ese error

Mira si le agrego un GOTO a mi main haciendo un bucle cerrado

Código: ASM
  1. MAIN
  2.      NOP                               ;Intruccion 1
  3.      CALL ALGO                      ;Instruccion 2
  4.      SUBLW 0x01                   ; Instruccion 3
  5.      GOTO  MAIN                    ; Instruccion 4
  6.  
  7. ALGO
  8.      SUBLW 0x10                   ;Instruccion 5
  9.      RETURN                ;Instruccion 6

Despues de la instruccion 3, ahora la instruccion 4 es el GOTO MAIN, el cual me lo vuelve al comienzo, haciendo que para entrar a ALGO solo pueda hacerlo con el CALL.

El stack son como 8 registros puestos uno encima de otro y se van llenando desde el fondo hasta arriba, siempre se saca la ultima cosa que se puso, es decir lo que esta mas arriba de todo

Puede ocurrir 2 cosas, cuando intentas meter mas cosas de las que puede contener (overrflow) como por ejemplo si se ejecutan muchos CALL y no se ejecutan la misma cantidad de RETURN, o cuando se quita mas de lo que se puso (underflow) como en tu caso que se ejecutan mas RETURN que CALL, Esto lleva a una conclusion simple como que si existe un CALL deberia existir un RETURN, aun asi no es suficiente para evitar errores, si te fijas en mi primer ejemplo ocurre  eso pero no se tomaron las precauciones necesarias para que la subrutina no se ejecute 1 sola ves.

Sinceramente te pido disculpas  :cry: assembler es el lenguaje que más me va a costar aprender bien y para esta materia que me tengo que sacar sabiendo el lenguaje sino a fin de año no tengo mi título.

No es dificil, lo que si tenes que tener en cuenta mucho como funciona el microcontrolador, esto es asi para todo sea microcontrolador o microprocesador.
Bien como dice elreypic2 es comenzar haciendo programas simples.

Una de mis ideas cuando comenzaste con esto fue hacer esto:

Código: ASM
  1. MAIN
  2.         CALL TOMAR_DATOS
  3.         CALL ENVIAR
  4.         CALL MOSTRAR_DISPLAYS
  5.         CALL ANIMACION
  6.         GOTO MAIN

Parece que la estoy complicando no?, pero en realidad lo que estoy haciendo es dividir mi programa en programitas simples, entonces lo que podrias hacer es tratar de crear una funcion para cada una de las tareas y verificar que funcione correctamente. Una ves que tenes todas las tareas hechas tratar de juntarlas poco a poco y ver que funcione todo el conjunto de las mismas.

Por ejemplo en mi codigo habia realizado que TOMAR_DATOS tomara el dato del PORTA lo guardara en un registro y luego lo pasara a BCD, lo hice, lo simule en el MPLAB y funciono correctamente. Listo, ya tengo esa parte lista, segui con lo siguiente en la lista. y asi con todo.

Yo te puedo decir que hacen las instrucciones, en que te equivocaste, pero no voy a poder cambiar tu cabeza con respecto a la programacion. La unica forma que cambies la forma de pensar y entres a la programacion es haciendo ejemplos simples y si te equivocas, preguntas y te corrigen ver exactamente el por que de eso y no simplemente aceptarlo "por que es asi".
« Última modificación: 16 de Abril de 2015, 22:36:47 por KILLERJC »

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Re: BIN a BCD-MULTIPLEXADO-USART(comunicación serial)-Uso de retardos e interrup.
« Respuesta #5 en: 19 de Abril de 2015, 12:45:30 »
Tienen razón, me puse a hacer los programas de a poco y juntandolos, me ayudo bastante pero me surge un problema cuando muestro el dato en los displays, lo cual me lo muestra como un parpadeo y desaparece, después de un rato otra vez y así sucesivamente en vez de mostrarlo todo el tiempo.
Acá el código de muestra:
Código: [Seleccionar]
MOSTRAR_DISPLAYS
    BANKSEL PORTA
BTFSC FLAG,2    ; Con este indico que display estoy mostrando, si esta en 1 significa que es mi 2do display
GOTO  display2

display1
BTFSS FLAG,1    ; Espero hasta que pase el tiempo se ejecute la interrupcion y me habilite la flag sino sigo saliendo
RETURN
BCF  PORTB,6    ; apago catodo_unidades
MOVF DECENAS,W
MOVWF PORTB ; Aca supongo que todo lo demas que no es dato esta en 0
BSF  PORTB,7      ; Prendo mi diplay de decenas
BSF FLAG,2      ; Activo el flag para que pase al otro display ( 2 )
    BCF FLAG,1          ; Desactivo el flag del timer
RETURN

display2
BTFSS FLAG,1
RETURN
BCF  PORTB,7      ; apago catodo_decenas
MOVF UNIDADES,W
MOVWF PORTB ; Aca supongo que todo lo demas que no es dato esta en 0
BSF PORTB,6         ; activo catodo_unidades
BCF FLAG,2      ; Activo el flag para que pase al otro display ( 1 )
    BCF FLAG,1          ; Desactivo el flag del timer
RETURN
Por ahora solo ese es mi problema porque hice solo la parte de cambiar de bin a bcd y anda, la parte de enviar por puerto serie también anda, también lo muestra pero no como necesito

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: BIN a BCD-MULTIPLEXADO-USART(comunicación serial)-Uso de retardos e interrup.
« Respuesta #6 en: 19 de Abril de 2015, 13:47:20 »
Ese codigo lo habia realizado yo.

El bit 2 de FLAG era solo para saber que display se activaba.
El bit 1 de FLAG se activaba cuando ocurria una interrupcion de un timer de esa forma El display iba a estar encendido hasta la proxima interrupcion, que es cuando cambia al otro display.

Si quisieras hacer funcionar ese codigo deberias de poner una interrupcion con un Timer o... de ultima crear un delay de unos 10/20ms por ejemplo, poner a 1 FLAG,1 y llamar a esa funcion.

Algo asi:

Código: Microchip Assembler
  1. MAIN
  2.       CALL DELAY_20MS
  3.       BSF  FLAG,1
  4.       CALL MOSTRAR_DISPLAYS
  5.       GOTO MAIN

Eso seria para probarlo pero NO para hacer el programa completo. Esto haria que estuviera mas tiempo prendido. Ya que cuando sale de esta funcion queda encendido un displays y recien cuando vuelve a entrar de nuevo es cuando lo apaga y vuelve a encencer el otro.
Lo que no se como lo interpretara el PROTEUS a eso.

EDIT:

Ahora que lo veo podria haber sacado el FLAG,1 afuera. y que se pregunte una sola ves y no dos veces.
Tambien podria haber omitido completamente FLAG,2, haciendo aun mucho mas corta esa parte. Quedando como lo pongo abajo
Pero bueno por ahora dejalo asi o si queres copia esa que solo necesita 1 bit como flag y llsto.


Código: Microchip Assembler
  1. MOSTRAR_DISPLAYS
  2.         BANKSEL PORTA
  3.         BTFSS FLAG,1            ; Espero hasta que pase el tiempo se ejecute la interrupcion y me habilite la flag sino sigo saliendo
  4.         RETURN
  5.         BCF FLAG,1                 ; Desactivo el flag del timer
  6.         BTFSC PORTB,7           ; Con este indico que display estoy mostrando, si esta en 1 significa que es mi 2do display
  7.         GOTO  display2
  8.  
  9. display1
  10.         BCF  PORTB,6            ; apago catodo_unidades
  11.         MOVF DECENAS,W
  12.         MOVWF PORTB             ; Aca supongo que todo lo demas que no es dato esta en 0
  13.         BSF  PORTB,7            ; Prendo mi diplay de decenas
  14.         RETURN
  15.  
  16. display2
  17.         BCF  PORTB,7            ; apago catodo_decenas
  18.         MOVF UNIDADES,W
  19.         MOVWF PORTB             ; Aca supongo que todo lo demas que no es dato esta en 0
  20.         BSF PORTB,6         ; activo catodo_unidades
  21.         RETURN
« Última modificación: 19 de Abril de 2015, 13:56:45 por KILLERJC »


 

anything